diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml new file mode 100644 index 000000000..b1b31a476 --- /dev/null +++ b/.github/workflows/cla.yml @@ -0,0 +1,29 @@ +name: "DCO Assistant" +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened,closed,synchronize] + +permissions: + actions: write + contents: write + pull-requests: write + statuses: write + +jobs: + DCOAssistant: + runs-on: ubuntu-latest + steps: + - name: "DCO Assistant" + if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the DCO Document and I hereby sign the DCO') || github.event_name == 'pull_request_target' + uses: contributor-assistant/github-action@v2.3.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + path-to-signatures: '.github/dco/signatures.json' + path-to-document: 'https://developercertificate.org/' + branch: 'dco-do-not-remove' + allowlist: user1,bot* + use-dco-flag: true + custom-notsigned-prcomment: '
Thank you for your submission. Before we can accept your contribution, please sign our [Developer Certificate of Origin](https://developercertificate.org) by posting a comment with the content exactly as below.
' diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/Dockerfile b/DGLPyTorch/DrugDiscovery/SE3Transformer/Dockerfile index c9d19da03..5f3f2c4fd 100644 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/Dockerfile +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/Dockerfile @@ -24,7 +24,7 @@ # run docker daemon with --default-runtime=nvidia for GPU detection during build # multistage build for DGL with CUDA and FP16 -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.08-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:23.01-py3 FROM ${FROM_IMAGE_NAME} AS dgl_builder @@ -33,7 +33,7 @@ RUN apt-get update \ && apt-get install -y git build-essential python3-dev make cmake \ && rm -rf /var/lib/apt/lists/* WORKDIR /dgl -RUN git clone --branch 0.9.0 --recurse-submodules --depth 1 https://github.com/dmlc/dgl.git . +RUN git clone --branch 1.0.0 --recurse-submodules --depth 1 https://github.com/dmlc/dgl.git . WORKDIR build RUN export NCCL_ROOT=/usr \ && cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release \ diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/README.md b/DGLPyTorch/DrugDiscovery/SE3Transformer/README.md index ea0265038..60e95d65d 100644 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/README.md +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/README.md @@ -252,9 +252,9 @@ The following section lists the requirements that you need to meet in order to s ### Requirements -This repository contains a Dockerfile which extends the PyTorch 21.07 NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: +This repository contains a Dockerfile which extends the PyTorch 23.01 NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: - [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -- PyTorch 21.07+ NGC container +- PyTorch 23.01+ NGC container - Supported GPUs: - [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) - [NVIDIA Turing architecture](https://www.nvidia.com/en-us/design-visualization/technologies/turing-architecture/) @@ -285,12 +285,12 @@ To train your model using mixed or TF32 precision with Tensor Cores or FP32, per 3. Start an interactive session in the NGC container to run training/inference. ``` mkdir -p results - docker run -it --runtime=nvidia --shm-size=8g --ulimit memlock=-1 --ulimit stack=67108864 --rm -v ${PWD}/results:/results se3-transformer:latest + docker run -it --runtime=nvidia --shm-size=8g --ulimit memlock=-1 --ulimit stack=67108864 --rm -v ${PWD}/results:/workspace/se3-transformer/results se3-transformer:latest ``` 4. Start training. ``` - bash scripts/train.sh + bash scripts/train.sh # or scripts/train_multi_gpu.sh ``` 5. Start inference/predictions. @@ -474,7 +474,7 @@ The following sections provide details on how we achieved our performance and ac ##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `scripts/train.sh` training script in the PyTorch 21.07 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. +Our results were obtained by running the `scripts/train.sh` and `scripts/train_multi_gpu.sh` training scripts in the PyTorch 23.01 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. | GPUs | Batch size / GPU | Absolute error - TF32 | Absolute error - mixed precision | Time to train - TF32 | Time to train - mixed precision | Time to train speedup (mixed precision to TF32) | |:----:|:----------------:|:---------------------:|:--------------------------------:|:--------------------:|:-------------------------------:|:-----------------------------------------------:| @@ -484,7 +484,7 @@ Our results were obtained by running the `scripts/train.sh` training script in t ##### Training accuracy: NVIDIA DGX-1 (8x V100 16GB) -Our results were obtained by running the `scripts/train.sh` training script in the PyTorch 21.07 NGC container on NVIDIA DGX-1 with (8x V100 16GB) GPUs. +Our results were obtained by running the `scripts/train.sh` and `scripts/train_multi_gpu.sh` training scripts in the PyTorch 23.01 NGC container on NVIDIA DGX-1 with (8x V100 16GB) GPUs. | GPUs | Batch size / GPU | Absolute error - FP32 | Absolute error - mixed precision | Time to train - FP32 | Time to train - mixed precision | Time to train speedup (mixed precision to FP32) | |:----:|:----------------:|:---------------------:|:--------------------------------:|:--------------------:|:-------------------------------:|:-----------------------------------------------:| @@ -497,14 +497,14 @@ Our results were obtained by running the `scripts/train.sh` training script in t ##### Training performance: NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `scripts/benchmark_train.sh` and `scripts/benchmark_train_multi_gpu.sh` benchmarking scripts in the PyTorch 21.07 NGC container on NVIDIA DGX A100 with 8x A100 80GB GPUs. Performance numbers (in molecules per millisecond) were averaged over five entire training epochs after a warmup epoch. +Our results were obtained by running the `scripts/benchmark_train.sh` and `scripts/benchmark_train_multi_gpu.sh` benchmarking scripts in the PyTorch 23.01 NGC container on NVIDIA DGX A100 with 8x A100 80GB GPUs. Performance numbers (in molecules per millisecond) were averaged over five entire training epochs after a warmup epoch. | GPUs | Batch size / GPU | Throughput - TF32 [mol/ms] | Throughput - mixed precision [mol/ms] | Throughput speedup (mixed precision - TF32) | Weak scaling - TF32 | Weak scaling - mixed precision | |:----------------:|:-------------------:|:--------------------------:|:-------------------------------------:|:-------------------------------------------:|:-------------------:|:------------------------------:| -| 1 | 240 | 2.61 | 3.35 | 1.28x | | | -| 1 | 120 | 1.94 | 2.07 | 1.07x | | | -| 8 | 240 | 18.80 | 23.90 | 1.27x | 7.20 | 7.13 | -| 8 | 120 | 14.10 | 14.52 | 1.03x | 7.27 | 7.01 | +| 1 | 240 | 2.59 | 3.23 | 1.25x | | | +| 1 | 120 | 1.89 | 1.89 | 1.00x | | | +| 8 | 240 | 18.38 | 21.42 | 1.17x | 7.09 | 6.63 | +| 8 | 120 | 13.23 | 13.23 | 1.00x | 7.00 | 7.00 | To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). @@ -512,14 +512,14 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic ##### Training performance: NVIDIA DGX-1 (8x V100 16GB) -Our results were obtained by running the `scripts/benchmark_train.sh` and `scripts/benchmark_train_multi_gpu.sh` benchmarking scripts in the PyTorch 21.07 NGC container on NVIDIA DGX-1 with 8x V100 16GB GPUs. Performance numbers (in molecules per millisecond) were averaged over five entire training epochs after a warmup epoch. +Our results were obtained by running the `scripts/benchmark_train.sh` and `scripts/benchmark_train_multi_gpu.sh` benchmarking scripts in the PyTorch 23.01 NGC container on NVIDIA DGX-1 with 8x V100 16GB GPUs. Performance numbers (in molecules per millisecond) were averaged over five entire training epochs after a warmup epoch. | GPUs | Batch size / GPU | Throughput - FP32 [mol/ms] | Throughput - mixed precision [mol/ms] | Throughput speedup (FP32 - mixed precision) | Weak scaling - FP32 | Weak scaling - mixed precision | |:----------------:|:--------------------:|:--------------------------:|:--------------------------------------:|:-------------------------------------------:|:-------------------:|:------------------------------:| -| 1 | 240 | 1.33 | 2.12 | 1.59x | | | -| 1 | 120 | 1.11 | 1.45 | 1.31x | | | -| 8 | 240 | 9.32 | 13.40 | 1.44x | 7.01 | 6.32 | -| 8 | 120 | 6.90 | 8.39 | 1.22x | 6.21 | 5.79 | +| 1 | 240 | 1.23 | 1.91 | 1.55x | | | +| 1 | 120 | 1.01 | 1.23 | 1.22x | | | +| 8 | 240 | 8.44 | 11.28 | 1.34x | 6.8 | 5.90 | +| 8 | 120 | 6.06 | 7.36 | 1.21x | 6.00 | 5.98 | To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). @@ -530,23 +530,23 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic ##### Inference performance: NVIDIA DGX A100 (1x A100 80GB) -Our results were obtained by running the `scripts/benchmark_inference.sh` inferencing benchmarking script in the PyTorch 21.07 NGC container on NVIDIA DGX A100 with 1x A100 80GB GPU. +Our results were obtained by running the `scripts/benchmark_inference.sh` inferencing benchmarking script in the PyTorch 23.01 NGC container on NVIDIA DGX A100 with 1x A100 80GB GPU. AMP | Batch size | Throughput Avg [mol/ms] | Latency Avg [ms] | Latency 90% [ms] | Latency 95% [ms] | Latency 99% [ms] | |:----------:|:-----------------------:|:----------------:|:----------------:|:----------------:|:----------------:| -| 1600 | 13.54 | 121.44 | 118.07 | 119.00 | 366.64 | -| 800 | 12.63 | 64.11 | 63.78 | 64.37 | 68.19 | -| 400 | 10.65 | 37.97 | 39.02 | 39.67 | 42.87 | +| 1600 | 9.71 | 175.2 | 190.2 | 191.8 | 432.4 | +| 800 | 7.90 | 114.5 | 134.3 | 135.8 | 140.2 | +| 400 | 7.18 | 75.49 | 108.6 | 109.6 | 113.2 | TF32 | Batch size | Throughput Avg [mol/ms] | Latency Avg [ms] | Latency 90% [ms] | Latency 95% [ms] | Latency 99% [ms] | |:----------:|:-----------------------:|:----------------:|:----------------:|:----------------:|:----------------:| -| 1600 | 8.97 | 180.85 | 178.31 | 178.92 | 375.33 | -| 800 | 8.86 | 90.76 | 90.77 | 91.11 | 92.96 | -| 400 | 8.49 | 47.42 | 47.65 | 48.15 | 50.74 | +| 1600 | 8.19 | 198.2 | 206.8 | 208.5 | 377.0 | +| 800 | 7.56 | 107.5 | 119.6 | 120.5 | 125.7 | +| 400 | 6.97 | 59.8 | 75.1 | 75.7 | 81.3 | To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). @@ -554,23 +554,23 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic ##### Inference performance: NVIDIA DGX-1 (1x V100 16GB) -Our results were obtained by running the `scripts/benchmark_inference.sh` inferencing benchmarking script in the PyTorch 21.07 NGC container on NVIDIA DGX-1 with 1x V100 16GB GPU. +Our results were obtained by running the `scripts/benchmark_inference.sh` inferencing benchmarking script in the PyTorch 23.01 NGC container on NVIDIA DGX-1 with 1x V100 16GB GPU. AMP | Batch size | Throughput Avg [mol/ms] | Latency Avg [ms] | Latency 90% [ms] | Latency 95% [ms] | Latency 99% [ms] | |:----------:|:-----------------------:|:----------------:|:----------------:|:----------------:|:----------------:| -| 1600 | 6.59 | 248.02 | 242.11 | 242.62 | 674.60 | -| 800 | 6.38 | 126.49 | 125.96 | 126.31 | 127.72 | -| 400 | 5.90 | 68.24 | 68.53 | 69.02 | 70.87 | +| 1600 | 5.39 | 306.6 | 321.2 | 324.9 | 819.1 | +| 800 | 4.67 | 179.8 | 201.5 | 203.8 | 213.3 | +| 400 | 4.25 | 108.2 | 142.0 | 143.0 | 149.0 | FP32 | Batch size | Throughput Avg [mol/ms] | Latency Avg [ms] | Latency 90% [ms] | Latency 95% [ms] | Latency 99% [ms] | |:----------:|:-----------------------:|:----------------:|:----------------:|:----------------:|:----------------:| -| 1600 | 3.33 | 482.20 | 483.50 | 485.28 | 754.84 | -| 800 | 3.35 | 239.09 | 242.21 | 243.13 | 244.91 | -| 400 | 3.27 | 122.68 | 123.60 | 124.18 | 125.85 | +| 1600 | 3.14 | 510.9 | 518.83 | 521.1 | 808.0 | +| 800 | 3.10 | 258.7 | 269.4 | 271.1 | 278.9 | +| 400 | 2.93 | 137.3 | 147.5 | 148.8 | 151.7 | To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). @@ -580,6 +580,10 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic ### Changelog +February 2023: +- Upgraded base container +- Fixed benchmarking code + August 2022: - Slight performance improvements - Upgraded base container @@ -604,3 +608,4 @@ August 2021 ### Known issues If you encounter `OSError: [Errno 12] Cannot allocate memory` during the Dataloader iterator creation (more precisely during the `fork()`, this is most likely due to the use of the `--precompute_bases` flag. If you cannot add more RAM or Swap to your machine, it is recommended to turn off bases precomputation by removing the `--precompute_bases` flag or using `--precompute_bases false`. + diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train.sh b/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train.sh index 5bcd707a9..fa7d89786 100755 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train.sh +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train.sh @@ -8,7 +8,7 @@ AMP=${2:-true} CUDA_VISIBLE_DEVICES=0 python -m se3_transformer.runtime.training \ --amp "$AMP" \ --batch_size "$BATCH_SIZE" \ - --epochs 6 \ + --epochs 16 \ --use_layer_norm \ --norm \ --save_ckpt_path model_qm9.pth \ diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train_multi_gpu.sh b/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train_multi_gpu.sh index fc371490b..632dc04e9 100755 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train_multi_gpu.sh +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/scripts/benchmark_train_multi_gpu.sh @@ -9,7 +9,7 @@ python -m torch.distributed.run --nnodes=1 --nproc_per_node=gpu --max_restarts 0 se3_transformer.runtime.training \ --amp "$AMP" \ --batch_size "$BATCH_SIZE" \ - --epochs 6 \ + --epochs 16 \ --use_layer_norm \ --norm \ --save_ckpt_path model_qm9.pth \ diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/convolution.py b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/convolution.py index fc46961a8..69d7b6f02 100644 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/convolution.py +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/convolution.py @@ -113,7 +113,7 @@ def __init__( nn.Linear(mid_dim, num_freq * channels_in * channels_out, bias=False) ] - self.net = nn.Sequential(*[m for m in modules if m is not None]) + self.net = torch.jit.script(nn.Sequential(*[m for m in modules if m is not None])) def forward(self, features: Tensor) -> Tensor: return self.net(features) diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/norm.py b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/norm.py index d1dd1a7da..ba83aee06 100644 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/norm.py +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/model/layers/norm.py @@ -32,6 +32,15 @@ from se3_transformer.model.fiber import Fiber +@torch.jit.script +def clamped_norm(x, clamp: float): + return x.norm(p=2, dim=-1, keepdim=True).clamp(min=clamp) + +@torch.jit.script +def rescale(x, norm, new_norm): + return x / norm * new_norm + + class NormSE3(nn.Module): """ Norm-based SE(3)-equivariant nonlinearity. @@ -63,7 +72,7 @@ def forward(self, features: Dict[str, Tensor], *args, **kwargs) -> Dict[str, Ten output = {} if hasattr(self, 'group_norm'): # Compute per-degree norms of features - norms = [features[str(d)].norm(dim=-1, keepdim=True).clamp(min=self.NORM_CLAMP) + norms = [clamped_norm(features[str(d)], self.NORM_CLAMP) for d in self.fiber.degrees] fused_norms = torch.cat(norms, dim=-2) @@ -73,11 +82,11 @@ def forward(self, features: Dict[str, Tensor], *args, **kwargs) -> Dict[str, Ten # Scale features to the new norms for norm, new_norm, d in zip(norms, new_norms, self.fiber.degrees): - output[str(d)] = features[str(d)] / norm * new_norm + output[str(d)] = rescale(features[str(d)], norm, new_norm) else: for degree, feat in features.items(): - norm = feat.norm(dim=-1, keepdim=True).clamp(min=self.NORM_CLAMP) + norm = clamped_norm(feat, self.NORM_CLAMP) new_norm = self.nonlinearity(self.layer_norms[degree](norm.squeeze(-1)).unsqueeze(-1)) - output[degree] = new_norm * feat / norm + output[degree] = rescale(new_norm, feat, norm) return output diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/arguments.py b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/arguments.py index 2ae115e37..d16e1617c 100644 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/arguments.py +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/arguments.py @@ -33,7 +33,7 @@ paths = PARSER.add_argument_group('Paths') paths.add_argument('--data_dir', type=pathlib.Path, default=pathlib.Path('./data'), help='Directory where the data is located or should be downloaded') -paths.add_argument('--log_dir', type=pathlib.Path, default=pathlib.Path('/results'), +paths.add_argument('--log_dir', type=pathlib.Path, default=pathlib.Path('./results'), help='Directory where the results logs should be saved') paths.add_argument('--dllogger_name', type=str, default='dllogger_results.json', help='Name for the resulting DLLogger JSON file') diff --git a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/callbacks.py b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/callbacks.py index 112906a27..a7c5a9f48 100644 --- a/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/callbacks.py +++ b/DGLPyTorch/DrugDiscovery/SE3Transformer/se3_transformer/runtime/callbacks.py @@ -133,6 +133,7 @@ def __init__(self, logger, batch_size: int, warmup_epochs: int = 1, mode: str = def on_batch_start(self): if self.epoch >= self.warmup_epochs: + torch.cuda.synchronize() self.timestamps.append(time.time() * 1000.0) def _log_perf(self): @@ -153,7 +154,7 @@ def on_fit_end(self): def process_performance_stats(self): timestamps = np.asarray(self.timestamps) deltas = np.diff(timestamps) - throughput = (self.batch_size / deltas).mean() + throughput = self.batch_size / deltas.mean() stats = { f"throughput_{self.mode}": throughput, f"latency_{self.mode}_mean": deltas.mean(), diff --git a/JAX/Classification/README.md b/JAX/Classification/README.md new file mode 100644 index 000000000..83427543b --- /dev/null +++ b/JAX/Classification/README.md @@ -0,0 +1,46 @@ +# Image Classification + +Image classification is the task of categorizing an image into one of several predefined classes, often also giving a probability of the input belonging to a certain class. This task is crucial in understanding and analyzing images, and it comes quite effortlessly to human beings with our complex visual systems. Most powerful image classification models today are built using some form of Convolution Neural Networks (CNNs), which are also the backbone of many other tasks in Computer Vision. + +![What is Image Classification?](../../PyTorch/Classification/img/1_image-classification-figure-1.PNG) + +[Source](https://github.com/NVlabs/stylegan) + +In this overview, we will cover +- Types of image Classification +- How does it work? +- How is the performance evaluated? +- Use cases and applications +- Where to get started + +--- +## Types of image Classification +Image Classification can be broadly divided into either Binary or Multi-class problems depending on the number of categories. Binary image classification problems entail predicting one of two classes. An example of this would be to predict whether an image is that of a dog or not. A subtly different problem is that of single-class (one vs all) classification, where the goal is to recognize data from one class and reject all other. This is beneficial when there is an overabundance of data from one of the classes, also called a class imbalance. + +![Input and Outputs for Image Classification](../../PyTorch/Classification/img/1_image-classification-figure-2.PNG) + +In Multi-class classification problems, models categorize instances into one of three or more categories. Multi-class models often also return confidence scores (or probabilities) of an image belonging to each of the possible classes. This should not be confused with multi-label classification, where a model assigns multiple labels to an instance. + +--- +## How is the performance evaluated? +Image Classification performance is often reported as Top-1 or Top-5 scores. In top-1 score, classification is considered correct if the top predicted class (with the highest predicted probability) matches the true class for a given instance. In top-5, we check if one of the top 5 predictions matches the true class. The score is just the number of correct predictions divided by the total number of instances evaluated. + +--- +## Use cases and applications +### Categorizing Images in Large Visual Databases +Businesses with visual databases may accumulate large amounts of images with missing tags or meta-data. Unless there is an effective way to organize such images, they may not be much use at all. On the contrary, they may hog precious storage space. Automated image classification algorithms can classify such untagged images into predefined categories. Businesses can avoid expensive manual labor by employing automated image classification algorithms. + +A related task is that of Image Organization in smart devices like mobile phones. With Image Classification techniques, images and videos can be organized for improved accessibility. + +### Visual Search +Visual Search or Image-based search has risen to popularity over the recent years. Many prominent search engines already provide this feature where users can search for visual content similar to a provided image. This has many applications in the e-commerce and retail industry where users can take a snap and upload an image of a product they are interested in purchasing. This makes the shopping experience much more efficient for customers, and can increase sales for businesses. + + +### Healthcare +Medical Imaging is about creating visual images of internal body parts for clinical purposes. This includes health monitoring, medical diagnosis, treatment, and keeping organized records. Image Classification algorithms can play a crucial role in Medical Imaging by assisting medical professionals detect presence of illness and having consistency in clinical diagnosis. + +--- +## Getting started +NVIDIA provides examples for JAX models on [Rosetta](https://github.com/NVIDIA/JAX-Toolbox/tree/main/rosetta/rosetta/projects). These examples provide you with easy to consume and highly optimized scripts for both training and inferencing. The quick start guide at our GitHub repository will help you in setting up the environment using NGC Docker Images, download pre-trained models from NGC and adapt the model training and inference for your application/use-case. + +These models are tested and maintained by NVIDIA, leveraging mixed precision using tensor cores on our latest GPUs for faster training times while maintaining accuracy. diff --git a/JAX/Classification/ViT/README.md b/JAX/Classification/ViT/README.md new file mode 100644 index 000000000..32dff1c47 --- /dev/null +++ b/JAX/Classification/ViT/README.md @@ -0,0 +1,2 @@ +# ViT on GPUs +Please refer to [Rosetta ViT](https://github.com/NVIDIA/JAX-Toolbox/tree/main/rosetta/rosetta/projects/vit), NVIDIA's project that enables seamless training of LLMs, CV models and multimodal models in JAX, for information about running Vision Transformer models and experiments on GPUs. diff --git a/JAX/LanguageModeling/PAXML/README.md b/JAX/LanguageModeling/PAXML/README.md new file mode 100644 index 000000000..96b1dceac --- /dev/null +++ b/JAX/LanguageModeling/PAXML/README.md @@ -0,0 +1,4 @@ +Paxml (aka Pax) is a framework for training LLMs. It allows for advanced and configurable experimentation and parallelization. It is based on [JAX](https://github.com/google/jax) and [Praxis](https://github.com/google/praxis). + +# PAXML on GPUs +Please refer to [Rosetta PAXML](https://github.com/NVIDIA/JAX-Toolbox/tree/main/rosetta/rosetta/projects/pax), NVIDIA's project that enables seamless training of LLMs, CV models and multimodal models in JAX, for information about running models and experiments on GPUs in PAXML. diff --git a/JAX/LanguageModeling/README.md b/JAX/LanguageModeling/README.md new file mode 100644 index 000000000..d8f57e0af --- /dev/null +++ b/JAX/LanguageModeling/README.md @@ -0,0 +1,90 @@ +# Language Modeling + + +Language modeling (LM) is a natural language processing (NLP) task that determines the probability of a given sequence of words occurring in a sentence. + +In an era where computers, smartphones and other electronic devices increasingly need to interact with humans, language modeling has become an indispensable technique for teaching devices how to communicate in natural languages in human-like ways. + +But how does language modeling work? And what can you build with it? What are the different approaches, what are its potential benefits and limitations, and how might you use it in your business? + +In this guide, you’ll find answers to all of those questions and more. Whether you’re an experienced machine learning engineer considering implementation, a developer wanting to learn more, or a product manager looking to explore what’s possible with natural language processing and language modeling, this guide is for you. + +Here’s a look at what we’ll cover: + +- Language modeling – the basics +- How does language modeling work? +- Use cases and applications +- Getting started + + +## Language modeling – the basics + +### What is language modeling? + +"*Language modeling is the task of assigning a probability to sentences in a language. […] +Besides assigning a probability to each sequence of words, the language models also assign a +probability for the likelihood of a given word (or a sequence of words) to follow a sequence +of words.*" Source: Page 105, [Neural Network Methods in Natural Language Processing](http://amzn.to/2wt1nzv), 2017. + + +### Types of language models + +There are primarily two types of Language Models: + +- Statistical Language Models: These models use traditional statistical techniques like N-grams, Hidden Markov Models (HMM), and certain linguistic rules to learn the probability distribution of words. +- Neural Language Models: They use different kinds of Neural Networks to model language, and have surpassed the statistical language models in their effectiveness. + +"*We provide ample empirical evidence to suggest that connectionist language models are +superior to standard n-gram techniques, except their high computational (training) +complexity.*" Source: [Recurrent neural network based language model](http://www.fit.vutbr.cz/research/groups/speech/publi/2010/mikolov_interspeech2010_IS100722.pdf), 2010. + +Given the superior performance of neural language models, we include in the container two popular state-of-the-art neural language models: BERT and Transformer-XL. + +### Why is language modeling important? + +Language modeling is fundamental in modern NLP applications. It enables machines to understand qualitative information, and enables people to communicate with machines in the natural languages that humans use to communicate with each other. + +Language modeling is used directly in a variety of industries, including tech, finance, healthcare, transportation, legal, military, government, and more -- actually, you probably have just interacted with a language model today, whether it be through Google search, engaging with a voice assistant, or using text autocomplete features. + + +## How does language modeling work? + +The roots of modern language modeling can be traced back to 1948, when Claude Shannon +published a paper titled "A Mathematical Theory of Communication", laying the foundation for information theory and language modeling. In the paper, Shannon detailed the use of a stochastic model called the Markov chain to create a statistical model for the sequences of letters in English text. The Markov models, along with n-gram, are still among the most popular statistical language models today. + +However, simple statistical language models have serious drawbacks in scalability and fluency because of its sparse representation of language. Overcoming the problem by representing language units (eg. words, characters) as a non-linear, distributed combination of weights in continuous space, neural language models can learn to approximate words without being misled by rare or unknown values. + +Therefore, as mentioned above, we introduce two popular state-of-the-art neural language models, BERT and Transformer-XL, in Tensorflow and PyTorch. More details can be found in the [NVIDIA Deep Learning Examples Github Repository ](https://github.com/NVIDIA/DeepLearningExamples) + + +## Use cases and applications + +### Speech Recognition + +Imagine speaking a phrase to the phone, expecting it to convert the speech to text. How does +it know if you said "recognize speech" or "wreck a nice beach"? Language models help figure it out +based on the context, enabling machines to process and make sense of speech audio. + + +### Spelling Correction + +Language-models-enabled spellcheckers can point to spelling errors and possibly suggest alternatives. + + +### Machine translation + +Imagine you are translating the Chinese sentence "我在开车" into English. Your translation system gives you several choices: + +- I at open car +- me at open car +- I at drive +- me at drive +- I am driving +- me am driving + +A language model tells you which translation sounds the most natural. + +## Getting started +NVIDIA provides examples for JAX models on [Rosetta](https://github.com/NVIDIA/JAX-Toolbox/tree/main/rosetta/rosetta/projects). These examples provide you with easy to consume and highly optimized scripts for both training and inferencing. The quick start guide at our GitHub repository will help you in setting up the environment using NGC Docker Images, download pre-trained models from NGC and adapt the model training and inference for your application/use-case. + +These models are tested and maintained by NVIDIA, leveraging mixed precision using tensor cores on our latest GPUs for faster training times while maintaining accuracy. diff --git a/JAX/LanguageModeling/T5X/README.md b/JAX/LanguageModeling/T5X/README.md new file mode 100644 index 000000000..285717459 --- /dev/null +++ b/JAX/LanguageModeling/T5X/README.md @@ -0,0 +1,5 @@ +T5X is a framework for training, evaluation, and inference of sequence models (starting with language). It is based on [JAX](https://github.com/google/jax) and [Flax](https://github.com/google/flax). To learn more, see the [T5X Paper](https://arxiv.org/abs/2203.17189). + +# T5X on GPUs + +Please refer to [Rosetta T5X](https://github.com/NVIDIA/JAX-Toolbox/tree/main/rosetta/rosetta/projects/t5x), NVIDIA's project that enables seamless training of LLMs, CV models and multimodal models in JAX, for information about running models and experiments on GPUs in T5X. diff --git a/JAX/MultiModal/Imagen/README.md b/JAX/MultiModal/Imagen/README.md new file mode 100644 index 000000000..0de87b58b --- /dev/null +++ b/JAX/MultiModal/Imagen/README.md @@ -0,0 +1,2 @@ +# Imagen on GPUs +Please refer to [Rosetta Imagen](https://github.com/NVIDIA/JAX-Toolbox/tree/main/rosetta/rosetta/projects/imagen), NVIDIA's project that enables seamless training of LLMs, CV models and multimodal models in JAX, for information about running Imagen models and experiments on GPUs. diff --git a/MxNet/Classification/RN50v1.5/dali.py b/MxNet/Classification/RN50v1.5/dali.py index 13d044a56..6cd02f99f 100644 --- a/MxNet/Classification/RN50v1.5/dali.py +++ b/MxNet/Classification/RN50v1.5/dali.py @@ -31,7 +31,7 @@ def add_dali_args(parser): group.add_argument('--dali-validation-threads', type=int, default=10, help="number of threads" +\ "per GPU for DALI for validation") group.add_argument('--dali-prefetch-queue', type=int, default=5, help="DALI prefetch queue depth") - group.add_argument('--dali-nvjpeg-memory-padding', type=int, default=256, help="Memory padding value for nvJPEG (in MB)") + group.add_argument('--dali-nvjpeg-memory-padding', type=int, default=64, help="Memory padding value for nvJPEG (in MB)") group.add_argument('--dali-fuse-decoder', type=int, default=1, help="0 or 1 whether to fuse decoder or not") group.add_argument('--dali-nvjpeg-width-hint', type=int, default=5980, help="Width hint value for nvJPEG (in pixels)") diff --git a/MxNet/Classification/RN50v1.5/fit.py b/MxNet/Classification/RN50v1.5/fit.py index e396606f3..8952b64e0 100644 --- a/MxNet/Classification/RN50v1.5/fit.py +++ b/MxNet/Classification/RN50v1.5/fit.py @@ -483,11 +483,6 @@ def fit(args, model, data_loader): # select gpu for horovod process if 'horovod' in args.kv_store: args.gpus = [args.gpus[hvd.local_rank()]] - ctx = mx.gpu(hvd.local_rank()) - - tensor1 = mx.nd.zeros(shape=(1,), dtype='float32', ctx=ctx) - tensor2 = mx.nd.zeros(shape=(1,), dtype='float32', ctx=ctx) - tensor1, tensor2 = hvd.grouped_allreduce([tensor1,tensor2]) if args.amp: amp.init() @@ -579,6 +574,11 @@ def fit(args, model, data_loader): params = model.collect_params() if params is not None: hvd.broadcast_parameters(params, root_rank=0) + ctx = mx.gpu(hvd.local_rank()) + tensor1 = mx.nd.zeros(shape=(1,), dtype='float32', ctx=ctx) + tensor2 = mx.nd.zeros(shape=(1,), dtype='float32', ctx=ctx) + tensor1, tensor2 = hvd.grouped_allreduce([tensor1,tensor2]) + global_metrics = CompositeMeter() if args.mode in ['train_val', 'train']: global_metrics.register_metric('train.loss', MinMeter()) diff --git a/PaddlePaddle/Classification/RN50v1.5/Dockerfile b/PaddlePaddle/Classification/RN50v1.5/Dockerfile index 44aad1329..932dca3c6 100644 --- a/PaddlePaddle/Classification/RN50v1.5/Dockerfile +++ b/PaddlePaddle/Classification/RN50v1.5/Dockerfile @@ -1,4 +1,4 @@ -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/paddlepaddle:22.05-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/paddlepaddle:23.12-py3 FROM ${FROM_IMAGE_NAME} ADD requirements.txt /workspace/ diff --git a/PaddlePaddle/Classification/RN50v1.5/README.md b/PaddlePaddle/Classification/RN50v1.5/README.md index 76a75104e..1e981db73 100644 --- a/PaddlePaddle/Classification/RN50v1.5/README.md +++ b/PaddlePaddle/Classification/RN50v1.5/README.md @@ -17,6 +17,8 @@ achieve state-of-the-art accuracy. The content of this repository is tested and * [Enabling TF32](#enabling-tf32) * [Automatic SParsity](#automatic-sparsity) * [Enable Automatic SParsity](#enable-automatic-sparsity) + * [Quantization aware training](#quantization-aware-training) + * [Enable quantization aware training](#enable-quantization-aware-training) * [Setup](#setup) * [Requirements](#requirements) * [Quick Start Guide](#quick-start-guide) @@ -26,6 +28,7 @@ achieve state-of-the-art accuracy. The content of this repository is tested and * [Dataset guidelines](#dataset-guidelines) * [Training process](#training-process) * [Automatic SParsity training process](#automatic-sparsity-training-process) + * [Quantization aware training process](#quantization-aware-training-process) * [Inference process](#inference-process) * [Performance](#performance) * [Benchmarking](#benchmarking) @@ -128,6 +131,7 @@ This model supports the following features: |[DALI](https://docs.nvidia.com/deeplearning/sdk/dali-release-notes/index.html) | Yes | |[Paddle AMP](https://www.paddlepaddle.org.cn/documentation/docs/en/guides/performance_improving/amp_en.html) | Yes | |[Paddle ASP](https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/static/sparsity/decorate_en.html) | Yes | +|[PaddleSlim QAT](https://paddleslim.readthedocs.io/en/latest/quick_start/quant_aware_tutorial_en.html) | Yes | |[Paddle-TRT](https://github.com/PaddlePaddle/Paddle-Inference-Demo/blob/master/docs/optimize/paddle_trt_en.rst) | Yes | #### Features @@ -139,7 +143,9 @@ with the DALI library. For more information about DALI, refer to the [DALI produ - Paddle ASP is a PaddlePaddle built-in module that provides functions to enable automatic sparsity workflow with only a few code line insertions. The full APIs can be found in [Paddle.static.sparsity](https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/static/sparsity/calculate_density_en.html). Paddle ASP support, currently, static graph mode only (Dynamic graph support is under development). Refer to the [Enable Automatic SParsity](#enable-automatic-sparsity) section for more details. -- Paddle-TRT is a PaddlePaddle inference integration with [TensorRT](https://docs.nvidia.com/deeplearning/tensorrt/developer-guide/index.html). It selects subgraph to be accelerated by TensorRT, while leaving the rest of the operations to be executed natively by PaddlePaddle. Refer to the [Inference with TensorRT](#inference-with-tensorrt) section for more details. +- PaddleSlim is a set of tools based on PaddlePaddle for model acceleration, quantization, pruning, and knowledge distillation. For model quantization, PaddleSlim offers simple and user-friendly APIs for quantization aware training. The full APIs can be found in [Quantization aware training](https://paddleslim.readthedocs.io/en/latest/api_en/index_en.html). PaddleSlim currently supports updating gradients and scales simultaneously during quantization aware training (Training with fixed scales is still under development). Refer to the [Enable quantization aware training](#enable-quantization-aware-training) section for more details. + +- Paddle-TRT is a PaddlePaddle inference integration with [TensorRT](https://docs.nvidia.com/deeplearning/tensorrt/developer-guide/index.html). It selects subgraphs to be accelerated by TensorRT, while leaving the rest of the operations to be executed natively by PaddlePaddle. Refer to the [Inference with TensorRT](#inference-with-tensorrt) section for more details. ### DALI @@ -147,7 +153,7 @@ We use [NVIDIA DALI](https://github.com/NVIDIA/DALI), which speeds up data loading when the CPU becomes a bottleneck. DALI can use CPU or GPU and outperforms the PaddlePaddle native data loader. -For data loader, we only support DALI as data loader for now. +For data loaders, we only support DALI as data loader for now. ### Mixed precision training @@ -225,6 +231,30 @@ Moreover, ASP is also compatible with mixed precision training. Note that currently ASP only supports static graphs (Dynamic graph support is under development). +### Quantization Aware Training +Quantization aware training (QAT) is a technique to train models with the awareness of the quantization process. Quantization refers to reducing the precision of numerical values in a model, typically from floating-point to lower-bit fixed-point representations. In QAT, during the training process, the model is trained to accommodate the effects of quantization, enabling it to maintain performance even when deployed with reduced precision. +Through PaddleSlim QAT, we can quantize models by the following steps: +- quantize and dequantize the weights and inputs before feeding them into weighted-layers (ex. Convolution and Fullyconnected) +- record the scale of each tensor for use in low precision inference + +For more information, refer to +- [INTEGER QUANTIZATION FOR DEEP LEARNING INFERENCE: PRINCIPLES AND EMPIRICAL EVALUATION](https://arxiv.org/pdf/2004.09602.pdf) + +#### Enable Quantization Aware Training +PaddlePaddle integrates some QAT modules from PaddleSlim, a toolkit for deep learning model compression, to enable QAT training. +The APIs can quantize a train program and also convert it into an INT8 inference model. + +```python +quant_program = quanter.quant_aware(program) +... +quant_infer_program = quanter.convert(quant_program) +``` + +The detailed information on QAT API can be found in [quantization_aware_tutorial](https://paddleslim.readthedocs.io/en/latest/quick_start/quant_aware_tutorial_en.html). + +Moreover, QAT is also compatible with mixed precision training. + + ## Setup The following section lists the requirements you need to meet to start training the ResNet50 model. @@ -233,7 +263,7 @@ The following section lists the requirements you need to meet to start training This repository contains a Dockerfile that extends the CUDA NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: * [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -* [PaddlePaddle 22.05-py3 NGC container](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/paddlepaddle) or newer +* [PaddlePaddle 23.12-py3 NGC container](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/paddlepaddle) or newer * Supported GPUs: * [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) @@ -289,13 +319,13 @@ docker build . -t nvidia_resnet50 ### 4. Start an interactive session in the NGC container to run training/inference. ```bash -nvidia-docker run --rm -it -v :/imagenet --ipc=host nvidia_resnet50 +nvidia-docker run --rm -it -v :/imagenet --ipc=host --e FLAGS_apply_pass_to_program=1 nvidia_resnet50 ``` ### 5. Start training To run training for a standard configuration (DGXA100, AMP/TF32), -use one of scripts in `scripts/training` to launch training. (Please ensure ImageNet is mounted in the `/imagenet` directory.) +use one of the scripts in `scripts/training` to launch training. (Please ensure ImageNet is mounted in the `/imagenet` directory.) Example: ```bash @@ -303,7 +333,7 @@ Example: bash scripts/training/train_resnet50_TF32_90E_DGXA100.sh # For AMP and 8 GPUs training in 90 epochs -bash scripts/training/train_resnet50_TF32_90E_DGXA100.sh +bash scripts/training/train_resnet50_AMP_90E_DGXA100.sh ``` Or you can manually launch training by `paddle.distributed.launch`. `paddle.distributed.launch` is a built-in module in PaddlePaddle that spawns up multiple distributed training processes on each of the training nodes. @@ -390,7 +420,8 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py ### Command-line options: To find the full list of available options and their descriptions, use the `-h` or `--help` command-line option, for example: -`python [train.py|export_model.py|inference.py] -h` + +`python train.py -h` ```bash PaddlePaddle RN50v1.5 training script @@ -398,9 +429,11 @@ PaddlePaddle RN50v1.5 training script optional arguments: -h, --help show this help message and exit -Global: - --output-dir OUTPUT_DIR - A path to store trained models. (default: ./output/) +General: + --checkpoint-dir CHECKPOINT_DIR + A path to store trained models. (default: ./checkpoint) + --inference-dir INFERENCE_DIR + A path to store inference model once the training is finished. (default: ./inference/) --run-scope {train_eval,train_only,eval_only} Running scope. It should be one of {train_eval, train_only, eval_only}. (default: train_eval) --epochs EPOCHS The number of epochs for training. (default: 90) @@ -410,11 +443,9 @@ Global: The iteration interval to test trained models on a given validation dataset. Ignored when --run-scope is train_only. (default: 1) --print-interval PRINT_INTERVAL - The iteration interval to show training/evaluation message. (default: 10) + The iteration interval to show a training/evaluation message. (default: 10) --report-file REPORT_FILE - A file in which to store JSON experiment report. (default: ./report.json) - --data-layout {NCHW,NHWC} - Data format. It should be one of {NCHW, NHWC}. (default: NCHW) + A file in which to store JSON experiment reports. (default: ./train.json) --benchmark To enable benchmark mode. (default: False) --benchmark-steps BENCHMARK_STEPS Steps for benchmark run, only be applied when --benchmark is set. (default: 100) @@ -431,7 +462,7 @@ Global: --last-epoch-of-checkpoint LAST_EPOCH_OF_CHECKPOINT The epoch id of the checkpoint given by --from-checkpoint. It should be None, auto or integer >= 0. If it is set as None, then training will start from 0-th epoch. If it is set as auto, then it will search largest integer- - convertable folder --from-checkpoint, which contains required checkpoint. Default is None. (default: None) + convertible folder --from-checkpoint, which contains the required checkpoint. Default is None. (default: None) --show-config SHOW_CONFIG To show arguments. (default: True) --enable-cpu-affinity ENABLE_CPU_AFFINITY @@ -448,7 +479,7 @@ Dataset: --dali-random-seed DALI_RANDOM_SEED The random seed for DALI data loader. (default: 42) --dali-num-threads DALI_NUM_THREADS - The number of threads applied to DALI data loader. (default: 4) + The number of threads applied to the DALI data loader. (default: 4) --dali-output-fp16 Output FP16 data from DALI data loader. (default: False) Data Augmentation: @@ -472,6 +503,8 @@ Model: The model architecture name. It should be one of {ResNet50}. (default: ResNet50) --num-of-class NUM_OF_CLASS The number classes of images. (default: 1000) + --data-layout {NCHW,NHWC} + Data format. It should be one of {NCHW, NHWC}. (default: NCHW) --bn-weight-decay Apply weight decay to BatchNorm shift and scale. (default: False) Training: @@ -479,16 +512,16 @@ Training: The ratio of label smoothing. (default: 0.1) --optimizer OPTIMIZER The name of optimizer. It should be one of {Momentum}. (default: Momentum) - --momentum MOMENTUM The momentum value of optimizer. (default: 0.875) + --momentum MOMENTUM The momentum value of an optimizer. (default: 0.875) --weight-decay WEIGHT_DECAY The coefficient of weight decay. (default: 3.0517578125e-05) --lr-scheduler LR_SCHEDULER - The name of learning rate scheduler. It should be one of {Cosine}. (default: Cosine) + The name of the learning rate scheduler. It should be one of {Cosine}. (default: Cosine) --lr LR The initial learning rate. (default: 0.256) --warmup-epochs WARMUP_EPOCHS The number of epochs for learning rate warmup. (default: 5) --warmup-start-lr WARMUP_START_LR - The initial learning rate for warmup. (default: 0.0) + The initial learning rate for warm up. (default: 0.0) Advanced Training: --amp Enable automatic mixed precision training (AMP). (default: False) @@ -497,36 +530,50 @@ Advanced Training: --use-dynamic-loss-scaling Enable dynamic loss scaling in AMP training, only be applied when --amp is set. (default: False) --use-pure-fp16 Enable pure FP16 training, only be applied when --amp is set. (default: False) + --fuse-resunit Enable CUDNNv8 ResUnit fusion, only be applied when --amp is set. (default: False) --asp Enable automatic sparse training (ASP). (default: False) --prune-model Prune model to 2:4 sparse pattern, only be applied when --asp is set. (default: False) --mask-algo {mask_1d,mask_2d_greedy,mask_2d_best} The algorithm to generate sparse masks. It should be one of {mask_1d, mask_2d_greedy, mask_2d_best}. This only be applied when --asp and --prune-model is set. (default: mask_1d) + --qat Enable quantization aware training (QAT). (default: False) +``` +`python inference.py -h` +```sh Paddle-TRT: - --trt-inference-dir TRT_INFERENCE_DIR - A path to store/load inference models. export_model.py would export models to this folder, then inference.py - would load from here. (default: ./inference) - --trt-precision {FP32,FP16,INT8} + --device DEVICE_ID + The GPU device id for Paddle-TRT inference. (default: 0) + --inference-dir INFERENCE_DIR + A path to load inference models. (default: ./inference) + --batch-size BATCH_SIZE + The batch size for Paddle-TRT. (default: 256) + --image-shape IMAGE_SHAPE + The image shape. Its shape should be [channel, height, width]. (default: [4, 224, 224]) + --data-layout {NCHW,NHWC} + Data format. It should be one of {NCHW, NHWC}. (default: NCHW) + --precision {FP32,FP16,INT8} The precision of TensorRT. It should be one of {FP32, FP16, INT8}. (default: FP32) - --trt-workspace-size TRT_WORKSPACE_SIZE + --workspace-size WORKSPACE_SIZE The memory workspace of TensorRT in MB. (default: 1073741824) - --trt-min-subgraph-size TRT_MIN_SUBGRAPH_SIZE + --min-subgraph-size MIN_SUBGRAPH_SIZE The minimal subgraph size to enable PaddleTRT. (default: 3) - --trt-use-static TRT_USE_STATIC + --use-static USE_STATIC Fix TensorRT engine at first running. (default: False) - --trt-use-calib-mode TRT_USE_CALIB_MODE + --use-calib-mode USE_CALIB_MODE Use the PTQ calibration of PaddleTRT int8. (default: False) - --trt-export-log-path TRT_EXPORT_LOG_PATH - A file in which to store JSON model exporting report. (default: ./export.json) - --trt-log-path TRT_LOG_PATH - A file in which to store JSON inference report. (default: ./inference.json) - --trt-use-synthat TRT_USE_SYNTHAT + --report-file REPORT_FILE + A file in which to store JSON experiment report. (default: ./inference.json) + --use-synthetic USE_SYNTHAT Apply synthetic data for benchmark. (default: False) + --benchmark-steps BENCHMARK_STEPS + Steps for benchmark run, only be applied when --benchmark is set. (default: 100) + --benchmark-warmup-steps BENCHMARK_WARMUP_STEPS + Warmup steps for benchmark run, only be applied when --benchmark is set. (default: 100) + --show-config SHOW_CONFIG + To show arguments. (default: True) ``` -Noted that arguments in Paddle-TRT are only available to `export_model.py` or `inference.py`. - ### Dataset guidelines To use your own dataset, divide it in directories as in the following scheme: @@ -537,15 +584,17 @@ To use your own dataset, divide it in directories as in the following scheme: If the number of classes in your dataset is not 1000, you need to specify it to `--num-of-class`. ### Training process -The model will be stored in the directory specified with `--output-dir` and `--model-arch-name`, including three files: +The checkpoint will be stored in the directory specified with `--checkpoint-dir` and `--model-arch-name`, including three files: - `.pdparams`: The parameters contain all the trainable tensors and will save to a file with the suffix “.pdparams”. -- `.pdopts`: The optimizer information contains all the Tensors used by the optimizer. For Adam optimizer, it contains beta1, beta2, momentum, and so on. All the information will be saved to a file with suffix “.pdopt”. (If the optimizer has no Tensor need to save (like SGD), the file will not be generated). +- `.pdopts`: The optimizer information contains all the Tensors used by the optimizer. For Adam optimizer, it contains beta1, beta2, momentum, and so on. All the information will be saved to a file with the suffix “.pdopt”. (If the optimizer has no Tensor need to save (like SGD), the file will not be generated). - `.pdmodel`: The network description is the description of the program. It’s only used for deployment. The description will save to a file with the suffix “.pdmodel”. -The prefix of model files is specified by `--model-prefix`, which default value is `resnet_50_paddle`. Model of each epoch would be stored in directory `./output/ResNet50/epoch_id/` with three files by default, including `resnet_50_paddle.pdparams`, `resnet_50_paddle.pdopts`, `resnet_50_paddle.pdmodel`. Note that `epoch_id` is 0-based, which means `epoch_id` is from 0 to 89 for a total of 90 epochs. For example, the model of the 89th epoch would be stored in `./output/ResNet50/89/resnet_50_paddle` +The prefix of model files is specified by `--model-prefix`, whose default value is `resnet_50_paddle`. Model of each epoch would be stored in directory `./checkpoint/ResNet50/epoch_id/` with three files by default, including `resnet_50_paddle.pdparams`, `resnet_50_paddle.pdopts`, `resnet_50_paddle.pdmodel`. Note that `epoch_id` is 0-based, which means `epoch_id` is from 0 to 89 for a total of 90 epochs. For example, the model of the 89th epoch would be stored in `./output/ResNet50/89/resnet_50_paddle` + +When the training phase is done, the inference model will be stored in the directory specified with `--inference-dir` and `--model-arch-name`, and it includes `.pdmodel` and `.pdparams` two files. Assume you want to train the ResNet50 for 90 epochs, but the training process aborts during the 50th epoch due to infrastructure faults. To resume training from the checkpoint, specify `--from-checkpoint` and `--last-epoch-of-checkpoint` with following these steps: -- Set `./output/ResNet50/49` to `--from-checkpoint`. +- Set `./checkpoint/ResNet50/49` to `--from-checkpoint`. - Set `--last-epoch-of-checkpoint` to `49`. Then rerun the training to resume training from the 50th epoch to the 89th epoch. @@ -559,11 +608,11 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ --use-dynamic-loss-scaling \ --data-layout NHWC \ --model-prefix resnet_50_paddle \ - --from-checkpoint ./output/ResNet50/49 \ + --from-checkpoint ./checkpoint/ResNet50/49 \ --last-epoch-of-checkpoint 49 ``` -We also provide automatic searching for the checkpoint from last epoch. You can enable this by set `--last-epoch-of-checkpoint` as `auto`. Noted that if enable automatic searching, `--from-checkpoint` should be a folder contains chekcpoint files or `/`. In previous example, it should be `./output/ResNet50`. +We also provide automatic searching for the checkpoint from last epoch. You can enable this by setting `--last-epoch-of-checkpoint` as `auto`. Note that if you enable automatic searching, `--from-checkpoint` should be a folder containing checkpoint files or `/`. In previous example, it should be `./checkpoint/ResNet50`. Example: ```bash @@ -575,11 +624,11 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ --use-dynamic-loss-scaling \ --data-layout NHWC \ --model-prefix resnet_50_paddle \ - --from-checkpoint ./output/ResNet50 \ + --from-checkpoint ./checkpoint/ResNet50 \ --last-epoch-of-checkpoint auto ``` -To start training from pretrained weights, set `--from-pretrained-params` to `./output/ResNet50//<--model-prefix>`. +To start training from pretrained weights, set `--from-pretrained-params` to `./checkpoint/ResNet50//<--model-prefix>`. Example: ```bash @@ -591,7 +640,7 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ --use-dynamic-loss-scaling \ --data-layout NHWC \ --model-prefix resnet_50_paddle \ - --from-pretrained-params ./output/ResNet50/ + --from-pretrained-params ./checkpoint/ResNet50/ ``` Make sure: @@ -603,7 +652,7 @@ The difference between those two is that `--from-pretrained-params` contain only `--from-checkpoint` is suitable for dividing the training into parts, for example, in order to divide the training job into shorter stages, or restart training after infrastructure faults. -`--from-pretrained-params` can be used as a base for finetuning the model to a different dataset or as a backbone to detection models. +`--from-pretrained-params` can be used as a base for fine tuning the model to a different dataset or as a backbone to detection models. Metrics gathered through both training and evaluation: - `[train|val].loss` - loss @@ -619,24 +668,24 @@ Metrics gathered through both training and evaluation: ### Automatic SParsity training process: -To enable automatic sparsity training workflow, turn on `--amp` and `--prune-mode` when training launches. Refer to [Command-line options](#command-line-options) +To enable automatic sparsity training workflow, turn on `--asp` and `--prune-mode` when training launches. Refer to [Command-line options](#command-line-options) Note that automatic sparsity (ASP) requires a pretrained model to initialize parameters. You can apply `scripts/training/train_resnet50_AMP_ASP_90E_DGXA100.sh` we provided to launch ASP + AMP training. ```bash -# Default path to pretrained parameters is ./output/ResNet50/89/resnet_50_paddle +# Default path to pretrained parameters is ./checkpoint/ResNet50/89/resnet_50_paddle bash scripts/training/train_resnet50_AMP_ASP_90E_DGXA100.sh ``` Or following steps below to manually launch ASP + AMP training. -First, set `--from-pretrained-params` to a pretrained model file. For example, if you have trained the ResNet50 for 90 epochs following [Training process](#training-process), the final pretrained weights would be stored in `./output/ResNet50/89/resnet_50_paddle.pdparams` by default, and set `--from-pretrained-params` to `./output/ResNet50/89`. +First, set `--from-pretrained-params` to a pretrained model file. For example, if you have trained the ResNet50 for 90 epochs following [Training process](#training-process), the final pretrained weights would be stored in `./checkpoint/ResNet50/89/resnet_50_paddle.pdparams` by default, and set `--from-pretrained-params` to `./checkpoint/ResNet50/89`. Then run following command to run AMP + ASP: ```bash python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ - --from-pretrained-params ./output/ResNet50/89 \ + --from-pretrained-params ./checkpoint/ResNet50/89 \ --model-prefix resnet_50_paddle \ --epochs 90 \ --amp \ @@ -648,14 +697,43 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ --mask-algo mask_1d ``` +## Quantization Aware Training Process +Quantization aware training requires a fine-tuned model. Quantize / dequantize OPs will be inserted into the model and then a smaller number of epochs of training will be taken to update the parameters in the model. + +To enable quantization aware training workflow, turn on `--qat` when training launches. Refer to [Command-line options](#command-line-options). + +You can apply the script `scripts/training/train_resnet50_AMP_QAT_10E_DGXA100.sh` we provided to launch AMP + QAT training. +```bash +# Default path to pretrained parameters is ./output/ResNet50/89/resnet_50_paddle +bash scripts/training/train_resnet50_AMP_QAT_10E_DGXA100.sh +``` + +Or following steps below to manually launch AMP + QAT training. + +First, set `--from-pretrained-params` to a pretrained model file. For example, if you have trained the ResNet50 for 90 epochs following [Training process](#training-process), the final pretrained weights would be stored in `./output/ResNet50/89/resnet_50_paddle.pdparams` by default, and set `--from-pretrained-params` to `./output/ResNet50/89`. + +Then run following command to run AMP + QAT: +```bash +python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ + --from-pretrained-params ./output/ResNet50/89 \ + --model-prefix resnet_50_paddle \ + --epochs 10 \ + --amp \ + --scale-loss 128.0 \ + --use-dynamic-loss-scaling \ + --data-layout NHWC \ + --qat +``` + + ### Inference process #### Inference on your own datasets. To run inference on a single example with pretrained parameters, 1. Set `--from-pretrained-params` to your pretrained parameters. -2. Set `--image-root` to the root folder of your own dataset. - - Note that validation dataset should be in `image-root/val`. +2. Set `--image-root` to the root folder of your own dataset. + - Note that the validation dataset should be in `image-root/val`. 3. Set `--run-scope` to `eval_only`. ```bash # For single GPU evaluation @@ -672,17 +750,27 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ ``` #### Inference with TensorRT -To run inference with TensorRT for the best performance, you can apply the scripts in `scripts/inference`. +For inference with TensorRT, we provide two scopes to benchmark with or without data preprocessing. + +The default scripts in `scripts/inference` use synthetic input to run inference without data preprocessing. For example, 1. Run `bash scripts/inference/export_resnet50_AMP.sh ` to export an inference model. - - The default path of checkpoint is `./output/ResNet50/89`. + - The default path of the checkpoint is `./output/ResNet50/89`. 2. Run `bash scripts/inference/infer_resnet50_AMP.sh` to infer with TensorRT. Or you could manually run `export_model.py` and `inference.py` with specific arguments, refer to [Command-line options](#command-line-options). Note that arguments passed to `export_model.py` and `inference.py` should be the same with arguments used in training. +To run inference with data preprocessing, set the option `--use-synthetic` to false and `--image-root` to the path of your own dataset. For example, + +```bash +python inference.py --inference-dir \ + --image-root \ + --use-synthetic False +``` + ## Performance The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to [NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). @@ -748,32 +836,32 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ ##### Benchmark with TensorRT -To benchmark the inference performance with TensorRT on a specific batch size, run: +To benchmark the inference performance with TensorRT on a specific batch size, run inference.py with `--use-synthetic True`. The benchmark uses synthetic input without data preprocessing. * FP32 / TF32 ```bash python inference.py \ - --trt-inference-dir \ - --trt-precision FP32 \ + --inference-dir \ + --precision FP32 \ --batch-size \ --benchmark-steps 1024 \ - --benchmark-warmup-steps 16 + --benchmark-warmup-steps 16 \ + --use-synthetic True ``` * FP16 ```bash python inference.py \ - --trt-inference-dir \ - --trt-precision FP16 \ + --inference-dir \ + --precision FP16 \ --batch-size --benchmark-steps 1024 \ - --benchmark-warmup-steps 16 + --benchmark-warmup-steps 16 \ + --use-synthetic True ``` Note that arguments passed to `inference.py` should be the same with arguments used in training. -The benchmark uses the validation dataset by default, which should be put in `--image-root/val`. -For the performance benchmark of the raw model, a synthetic dataset can be used. To use synthetic dataset, add `--trt-use-synthat True` as a command line option. ### Results @@ -793,7 +881,7 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic ##### Example plots -The following images show the 90 epochs configuration on a DGX-A100. +The following images show the 90 epoch configuration on a DGX-A100. ![ValidationLoss](./img/loss.png) ![ValidationTop1](./img/top1.png) @@ -815,8 +903,8 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic | **GPUs** | **Throughput - TF32** | **Throughput - mixed precision** | **Throughput speedup (TF32 to mixed precision)** | **TF32 Scaling** | **Mixed Precision Scaling** | **Mixed Precision Training Time (90E)** | **TF32 Training Time (90E)** | |:--------:|:------------:|:-------------:|:------------:|:------:|:--------:|:--------:|:--------:| -| 1 | 993 img/s | 2711 img/s | 2.73 x | 1.0 x | 1.0 x | ~13 hours| ~40 hours| -| 8 | 7955 img/s | 20267 img/s | 2.54 x | 8.01 x | 7.47 x | ~2 hours | ~4 hours | +| 1 | 1024 img/s | 2897 img/s | 2.83 x | 1.0 x | 1.0 x | ~13 hours| ~40 hours| +| 8 | 8013 img/s | 23874 img/s | 2.98 x | 7.83 x | 8.24 x | ~2 hours | ~4 hours | ##### Training performance of Automatic SParsity: NVIDIA DGX A100 (8x A100 80GB) | **GPUs** | **Throughput - mixed precision** | **Throughput - mixed precision+ASP** | **Overhead** | @@ -825,7 +913,7 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic | 8 | 20267 img/s | 20144 img/s | 0.6% | -Note that the `train.py` would enable CPU affinity binding to GPUs by default, that is designed and guaranteed being optimal for NVIDIA DGX-series. You could disable binding via launch `train.py` with `--enable-cpu-affinity false`. +Note that the `train.py` would enable CPU affinity binding to GPUs by default, that is designed and guaranteed to be optimal for NVIDIA DGX-series. You could disable binding via launch `train.py` with `--enable-cpu-affinity false`. ### Inference performance results @@ -866,96 +954,143 @@ Our results were obtained by running the applicable training script with `--run- #### Paddle-TRT performance: NVIDIA DGX A100 (1x A100 80GB) Our results for Paddle-TRT were obtained by running the `inference.py` script on NVIDIA DGX A100 with (1x A100 80G) GPU. +Note that the benchmark does not include data preprocessing. Refer to [Benchmark with TensorRT](#benchmark-with-tensorrt). + **TF32 Inference Latency** |**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| |--------------|------------------|---------------|---------------|---------------|---------------| -| 1 | 716.49 img/s | 1.40 ms | 1.96 ms | 2.20 ms | 3.01 ms | -| 2 | 1219.98 img/s | 1.64 ms | 2.26 ms | 2.90 ms | 5.04 ms | -| 4 | 1880.12 img/s | 2.13 ms | 3.39 ms | 4.44 ms | 7.32 ms | -| 8 | 2404.10 img/s | 3.33 ms | 4.51 ms | 5.90 ms | 10.39 ms | -| 16 | 3101.28 img/s | 5.16 ms | 7.06 ms | 9.13 ms | 15.18 ms | -| 32 | 3294.11 img/s | 9.71 ms | 21.42 ms | 26.94 ms | 35.79 ms | -| 64 | 4327.38 img/s | 14.79 ms | 25.59 ms | 30.45 ms | 45.34 ms | -| 128 | 4956.59 img/s | 25.82 ms | 33.74 ms | 40.36 ms | 56.06 ms | -| 256 | 5244.29 img/s | 48.81 ms | 62.11 ms | 67.56 ms | 88.38 ms | +| 1 | 969.11 img/s | 1.03 ms | 1.03 ms | 1.13 ms | 1.14 ms | +| 2 | 1775.33 img/s | 1.13 ms | 1.13 ms | 1.22 ms | 1.23 ms | +| 4 | 3088.02 img/s | 1.29 ms | 1.30 ms | 1.39 ms | 1.40 ms | +| 8 | 4552.29 img/s | 1.76 ms | 1.76 ms | 1.85 ms | 1.87 ms | +| 16 | 6059.48 img/s | 2.64 ms | 2.64 ms | 2.73 ms | 2.75 ms | +| 32 | 7264.92 img/s | 4.40 ms | 4.41 ms | 4.49 ms | 4.52 ms | +| 64 | 8022.82 img/s | 7.98 ms | 8.03 ms | 8.05 ms | 8.11 ms | +| 128 | 8436.27 img/s | 15.17 ms | 15.20 ms | 15.27 ms | 15.30 ms | +| 256 | 8623.08 img/s | 29.69 ms | 29.82 ms | 29.86 ms | 29.97 ms | **FP16 Inference Latency** |**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| |--------------|------------------|---------------|---------------|---------------|---------------| -| 1 | 860.90 img/s | 1.16 ms | 1.81 ms | 2.06 ms | 2.98 ms | -| 2 | 1464.06 img/s | 1.37 ms | 2.13 ms | 2.73 ms | 4.76 ms | -| 4 | 2246.24 img/s | 1.78 ms | 3.17 ms | 4.20 ms | 7.39 ms | -| 8 | 2457.44 img/s | 3.25 ms | 4.35 ms | 5.50 ms | 9.98 ms | -| 16 | 3928.83 img/s | 4.07 ms | 6.26 ms | 8.50 ms | 15.10 ms | -| 32 | 3853.13 img/s | 8.30 ms | 19.87 ms | 25.51 ms | 34.99 ms | -| 64 | 5581.89 img/s | 11.46 ms | 22.32 ms | 30.75 ms | 43.35 ms | -| 128 | 6846.77 img/s | 18.69 ms | 25.43 ms | 35.03 ms | 50.04 ms | -| 256 | 7481.19 img/s | 34.22 ms | 40.92 ms | 51.10 ms | 65.68 ms | +| 1 | 1306.28 img/s | 0.76 ms | 0.77 ms | 0.86 ms | 0.87 ms | +| 2 | 2453.18 img/s | 0.81 ms | 0.82 ms | 0.91 ms | 0.92 ms | +| 4 | 4295.75 img/s | 0.93 ms | 0.95 ms | 1.03 ms | 1.04 ms | +| 8 | 7036.09 img/s | 1.14 ms | 1.15 ms | 1.23 ms | 1.25 ms | +| 16 | 10376.70 img/s | 1.54 ms | 1.56 ms | 1.64 ms | 1.66 ms | +| 32 | 13078.23 img/s | 2.45 ms | 2.45 ms | 2.54 ms | 2.56 ms | +| 64 | 14992.88 img/s | 4.27 ms | 4.27 ms | 4.36 ms | 4.38 ms | +| 128 | 16386.96 img/s | 7.81 ms | 7.83 ms | 7.89 ms | 7.93 ms | +| 256 | 17363.79 img/s | 14.74 ms | 14.80 ms | 14.82 ms | 14.90 ms | + +**INT8 Inference Latency** + +|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| +|--------------|------------------|---------------|---------------|---------------|---------------| +| 1 | 1430.17 img/s | 0.70 ms | 0.70 ms | 0.79 ms | 0.80 ms | +| 2 | 2683.75 img/s | 0.74 ms | 0.75 ms | 0.84 ms | 0.85 ms | +| 4 | 4792.51 img/s | 0.83 ms | 0.84 ms | 0.93 ms | 0.94 ms | +| 8 | 8366.92 img/s | 0.96 ms | 0.96 ms | 1.05 ms | 1.06 ms | +| 16 | 13083.56 img/s | 1.22 ms | 1.22 ms | 1.32 ms | 1.33 ms | +| 32 | 18171.90 img/s | 1.76 ms | 1.76 ms | 1.86 ms | 1.87 ms | +| 64 | 22578.08 img/s | 2.83 ms | 2.84 ms | 2.93 ms | 2.95 ms | +| 128 | 25730.51 img/s | 4.97 ms | 4.98 ms | 5.07 ms | 5.08 ms | +| 256 | 27935.10 img/s | 9.16 ms | 9.26 ms | 9.30 ms | 9.34 ms | #### Paddle-TRT performance: NVIDIA A30 (1x A30 24GB) Our results for Paddle-TRT were obtained by running the `inference.py` script on NVIDIA A30 with (1x A30 24G) GPU. +Note that the benchmark does not include data preprocessing. Refer to [Benchmark with TensorRT](#benchmark-with-tensorrt). + **TF32 Inference Latency** |**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| |--------------|------------------|---------------|---------------|---------------|---------------| -| 1 | 672.79 img/s | 1.49 ms | 2.01 ms | 2.29 ms | 3.04 ms | -| 2 | 1041.47 img/s | 1.92 ms | 2.49 ms | 2.87 ms | 4.13 ms | -| 4 | 1505.64 img/s | 2.66 ms | 3.43 ms | 4.06 ms | 6.85 ms | -| 8 | 2001.13 img/s | 4.00 ms | 4.72 ms | 5.54 ms | 9.51 ms | -| 16 | 2462.80 img/s | 6.50 ms | 7.71 ms | 9.32 ms | 15.54 ms | -| 32 | 2474.34 img/s | 12.93 ms | 21.61 ms | 25.76 ms | 34.69 ms | -| 64 | 2949.38 img/s | 21.70 ms | 29.58 ms | 34.63 ms | 47.11 ms | -| 128 | 3278.67 img/s | 39.04 ms | 43.34 ms | 52.72 ms | 66.78 ms | -| 256 | 3293.10 img/s | 77.74 ms | 90.51 ms | 99.71 ms | 110.80 ms | +| 1 | 860.08 img/s | 1.16 ms | 1.16 ms | 1.27 ms | 1.29 ms | +| 2 | 1422.02 img/s | 1.40 ms | 1.41 ms | 1.52 ms | 1.53 ms | +| 4 | 2058.41 img/s | 1.94 ms | 1.94 ms | 2.06 ms | 2.10 ms | +| 8 | 2748.94 img/s | 2.91 ms | 2.93 ms | 3.03 ms | 3.22 ms | +| 16 | 3329.39 img/s | 4.80 ms | 4.90 ms | 4.93 ms | 5.09 ms | +| 32 | 3729.45 img/s | 8.58 ms | 8.68 ms | 8.74 ms | 8.84 ms | +| 64 | 3946.74 img/s | 16.21 ms | 16.34 ms | 16.41 ms | 16.51 ms | +| 128 | 4116.98 img/s | 31.09 ms | 31.26 ms | 31.38 ms | 31.43 ms | +| 256 | 4227.52 img/s | 60.55 ms | 60.93 ms | 61.01 ms | 61.25 ms | **FP16 Inference Latency** |**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| |--------------|------------------|---------------|---------------|---------------|---------------| -| 1 | 804.56 img/s | 1.24 ms | 1.81 ms | 2.15 ms | 3.07 ms | -| 2 | 1435.74 img/s | 1.39 ms | 2.05 ms | 2.48 ms | 3.86 ms | -| 4 | 2169.87 img/s | 1.84 ms | 2.72 ms | 3.39 ms | 5.94 ms | -| 8 | 2395.13 img/s | 3.34 ms | 4.46 ms | 5.11 ms | 9.49 ms | -| 16 | 3779.82 img/s | 4.23 ms | 5.83 ms | 7.66 ms | 14.44 ms | -| 32 | 3620.18 img/s | 8.84 ms | 17.90 ms | 22.31 ms | 30.91 ms | -| 64 | 4592.08 img/s | 13.94 ms | 24.00 ms | 29.38 ms | 41.41 ms | -| 128 | 5064.06 img/s | 25.28 ms | 31.73 ms | 37.79 ms | 53.01 ms | -| 256 | 4774.61 img/s | 53.62 ms | 59.04 ms | 67.29 ms | 80.51 ms | +| 1 | 1195.76 img/s | 0.83 ms | 0.84 ms | 0.95 ms | 0.96 ms | +| 2 | 2121.44 img/s | 0.94 ms | 0.95 ms | 1.05 ms | 1.10 ms | +| 4 | 3498.59 img/s | 1.14 ms | 1.14 ms | 1.26 ms | 1.30 ms | +| 8 | 5139.91 img/s | 1.55 ms | 1.56 ms | 1.67 ms | 1.72 ms | +| 16 | 6322.78 img/s | 2.53 ms | 2.54 ms | 2.64 ms | 2.83 ms | +| 32 | 7093.70 img/s | 4.51 ms | 4.61 ms | 4.64 ms | 4.70 ms | +| 64 | 7682.36 img/s | 8.33 ms | 8.44 ms | 8.48 ms | 8.58 ms | +| 128 | 8072.73 img/s | 15.85 ms | 15.98 ms | 16.04 ms | 16.14 ms | +| 256 | 8393.37 img/s | 30.50 ms | 30.67 ms | 30.70 ms | 30.84 ms | + +**INT8 Inference Latency** +|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| +|--------------|------------------|---------------|---------------|---------------|---------------| +| 1 | 1346.83 img/s | 0.74 ms | 0.74 ms | 0.85 ms | 0.87 ms | +| 2 | 2415.06 img/s | 0.83 ms | 0.83 ms | 0.94 ms | 0.99 ms | +| 4 | 4152.29 img/s | 0.96 ms | 0.97 ms | 1.07 ms | 1.11 ms | +| 8 | 6684.53 img/s | 1.20 ms | 1.20 ms | 1.31 ms | 1.37 ms | +| 16 | 9336.11 img/s | 1.71 ms | 1.72 ms | 1.82 ms | 1.89 ms | +| 32 | 11544.88 img/s | 2.77 ms | 2.77 ms | 2.88 ms | 3.09 ms | +| 64 | 12954.16 img/s | 4.94 ms | 5.04 ms | 5.08 ms | 5.23 ms | +| 128 | 13914.60 img/s | 9.20 ms | 9.27 ms | 9.34 ms | 9.45 ms | +| 256 | 14443.15 img/s | 17.72 ms | 17.87 ms | 17.92 ms | 18.00 ms | #### Paddle-TRT performance: NVIDIA A10 (1x A10 24GB) Our results for Paddle-TRT were obtained by running the `inference.py` script on NVIDIA A10 with (1x A10 24G) GPU. +Note that the benchmark does not include data preprocessing. Refer to [Benchmark with TensorRT](#benchmark-with-tensorrt). + **TF32 Inference Latency** |**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| |--------------|------------------|---------------|---------------|---------------|---------------| -| 1 | 372.04 img/s | 2.69 ms | 3.64 ms | 4.20 ms | 5.28 ms | -| 2 | 615.93 img/s | 3.25 ms | 4.08 ms | 4.59 ms | 6.42 ms | -| 4 | 1070.02 img/s | 3.74 ms | 3.90 ms | 4.35 ms | 7.48 ms | -| 8 | 1396.88 img/s | 5.73 ms | 6.87 ms | 7.52 ms | 10.63 ms | -| 16 | 1522.20 img/s | 10.51 ms | 12.73 ms | 13.84 ms | 17.84 ms | -| 32 | 1674.39 img/s | 19.11 ms | 23.23 ms | 24.63 ms | 29.55 ms | -| 64 | 1782.14 img/s | 35.91 ms | 41.84 ms | 44.53 ms | 48.94 ms | -| 128 | 1722.33 img/s | 74.32 ms | 85.37 ms | 89.27 ms | 94.85 ms | -| 256 | 1576.89 img/s | 162.34 ms | 181.01 ms | 185.92 ms | 194.42 ms | +| 1 | 601.39 img/s | 1.66 ms | 1.66 ms | 1.82 ms | 1.85 ms | +| 2 | 962.31 img/s | 2.08 ms | 2.13 ms | 2.23 ms | 2.38 ms | +| 4 | 1338.26 img/s | 2.99 ms | 3.04 ms | 3.14 ms | 3.32 ms | +| 8 | 1650.56 img/s | 4.85 ms | 4.93 ms | 5.01 ms | 5.14 ms | +| 16 | 2116.53 img/s | 7.56 ms | 7.64 ms | 7.71 ms | 7.84 ms | +| 32 | 2316.43 img/s | 13.81 ms | 14.00 ms | 14.07 ms | 14.26 ms | +| 64 | 2477.26 img/s | 25.83 ms | 26.05 ms | 26.15 ms | 26.35 ms | +| 128 | 2528.92 img/s | 50.61 ms | 51.24 ms | 51.37 ms | 51.72 ms | +| 256 | 2576.08 img/s | 99.37 ms | 100.45 ms | 100.66 ms | 101.05 ms | **FP16 Inference Latency** |**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| |--------------|------------------|---------------|---------------|---------------|---------------| -| 1 | 365.38 img/s | 2.74 ms | 3.94 ms | 4.35 ms | 5.64 ms | -| 2 | 612.52 img/s | 3.26 ms | 4.34 ms | 4.80 ms | 6.97 ms | -| 4 | 1018.15 img/s | 3.93 ms | 4.95 ms | 5.55 ms | 9.16 ms | -| 8 | 1924.26 img/s | 4.16 ms | 5.44 ms | 6.20 ms | 11.89 ms | -| 16 | 2477.49 img/s | 6.46 ms | 8.07 ms | 9.21 ms | 15.05 ms | -| 32 | 2896.01 img/s | 11.05 ms | 13.56 ms | 15.32 ms | 21.76 ms | -| 64 | 3165.27 img/s | 20.22 ms | 24.20 ms | 25.94 ms | 33.18 ms | -| 128 | 3176.46 img/s | 40.29 ms | 46.36 ms | 49.15 ms | 54.95 ms | -| 256 | 3110.01 img/s | 82.31 ms | 93.21 ms | 96.06 ms | 99.97 ms | +| 1 | 1109.59 img/s | 0.90 ms | 0.90 ms | 1.06 ms | 1.08 ms | +| 2 | 1901.53 img/s | 1.05 ms | 1.05 ms | 1.22 ms | 1.23 ms | +| 4 | 2733.20 img/s | 1.46 ms | 1.48 ms | 1.62 ms | 1.65 ms | +| 8 | 3494.23 img/s | 2.29 ms | 2.32 ms | 2.44 ms | 2.48 ms | +| 16 | 4113.53 img/s | 3.89 ms | 3.99 ms | 4.10 ms | 4.17 ms | +| 32 | 4714.63 img/s | 6.79 ms | 6.98 ms | 7.14 ms | 7.30 ms | +| 64 | 5054.70 img/s | 12.66 ms | 12.78 ms | 12.83 ms | 13.08 ms | +| 128 | 5261.98 img/s | 24.32 ms | 24.58 ms | 24.71 ms | 24.96 ms | +| 256 | 5397.53 img/s | 47.43 ms | 47.83 ms | 47.95 ms | 48.17 ms | + +**INT8 Inference Latency** + +|**Batch Size**|**Avg throughput**|**Avg latency**|**90% Latency**|**95% Latency**|**99% Latency**| +|--------------|------------------|---------------|---------------|---------------|---------------| +| 1 | 1285.15 img/s | 0.78 ms | 0.78 ms | 0.93 ms | 0.95 ms | +| 2 | 2293.43 img/s | 0.87 ms | 0.88 ms | 1.03 ms | 1.05 ms | +| 4 | 3508.39 img/s | 1.14 ms | 1.15 ms | 1.29 ms | 1.32 ms | +| 8 | 5907.02 img/s | 1.35 ms | 1.36 ms | 1.51 ms | 1.60 ms | +| 16 | 7416.99 img/s | 2.16 ms | 2.19 ms | 2.31 ms | 2.36 ms | +| 32 | 8337.02 img/s | 3.84 ms | 3.91 ms | 4.01 ms | 4.14 ms | +| 64 | 9039.71 img/s | 7.08 ms | 7.24 ms | 7.40 ms | 7.66 ms | +| 128 | 9387.23 img/s | 13.63 ms | 13.84 ms | 13.92 ms | 14.11 ms | +| 256 | 9598.97 img/s | 26.67 ms | 27.12 ms | 27.24 ms | 27.48 ms | ## Release notes @@ -975,6 +1110,11 @@ Our results for Paddle-TRT were obtained by running the `inference.py` script on * Updated README * A100 convergence benchmark +3. December 2023 + * Add quantization aware training + * Add INT8 inference for Paddle-TRT + * Simplify the inference process + ### Known issues * Allreduce issues to top1 and top5 accuracy in evaluation. Workaround: use `build_strategy.fix_op_run_order = True` for eval program. (refer to [Paddle-issue-39567](https://github.com/PaddlePaddle/Paddle/issues/39567) for details) diff --git a/PaddlePaddle/Classification/RN50v1.5/dali.py b/PaddlePaddle/Classification/RN50v1.5/dali.py index 3f4a4def8..e1f99ce16 100644 --- a/PaddlePaddle/Classification/RN50v1.5/dali.py +++ b/PaddlePaddle/Classification/RN50v1.5/dali.py @@ -12,10 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +import ctypes import os from dataclasses import dataclass +from cuda import cudart import paddle +import numpy as np +from nvidia.dali.backend import TensorListCPU import nvidia.dali.ops as ops +import nvidia.dali.fn as fn import nvidia.dali.types as types from nvidia.dali.pipeline import Pipeline from nvidia.dali.plugin.paddle import DALIGenericIterator @@ -236,3 +241,54 @@ def build_dataloader(args, mode): """ assert mode in Mode, "Dataset mode should be in supported Modes (train or eval)" return dali_dataloader(args, mode, paddle.device.get_device()) + + +def dali_synthetic_dataloader(args, device): + """ + Define a dali dataloader with synthetic data. + + Args: + args(Namespace): Arguments obtained from ArgumentParser. + device(int): Id of GPU to load data. + Outputs: + DALIGenericIterator(nvidia.dali.plugin.paddle.DALIGenericIterator) + Iteratable outputs of DALI pipeline, + including "data" in type of Paddle's Tensor. + """ + assert "gpu" in device, "gpu training is required for DALI" + + device_id = int(device.split(':')[1]) + + batch_size = args.batch_size + image_shape = args.image_shape + output_dtype = types.FLOAT16 if args.dali_output_fp16 else types.FLOAT + num_threads = args.dali_num_threads + + class ExternalInputIterator(object): + def __init__(self, batch_size, image_shape): + n_bytes = int(batch_size * np.prod(image_shape) * 4) + err, mem = cudart.cudaMallocHost(n_bytes) + assert err == cudart.cudaError_t.cudaSuccess + mem_ptr = ctypes.cast(mem, ctypes.POINTER(ctypes.c_float)) + self.synthetic_data = np.ctypeslib.as_array(mem_ptr, shape=(batch_size, *image_shape)) + self.n = args.benchmark_steps + + def __iter__(self): + self.i = 0 + return self + + def __next__(self): + if self.i >= self.n: + self.__iter__() + raise StopIteration() + self.i += 1 + return TensorListCPU(self.synthetic_data, is_pinned=True) + + eli = ExternalInputIterator(batch_size, image_shape) + pipe = Pipeline(batch_size=batch_size, num_threads=num_threads, device_id=device_id) + with pipe: + images = fn.external_source(source=eli, no_copy=True, dtype=output_dtype) + images = images.gpu() + pipe.set_outputs(images) + pipe.build() + return DALIGenericIterator([pipe], ['data']) diff --git a/PaddlePaddle/Classification/RN50v1.5/export_model.py b/PaddlePaddle/Classification/RN50v1.5/export_model.py deleted file mode 100644 index dac24d3e8..000000000 --- a/PaddlePaddle/Classification/RN50v1.5/export_model.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2022 NVIDIA Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import logging -import paddle -import program -from dali import build_dataloader -from utils.mode import Mode -from utils.save_load import init_ckpt -from utils.logger import setup_dllogger -from utils.config import parse_args, print_args - - -def main(args): - ''' - Export saved model params to paddle inference model - ''' - setup_dllogger(args.trt_export_log_path) - if args.show_config: - print_args(args) - - eval_dataloader = build_dataloader(args, Mode.EVAL) - - startup_prog = paddle.static.Program() - eval_prog = paddle.static.Program() - - eval_fetchs, _, eval_feeds, _ = program.build( - args, - eval_prog, - startup_prog, - step_each_epoch=len(eval_dataloader), - is_train=False) - eval_prog = eval_prog.clone(for_test=True) - - device = paddle.set_device('gpu') - exe = paddle.static.Executor(device) - exe.run(startup_prog) - - path_to_ckpt = args.from_checkpoint - - if path_to_ckpt is None: - logging.warning( - 'The --from-checkpoint is not set, model weights will not be initialize.' - ) - else: - init_ckpt(path_to_ckpt, eval_prog, exe) - logging.info('Checkpoint path is %s', path_to_ckpt) - - save_inference_dir = args.trt_inference_dir - paddle.static.save_inference_model( - path_prefix=os.path.join(save_inference_dir, args.model_arch_name), - feed_vars=[eval_feeds['data']], - fetch_vars=[eval_fetchs['label'][0]], - executor=exe, - program=eval_prog) - - logging.info('Successully export inference model to %s', - save_inference_dir) - - -if __name__ == '__main__': - paddle.enable_static() - main(parse_args(including_trt=True)) diff --git a/PaddlePaddle/Classification/RN50v1.5/inference.py b/PaddlePaddle/Classification/RN50v1.5/inference.py index fe2e0c812..bad6ccac9 100644 --- a/PaddlePaddle/Classification/RN50v1.5/inference.py +++ b/PaddlePaddle/Classification/RN50v1.5/inference.py @@ -22,14 +22,14 @@ from paddle.fluid import LoDTensor from paddle.inference import Config, PrecisionType, create_predictor -from dali import dali_dataloader +from dali import dali_dataloader, dali_synthetic_dataloader from utils.config import parse_args, print_args from utils.mode import Mode from utils.logger import setup_dllogger def init_predictor(args): - infer_dir = args.trt_inference_dir + infer_dir = args.inference_dir assert os.path.isdir( infer_dir), f'inference_dir = "{infer_dir}" is not a directory' pdiparams_path = glob.glob(os.path.join(infer_dir, '*.pdiparams')) @@ -40,8 +40,8 @@ def init_predictor(args): f'There should be only 1 pdmodel in {infer_dir}, but there are {len(pdmodel_path)}' predictor_config = Config(pdmodel_path[0], pdiparams_path[0]) predictor_config.enable_memory_optim() - predictor_config.enable_use_gpu(0, 0) - precision = args.trt_precision + predictor_config.enable_use_gpu(0, args.device) + precision = args.precision max_batch_size = args.batch_size assert precision in ['FP32', 'FP16', 'INT8'], \ 'precision should be FP32/FP16/INT8' @@ -54,12 +54,17 @@ def init_predictor(args): else: raise NotImplementedError predictor_config.enable_tensorrt_engine( - workspace_size=args.trt_workspace_size, + workspace_size=args.workspace_size, max_batch_size=max_batch_size, - min_subgraph_size=args.trt_min_subgraph_size, + min_subgraph_size=args.min_subgraph_size, precision_mode=precision_mode, - use_static=args.trt_use_static, - use_calib_mode=args.trt_use_calib_mode) + use_static=args.use_static, + use_calib_mode=args.use_calib_mode) + predictor_config.set_trt_dynamic_shape_info( + {"data": (1,) + tuple(args.image_shape)}, + {"data": (args.batch_size,) + tuple(args.image_shape)}, + {"data": (args.batch_size,) + tuple(args.image_shape)}, + ) predictor = create_predictor(predictor_config) return predictor @@ -106,14 +111,14 @@ def benchmark_dataset(args): """ predictor = init_predictor(args) - dali_iter = dali_dataloader(args, Mode.EVAL, 'gpu:0') + dali_iter = dali_dataloader(args, Mode.EVAL, 'gpu:' + str(args.device)) # Warmup some samples for the stable performance number batch_size = args.batch_size image_shape = args.image_shape - image = np.zeros((batch_size, *image_shape)).astype(np.single) + images = np.zeros((batch_size, *image_shape)).astype(np.float32) for _ in range(args.benchmark_warmup_steps): - predict(predictor, [image])[0] + predict(predictor, [images])[0] total_images = 0 correct_predict = 0 @@ -127,8 +132,8 @@ def benchmark_dataset(args): label = np.asarray(data['label']) total_images += label.shape[0] label = label.flatten() - image = data['data'] - predict_label = predict(predictor, [image])[0] + images = data['data'] + predict_label = predict(predictor, [images])[0] correct_predict += (label == predict_label).sum() batch_end_time_step = time.perf_counter() batch_latency = batch_end_time_step - last_time_step @@ -140,7 +145,7 @@ def benchmark_dataset(args): quantile = np.quantile(latency, [0.9, 0.95, 0.99]) statistics = { - 'precision': args.trt_precision, + 'precision': args.precision, 'batch_size': batch_size, 'throughput': total_images / (end - start), 'accuracy': correct_predict / total_images, @@ -152,29 +157,33 @@ def benchmark_dataset(args): return statistics -def benchmark_synthat(args): +def benchmark_synthetic(args): """ - Benchmark on the synthatic data and bypass all pre-processing. + Benchmark on the synthetic data and bypass all pre-processing. The host to device copy is still included. This used to find the upper throughput bound when tunning the full input pipeline. """ predictor = init_predictor(args) + dali_iter = dali_synthetic_dataloader(args, 'gpu:' + str(args.device)) + batch_size = args.batch_size image_shape = args.image_shape - image = np.random.random((batch_size, *image_shape)).astype(np.single) + images = np.random.random((batch_size, *image_shape)).astype(np.float32) latency = [] # warmup for _ in range(args.benchmark_warmup_steps): - predict(predictor, [image])[0] + predict(predictor, [images])[0] # benchmark start = time.perf_counter() last_time_step = time.perf_counter() - for _ in range(args.benchmark_steps): - predict(predictor, [image])[0] + for dali_data in dali_iter: + for data in dali_data: + images = data['data'] + predict(predictor, [images])[0] batch_end_time_step = time.perf_counter() batch_latency = batch_end_time_step - last_time_step latency.append(batch_latency) @@ -185,7 +194,7 @@ def benchmark_synthat(args): quantile = np.quantile(latency, [0.9, 0.95, 0.99]) statistics = { - 'precision': args.trt_precision, + 'precision': args.precision, 'batch_size': batch_size, 'throughput': args.benchmark_steps * batch_size / (end - start), 'eval_latency_avg': np.mean(latency), @@ -195,14 +204,13 @@ def benchmark_synthat(args): } return statistics - def main(args): - setup_dllogger(args.trt_log_path) + setup_dllogger(args.report_file) if args.show_config: print_args(args) - if args.trt_use_synthat: - statistics = benchmark_synthat(args) + if args.use_synthetic: + statistics = benchmark_synthetic(args) else: statistics = benchmark_dataset(args) @@ -210,4 +218,4 @@ def main(args): if __name__ == '__main__': - main(parse_args(including_trt=True)) + main(parse_args(script='inference')) diff --git a/PaddlePaddle/Classification/RN50v1.5/program.py b/PaddlePaddle/Classification/RN50v1.5/program.py index 6dcba59a2..ec16c727d 100644 --- a/PaddlePaddle/Classification/RN50v1.5/program.py +++ b/PaddlePaddle/Classification/RN50v1.5/program.py @@ -12,26 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -import time import logging - +import time from profile import Profiler + +import dllogger +import models import numpy as np -from optimizer import build_optimizer from lr_scheduler import build_lr_scheduler +from optimizer import build_optimizer from utils.misc import AverageMeter from utils.mode import Mode, RunScope from utils.utility import get_num_trainers -import models - -import dllogger import paddle import paddle.nn.functional as F from paddle.distributed import fleet from paddle.distributed.fleet import DistributedStrategy -from paddle.static import sparsity from paddle.distributed.fleet.meta_optimizers.common import CollectiveHelper +from paddle.incubate import asp as sparsity def create_feeds(image_shape): @@ -45,11 +44,13 @@ def create_feeds(image_shape): key (string): Name of variable to feed. Value (tuple): paddle.static.data. """ - feeds = dict() + feeds = {} feeds['data'] = paddle.static.data( - name="data", shape=[None] + image_shape, dtype="float32") + name="data", shape=[None] + image_shape, dtype="float32" + ) feeds['label'] = paddle.static.data( - name="label", shape=[None, 1], dtype="int64") + name="label", shape=[None, 1], dtype="int64" + ) return feeds @@ -70,7 +71,7 @@ def create_fetchs(out, feeds, class_num, label_smoothing=0, mode=Mode.TRAIN): key (string): Name of variable to fetch. Value (tuple): (variable, AverageMeter). """ - fetchs = dict() + fetchs = {} target = paddle.reshape(feeds['label'], [-1, 1]) if mode == Mode.TRAIN: @@ -78,8 +79,7 @@ def create_fetchs(out, feeds, class_num, label_smoothing=0, mode=Mode.TRAIN): loss = F.cross_entropy(out, target) else: label_one_hot = F.one_hot(target, class_num) - soft_target = F.label_smooth( - label_one_hot, epsilon=label_smoothing) + soft_target = F.label_smooth(label_one_hot, epsilon=label_smoothing) soft_target = paddle.reshape(soft_target, shape=[-1, class_num]) log_softmax = -F.log_softmax(out, axis=-1) loss = paddle.sum(log_softmax * soft_target, axis=-1) @@ -94,19 +94,23 @@ def create_fetchs(out, feeds, class_num, label_smoothing=0, mode=Mode.TRAIN): acc_top1 = paddle.metric.accuracy(input=out, label=target, k=1) acc_top5 = paddle.metric.accuracy(input=out, label=target, k=5) - metric_dict = dict() + metric_dict = {} metric_dict["top1"] = acc_top1 metric_dict["top5"] = acc_top5 for key in metric_dict: if mode != Mode.TRAIN and paddle.distributed.get_world_size() > 1: paddle.distributed.all_reduce( - metric_dict[key], op=paddle.distributed.ReduceOp.SUM) - metric_dict[key] = metric_dict[ - key] / paddle.distributed.get_world_size() + metric_dict[key], op=paddle.distributed.ReduceOp.SUM + ) + metric_dict[key] = ( + metric_dict[key] / paddle.distributed.get_world_size() + ) - fetchs[key] = (metric_dict[key], AverageMeter( - key, '7.4f', need_avg=True)) + fetchs[key] = ( + metric_dict[key], + AverageMeter(key, '7.4f', need_avg=True), + ) return fetchs @@ -127,13 +131,16 @@ def create_strategy(args, is_train=True): exec_strategy = paddle.static.ExecutionStrategy() exec_strategy.num_threads = 1 - exec_strategy.num_iteration_per_drop_scope = (10000 if args.amp and - args.use_pure_fp16 else 10) - - paddle.set_flags({ - 'FLAGS_cudnn_exhaustive_search': True, - 'FLAGS_conv_workspace_size_limit': 4096 - }) + exec_strategy.num_iteration_per_drop_scope = ( + 10000 if args.amp and args.use_pure_fp16 else 10 + ) + + paddle.set_flags( + { + 'FLAGS_cudnn_exhaustive_search': True, + 'FLAGS_conv_workspace_size_limit': 4096, + } + ) if not is_train: build_strategy.fix_op_run_order = True @@ -143,6 +150,8 @@ def create_strategy(args, is_train=True): build_strategy.fuse_elewise_add_act_ops = True build_strategy.fuse_bn_add_act_ops = True build_strategy.enable_addto = True + if args.fuse_resunit and is_train: + build_strategy.fuse_resunit = True return build_strategy, exec_strategy @@ -175,10 +184,11 @@ def dist_optimizer(args, optimizer): dist_strategy.amp_configs = { "init_loss_scaling": args.scale_loss, "use_dynamic_loss_scaling": args.use_dynamic_loss_scaling, - "use_pure_fp16": args.use_pure_fp16 + "use_pure_fp16": args.use_pure_fp16, } dist_strategy.asp = args.asp + dist_strategy.qat = args.qat optimizer = fleet.distributed_optimizer(optimizer, strategy=dist_strategy) @@ -221,14 +231,16 @@ def build(args, main_prog, startup_prog, step_each_epoch, is_train=True): input_image_channel=input_image_channel, data_format=data_format, use_pure_fp16=use_pure_fp16, - bn_weight_decay=bn_weight_decay) + bn_weight_decay=bn_weight_decay, + ) out = model(feeds["data"]) fetchs = create_fetchs( - out, feeds, class_num, args.label_smoothing, mode=mode) + out, feeds, class_num, args.label_smoothing, mode=mode + ) if args.asp: - sparsity.set_excluded_layers(main_prog, [model.fc.weight.name]) + sparsity.set_excluded_layers(main_program=main_prog, param_names=[model.fc.weight.name]) lr_scheduler = None optimizer = None @@ -242,10 +254,13 @@ def build(args, main_prog, startup_prog, step_each_epoch, is_train=True): # This is a workaround to "Communicator of ring id 0 has not been initialized.". # Since Paddle's design, the initialization would be done inside train program, # eval_only need to manually call initialization. - if args.run_scope == RunScope.EVAL_ONLY and \ - paddle.distributed.get_world_size() > 1: + if ( + args.run_scope == RunScope.EVAL_ONLY + and paddle.distributed.get_world_size() > 1 + ): collective_helper = CollectiveHelper( - role_maker=fleet.PaddleCloudRoleMaker(is_collective=True)) + role_maker=fleet.PaddleCloudRoleMaker(is_collective=True) + ) collective_helper.update_startup_program(startup_prog) return fetchs, lr_scheduler, feeds, optimizer @@ -268,22 +283,22 @@ def compile_prog(args, program, loss_name=None, is_train=True): build_strategy, exec_strategy = create_strategy(args, is_train) compiled_program = paddle.static.CompiledProgram( - program).with_data_parallel( - loss_name=loss_name, - build_strategy=build_strategy, - exec_strategy=exec_strategy) + program, build_strategy=build_strategy + ) return compiled_program -def run(args, - dataloader, - exe, - program, - fetchs, - epoch, - mode=Mode.TRAIN, - lr_scheduler=None): +def run( + args, + dataloader, + exe, + program, + fetchs, + epoch, + mode=Mode.TRAIN, + lr_scheduler=None, +): """ Execute program. @@ -310,11 +325,11 @@ def run(args, if fetchs[k][1] is not None: metric_dict[k] = fetchs[k][1] - metric_dict["batch_time"] = AverageMeter( - 'batch_time', '.5f', postfix=" s,") + metric_dict["batch_time"] = AverageMeter('batch_time', '.5f', postfix=" s,") metric_dict["data_time"] = AverageMeter('data_time', '.5f', postfix=" s,") metric_dict["compute_time"] = AverageMeter( - 'compute_time', '.5f', postfix=" s,") + 'compute_time', '.5f', postfix=" s," + ) for m in metric_dict.values(): m.reset() @@ -326,8 +341,7 @@ def run(args, batch_size = None latency = [] - total_benchmark_steps = \ - args.benchmark_steps + args.benchmark_warmup_steps + total_benchmark_steps = args.benchmark_steps + args.benchmark_warmup_steps dataloader.reset() while True: @@ -359,11 +373,12 @@ def run(args, batch_size = batch[0]["data"].shape()[0] feed_dict = batch[0] - with profiler.profile_tag(idx, "Training" - if mode == Mode.TRAIN else "Evaluation"): - results = exe.run(program=program, - feed=feed_dict, - fetch_list=fetch_list) + with profiler.profile_tag( + idx, "Training" if mode == Mode.TRAIN else "Evaluation" + ): + results = exe.run( + program=program, feed=feed_dict, fetch_list=fetch_list + ) for name, m in zip(fetchs.keys(), results): if name in metric_dict: @@ -380,15 +395,16 @@ def run(args, tic = time.perf_counter() if idx % args.print_interval == 0: - log_msg = dict() + log_msg = {} log_msg['loss'] = metric_dict['loss'].val.item() log_msg['top1'] = metric_dict['top1'].val.item() log_msg['top5'] = metric_dict['top5'].val.item() log_msg['data_time'] = metric_dict['data_time'].val log_msg['compute_time'] = metric_dict['compute_time'].val log_msg['batch_time'] = metric_dict['batch_time'].val - log_msg['ips'] = \ + log_msg['ips'] = ( batch_size * num_trainers / metric_dict['batch_time'].val + ) if mode == Mode.TRAIN: log_msg['lr'] = metric_dict['lr'].val log_info((epoch, idx), log_msg, mode) @@ -404,10 +420,10 @@ def run(args, logging.info("Begin benchmark at step %d", idx + 1) if idx == total_benchmark_steps: - benchmark_data = dict() - benchmark_data[ - 'ips'] = batch_size * num_trainers / metric_dict[ - 'batch_time'].avg + benchmark_data = {} + benchmark_data['ips'] = ( + batch_size * num_trainers / metric_dict['batch_time'].avg + ) if mode == mode.EVAL: latency = np.array(latency) * 1000 quantile = np.quantile(latency, [0.9, 0.95, 0.99]) @@ -420,15 +436,19 @@ def run(args, logging.info("End benchmark at epoch step %d", idx) return benchmark_data - epoch_data = dict() + epoch_data = {} epoch_data['loss'] = metric_dict['loss'].avg.item() epoch_data['epoch_time'] = metric_dict['batch_time'].total - epoch_data['ips'] = batch_size * num_trainers * \ - metric_dict["batch_time"].count / metric_dict["batch_time"].sum + epoch_data['ips'] = ( + batch_size + * num_trainers + * metric_dict["batch_time"].count + / metric_dict["batch_time"].sum + ) if mode == Mode.EVAL: epoch_data['top1'] = metric_dict['top1'].avg.item() epoch_data['top5'] = metric_dict['top5'].avg.item() - log_info((epoch, ), epoch_data, mode) + log_info((epoch,), epoch_data, mode) return epoch_data @@ -443,7 +463,7 @@ def log_info(step, metrics, mode): mode(utils.Mode): Train or eval mode. """ prefix = 'train' if mode == Mode.TRAIN else 'val' - dllogger_iter_data = dict() + dllogger_iter_data = {} for key in metrics: dllogger_iter_data[f"{prefix}.{key}"] = metrics[key] dllogger.log(step=step, data=dllogger_iter_data) diff --git a/PaddlePaddle/Classification/RN50v1.5/requirements.txt b/PaddlePaddle/Classification/RN50v1.5/requirements.txt index 3a6cbc400..66e17d3a0 100644 --- a/PaddlePaddle/Classification/RN50v1.5/requirements.txt +++ b/PaddlePaddle/Classification/RN50v1.5/requirements.txt @@ -1 +1,2 @@ git+https://github.com/NVIDIA/dllogger@v1.0.0#egg=dllogger +cuda-python==12.0.0 diff --git a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_AMP.sh b/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_AMP.sh index 2d59953ff..7dd68dc40 100644 --- a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_AMP.sh +++ b/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_AMP.sh @@ -14,8 +14,9 @@ python inference.py \ --data-layout NHWC \ - --trt-inference-dir ./inference_amp \ - --trt-precision FP16 \ + --inference-dir ./inference_amp \ + --precision FP16 \ --batch-size 256 \ --benchmark-steps 1024 \ - --benchmark-warmup-steps 16 + --benchmark-warmup-steps 16 \ + --use-synthetic True diff --git a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/export_resnet50_TF32.sh b/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_QAT.sh similarity index 71% rename from PaddlePaddle/Classification/RN50v1.5/scripts/inference/export_resnet50_TF32.sh rename to PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_QAT.sh index 107b1f4f9..bb2858eb7 100644 --- a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/export_resnet50_TF32.sh +++ b/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_QAT.sh @@ -12,10 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -CKPT=${1:-"./output/ResNet50/89"} -MODEL_PREFIX=${2:-"resnet_50_paddle"} - -python -m paddle.distributed.launch --gpus=0 export_model.py \ - --trt-inference-dir ./inference_tf32 \ - --from-checkpoint $CKPT \ - --model-prefix ${MODEL_PREFIX} +python inference.py \ + --data-layout NHWC \ + --inference-dir ./inference_qat \ + --precision INT8 \ + --batch-size 256 \ + --benchmark-steps 1024 \ + --benchmark-warmup-steps 16 \ + --use-synthetic True diff --git a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_TF32.sh b/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_TF32.sh index 559677133..6e55fd0be 100644 --- a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_TF32.sh +++ b/PaddlePaddle/Classification/RN50v1.5/scripts/inference/infer_resnet50_TF32.sh @@ -13,9 +13,10 @@ # limitations under the License. python inference.py \ - --trt-inference-dir ./inference_tf32 \ - --trt-precision FP32 \ + --inference-dir ./inference_tf32 \ + --precision FP32 \ --dali-num-threads 8 \ --batch-size 256 \ --benchmark-steps 1024 \ - --benchmark-warmup-steps 16 + --benchmark-warmup-steps 16 \ + --use-synthetic True diff --git a/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_AMP_90E_DGXA100.sh b/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_AMP_90E_DGXA100.sh index a9badfefe..23c4a4991 100644 --- a/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_AMP_90E_DGXA100.sh +++ b/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_AMP_90E_DGXA100.sh @@ -17,4 +17,6 @@ python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ --amp \ --scale-loss 128.0 \ --use-dynamic-loss-scaling \ - --data-layout NHWC + --data-layout NHWC \ + --fuse-resunit \ + --inference-dir ./inference_amp diff --git a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/export_resnet50_AMP.sh b/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_AMP_QAT_10E_DGXA100.sh similarity index 69% rename from PaddlePaddle/Classification/RN50v1.5/scripts/inference/export_resnet50_AMP.sh rename to PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_AMP_QAT_10E_DGXA100.sh index b1c5676b9..0e7c8f104 100644 --- a/PaddlePaddle/Classification/RN50v1.5/scripts/inference/export_resnet50_AMP.sh +++ b/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_AMP_QAT_10E_DGXA100.sh @@ -15,9 +15,14 @@ CKPT=${1:-"./output/ResNet50/89"} MODEL_PREFIX=${2:-"resnet_50_paddle"} -python -m paddle.distributed.launch --gpus=0 export_model.py \ - --amp \ - --data-layout NHWC \ - --trt-inference-dir ./inference_amp \ - --from-checkpoint ${CKPT} \ - --model-prefix ${MODEL_PREFIX} +python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py \ + --from-pretrained-params ${CKPT} \ + --model-prefix ${MODEL_PREFIX} \ + --epochs 10 \ + --amp \ + --scale-loss 128.0 \ + --use-dynamic-loss-scaling \ + --data-layout NHWC \ + --qat \ + --lr 0.00005 \ + --inference-dir ./inference_qat diff --git a/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_TF32_90E_DGXA100.sh b/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_TF32_90E_DGXA100.sh index 65c87b752..0c5ea7988 100644 --- a/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_TF32_90E_DGXA100.sh +++ b/PaddlePaddle/Classification/RN50v1.5/scripts/training/train_resnet50_TF32_90E_DGXA100.sh @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py --epochs 90 +python -m paddle.distributed.launch --gpus=0,1,2,3,4,5,6,7 train.py --epochs 90 --inference-dir ./inference_tf32 diff --git a/PaddlePaddle/Classification/RN50v1.5/train.py b/PaddlePaddle/Classification/RN50v1.5/train.py index d469534de..28e985135 100644 --- a/PaddlePaddle/Classification/RN50v1.5/train.py +++ b/PaddlePaddle/Classification/RN50v1.5/train.py @@ -12,20 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import logging -import paddle -from paddle.distributed import fleet -from paddle.static import sparsity -from paddle.fluid.contrib.mixed_precision.fp16_utils import rewrite_program -from paddle.fluid.contrib.mixed_precision.fp16_lists import AutoMixedPrecisionLists +import os + from dali import build_dataloader +from utils.affinity import set_cpu_affinity from utils.config import parse_args, print_args from utils.logger import setup_dllogger -from utils.save_load import init_program, save_model -from utils.affinity import set_cpu_affinity from utils.mode import Mode, RunScope +from utils.save_load import init_program, save_model + +import paddle import program +from paddle.distributed import fleet +from paddle.static.amp.fp16_lists import AutoMixedPrecisionLists +from paddle.static.amp.fp16_utils import cast_model_to_fp16 +from paddle.incubate import asp as sparsity +from paddle.static.quantization.quanter import quant_aware class MetricSummary: @@ -35,18 +38,24 @@ def __init__(self): def update(self, new_metrics): if not self.is_updated: - self.metric_dict = dict() + self.metric_dict = {} for key in new_metrics: if key in self.metric_dict: # top1, top5 and ips are "larger is better" if key in ['top1', 'top5', 'ips']: - self.metric_dict[key] = new_metrics[key] if new_metrics[ - key] > self.metric_dict[key] else self.metric_dict[key] + self.metric_dict[key] = ( + new_metrics[key] + if new_metrics[key] > self.metric_dict[key] + else self.metric_dict[key] + ) # Others are "Smaller is better" else: - self.metric_dict[key] = new_metrics[key] if new_metrics[ - key] < self.metric_dict[key] else self.metric_dict[key] + self.metric_dict[key] = ( + new_metrics[key] + if new_metrics[key] < self.metric_dict[key] + else self.metric_dict[key] + ) else: self.metric_dict[key] = new_metrics[key] @@ -89,7 +98,8 @@ def main(args): train_prog, startup_prog, step_each_epoch=train_step_each_epoch, - is_train=True) + is_train=True, + ) eval_dataloader = None eval_prog = None @@ -98,12 +108,13 @@ def main(args): eval_step_each_epoch = len(eval_dataloader) eval_prog = paddle.static.Program() - eval_fetchs, _, _, _ = program.build( + eval_fetchs, _, eval_feeds, _ = program.build( args, eval_prog, startup_prog, step_each_epoch=eval_step_each_epoch, - is_train=False) + is_train=False, + ) # clone to prune some content which is irrelevant in eval_prog eval_prog = eval_prog.clone(for_test=True) @@ -113,23 +124,38 @@ def main(args): init_program( args, exe=exe, - program=train_prog if train_prog is not None else eval_prog) + program=train_prog if train_prog is not None else eval_prog, + ) if args.amp: if args.run_scope == RunScope.EVAL_ONLY: - rewrite_program(eval_prog, amp_lists=AutoMixedPrecisionLists()) + cast_model_to_fp16( + eval_prog, + AutoMixedPrecisionLists(), + use_fp16_guard=False, + level='O1', + ) else: optimizer.amp_init( device, scope=paddle.static.global_scope(), test_program=eval_prog, - use_fp16_test=True) + use_fp16_test=True, + ) if args.asp and args.prune_model: logging.info("Pruning model to 2:4 sparse pattern...") sparsity.prune_model(train_prog, mask_algo=args.mask_algo) logging.info("Pruning model done.") + if args.qat: + if args.run_scope == RunScope.EVAL_ONLY: + eval_prog = quant_aware(eval_prog, device, for_test=True, return_program=True) + else: + optimizer.qat_init( + device, + test_program=eval_prog) + if eval_prog is not None: eval_prog = program.compile_prog(args, eval_prog, is_train=False) @@ -138,28 +164,44 @@ def main(args): for epoch_id in range(args.start_epoch, args.epochs): # Training if train_prog is not None: - metric_summary = program.run(args, train_dataloader, exe, - train_prog, train_fetchs, epoch_id, - Mode.TRAIN, lr_scheduler) + metric_summary = program.run( + args, + train_dataloader, + exe, + train_prog, + train_fetchs, + epoch_id, + Mode.TRAIN, + lr_scheduler, + ) train_summary.update(metric_summary) # Save a checkpoint if epoch_id % args.save_interval == 0: - model_path = os.path.join(args.output_dir, - args.model_arch_name) + model_path = os.path.join(args.checkpoint_dir, args.model_arch_name) save_model(train_prog, model_path, epoch_id, args.model_prefix) # Evaluation - if (eval_prog is not None) and \ - (epoch_id % args.eval_interval == 0): - metric_summary = program.run(args, eval_dataloader, exe, eval_prog, - eval_fetchs, epoch_id, Mode.EVAL) + if (eval_prog is not None) and (epoch_id % args.eval_interval == 0): + metric_summary = program.run( + args, + eval_dataloader, + exe, + eval_prog, + eval_fetchs, + epoch_id, + Mode.EVAL, + ) eval_summary.update(metric_summary) if train_summary.is_updated: - program.log_info(tuple(), train_summary.metric_dict, Mode.TRAIN) + program.log_info((), train_summary.metric_dict, Mode.TRAIN) if eval_summary.is_updated: - program.log_info(tuple(), eval_summary.metric_dict, Mode.EVAL) + program.log_info((), eval_summary.metric_dict, Mode.EVAL) + + if eval_prog is not None: + model_path = os.path.join(args.inference_dir, args.model_arch_name) + paddle.static.save_inference_model(model_path, [eval_feeds['data']], [eval_fetchs['label'][0]], exe, program=eval_prog) if __name__ == '__main__': diff --git a/PaddlePaddle/Classification/RN50v1.5/utils/config.py b/PaddlePaddle/Classification/RN50v1.5/utils/config.py index 3987084e6..3b4b46494 100644 --- a/PaddlePaddle/Classification/RN50v1.5/utils/config.py +++ b/PaddlePaddle/Classification/RN50v1.5/utils/config.py @@ -100,7 +100,8 @@ def print_args(args): args_for_log = copy.deepcopy(args) # Due to dllogger cannot serialize Enum into JSON. - args_for_log.run_scope = args_for_log.run_scope.value + if hasattr(args_for_log, 'run_scope'): + args_for_log.run_scope = args_for_log.run_scope.value dllogger.log(step='PARAMETER', data=vars(args_for_log)) @@ -150,13 +151,19 @@ def check_and_process_args(args): args.eval_interval = 1 -def add_global_args(parser): - group = parser.add_argument_group('Global') +def add_general_args(parser): + group = parser.add_argument_group('General') group.add_argument( - '--output-dir', + '--checkpoint-dir', type=str, - default='./output/', + default='./checkpoint/', help='A path to store trained models.') + group.add_argument( + '--inference-dir', + type=str, + default='./inference/', + help='A path to store inference model once the training is finished.' + ) group.add_argument( '--run-scope', default='train_eval', @@ -188,13 +195,8 @@ def add_global_args(parser): group.add_argument( '--report-file', type=str, - default='./report.json', + default='./train.json', help='A file in which to store JSON experiment report.') - group.add_argument( - '--data-layout', - default='NCHW', - choices=('NCHW', 'NHWC'), - help='Data format. It should be one of {NCHW, NHWC}.') group.add_argument( '--benchmark', action='http://github.com/store_true', help='To enable benchmark mode.') group.add_argument( @@ -276,7 +278,10 @@ def add_advance_args(parser): '--use-pure-fp16', action='http://github.com/store_true', help='Enable pure FP16 training, only be applied when --amp is set.') - + group.add_argument( + '--fuse-resunit', + action='http://github.com/store_true', + help='Enable CUDNNv8 ResUnit fusion, only be applied when --amp is set.') # ASP group.add_argument( '--asp', @@ -295,6 +300,11 @@ def add_advance_args(parser): '{mask_1d, mask_2d_greedy, mask_2d_best}. This only be applied ' \ 'when --asp and --prune-model is set.' ) + # QAT + group.add_argument( + '--qat', + action='http://github.com/store_true', + help='Enable quantization aware training (QAT).') return parser @@ -392,6 +402,11 @@ def add_model_args(parser): type=int, default=1000, help='The number classes of images.') + group.add_argument( + '--data-layout', + default='NCHW', + choices=('NCHW', 'NHWC'), + help='Data format. It should be one of {NCHW, NHWC}.') group.add_argument( '--bn-weight-decay', action='http://github.com/store_true', @@ -445,72 +460,105 @@ def add_training_args(parser): def add_trt_args(parser): + def int_list(x): + return list(map(int, x.split(','))) + group = parser.add_argument_group('Paddle-TRT') group.add_argument( - '--trt-inference-dir', + '--device', + type=int, + default='0', + help='The GPU device id for Paddle-TRT inference.' + ) + group.add_argument( + '--inference-dir', type=str, default='./inference', - help='A path to store/load inference models. ' \ - 'export_model.py would export models to this folder, ' \ - 'then inference.py would load from here.' + help='A path to load inference models.' ) group.add_argument( - '--trt-precision', + '--data-layout', + default='NCHW', + choices=('NCHW', 'NHWC'), + help='Data format. It should be one of {NCHW, NHWC}.') + group.add_argument( + '--precision', default='FP32', choices=('FP32', 'FP16', 'INT8'), help='The precision of TensorRT. It should be one of {FP32, FP16, INT8}.' ) group.add_argument( - '--trt-workspace-size', + '--workspace-size', type=int, default=(1 << 30), help='The memory workspace of TensorRT in MB.') group.add_argument( - '--trt-min-subgraph-size', + '--min-subgraph-size', type=int, default=3, help='The minimal subgraph size to enable PaddleTRT.') group.add_argument( - '--trt-use-static', + '--use-static', type=distutils.util.strtobool, default=False, help='Fix TensorRT engine at first running.') group.add_argument( - '--trt-use-calib-mode', + '--use-calib-mode', type=distutils.util.strtobool, default=False, help='Use the PTQ calibration of PaddleTRT int8.') group.add_argument( - '--trt-export-log-path', - type=str, - default='./export.json', - help='A file in which to store JSON model exporting report.') - group.add_argument( - '--trt-log-path', + '--report-file', type=str, default='./inference.json', help='A file in which to store JSON inference report.') group.add_argument( - '--trt-use-synthat', + '--use-synthetic', type=distutils.util.strtobool, default=False, help='Apply synthetic data for benchmark.') + group.add_argument( + '--benchmark-steps', + type=int, + default=100, + help='Steps for benchmark run, only be applied when --benchmark is set.' + ) + group.add_argument( + '--benchmark-warmup-steps', + type=int, + default=100, + help='Warmup steps for benchmark run, only be applied when --benchmark is set.' + ) + group.add_argument( + '--show-config', + type=distutils.util.strtobool, + default=True, + help='To show arguments.') return parser -def parse_args(including_trt=False): +def parse_args(script='train'): + assert script in ['train', 'inference'] parser = argparse.ArgumentParser( - description="PaddlePaddle RN50v1.5 training script", + description=f'PaddlePaddle RN50v1.5 {script} script', formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser = add_global_args(parser) - parser = add_dataset_args(parser) - parser = add_model_args(parser) - parser = add_training_args(parser) - parser = add_advance_args(parser) - - if including_trt: + if script == 'train': + parser = add_general_args(parser) + parser = add_dataset_args(parser) + parser = add_model_args(parser) + parser = add_training_args(parser) + parser = add_advance_args(parser) + args = parser.parse_args() + check_and_process_args(args) + else: parser = add_trt_args(parser) + parser = add_dataset_args(parser) + args = parser.parse_args() + # Precess image layout and channel + args.image_channel = args.image_shape[0] + if args.data_layout == "NHWC": + args.image_shape = [ + args.image_shape[1], args.image_shape[2], args.image_shape[0] + ] - args = parser.parse_args() - check_and_process_args(args) return args diff --git a/PaddlePaddle/LanguageModeling/BERT/Dockerfile b/PaddlePaddle/LanguageModeling/BERT/Dockerfile index de3f7feb1..d7f0d43f5 100644 --- a/PaddlePaddle/LanguageModeling/BERT/Dockerfile +++ b/PaddlePaddle/LanguageModeling/BERT/Dockerfile @@ -1,15 +1,20 @@ -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/paddlepaddle:22.08-py3 - +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/paddlepaddle:23.06-py3 FROM ${FROM_IMAGE_NAME} - RUN apt-get update && apt-get install -y pbzip2 pv bzip2 cabextract ENV BERT_PREP_WORKING_DIR /workspace/bert/data -ADD requirements.txt /workspace/ + WORKDIR /workspace/ -RUN pip install --no-cache-dir -r requirements.txt -RUN git clone https://github.com/attardi/wikiextractor.git && cd wikiextractor && git checkout 6408a430fc504a38b04d37ce5e7fc740191dee16 && cd .. -RUN git clone https://github.com/soskek/bookcorpus.git -ADD . /workspace/bert WORKDIR /workspace/bert +RUN pip install --no-cache-dir \ + tqdm boto3 requests six ipdb h5py nltk progressbar tokenizers>=0.7\ + git+https://github.com/NVIDIA/dllogger wget + +RUN apt-get install -y iputils-ping + +COPY . . + +RUN apt-get install -y libjemalloc-dev +RUN pip install git+https://github.com/NVIDIA/lddl.git +RUN python -m nltk.downloader punkt diff --git a/PaddlePaddle/LanguageModeling/BERT/README.md b/PaddlePaddle/LanguageModeling/BERT/README.md index 69ff2cc86..b7b059c76 100644 --- a/PaddlePaddle/LanguageModeling/BERT/README.md +++ b/PaddlePaddle/LanguageModeling/BERT/README.md @@ -20,7 +20,8 @@ This repository provides a script and recipe to train the BERT model for PaddleP * [Scripts and sample code](#scripts-and-sample-code) * [Parameters](#parameters) * [Pre-training parameters](#pre-training-parameters) - * [Fine tuning parameters](#fine-tuning-parameters) + * [Fine tuning parameters](#fine-tuning-parameters) + * [Multi-node](#multi-node) * [Command-line options](#command-line-options) * [Getting the data](#getting-the-data) * [Dataset guidelines](#dataset-guidelines) @@ -43,6 +44,7 @@ This repository provides a script and recipe to train the BERT model for PaddleP * [Training performance results](#training-performance-results) * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-dgx-a100-8x-a100-80gb) * [Pre-training NVIDIA DGX A100 (8x A100 80GB)](#pre-training-nvidia-dgx-a100-8x-a100-80gb) + * [Pre-training NVIDIA DGX A100 (8x A100 80GB) Multi-node Scaling](#pre-training-nvidia-dgx-a100-8x-a100-80gb-multi-node-scaling) * [Fine-tuning NVIDIA DGX A100 (8x A100 80GB)](#fine-tuning-nvidia-dgx-a100-8x-a100-80gb) * [Inference performance results](#inference-performance-results) * [Inference performance: NVIDIA DGX A100 (1x A100 80GB)](#inference-performance-nvidia-dgx-a100-1x-a100-80gb) @@ -105,13 +107,17 @@ The following features are supported by this model. | [Paddle AMP](https://www.paddlepaddle.org.cn/documentation/docs/en/guides/performance_improving/amp_en.html) | Yes | | [Paddle Fleet](https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/distributed/fleet/Fleet_en.html#fleet) | Yes | | [LAMB](https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/optimizer/Lamb_en.html) | Yes | +| [LDDL](https://github.com/NVIDIA/LDDL) | Yes | +| Multi-node | Yes | #### Features [Fleet](https://www.paddlepaddle.org.cn/documentation/docs/en/api/paddle/distributed/fleet/Fleet_en.html#fleet) is a unified API for distributed training of PaddlePaddle. [LAMB](https://arxiv.org/pdf/1904.00962.pdf) stands for Layerwise Adaptive Moments based optimizer, which is a large batch optimization technique that helps accelerate the training of deep neural networks using large minibatches. It allows using a global batch size of 65536 and 32768 on sequence lengths 128 and 512, respectively, compared to a batch size of 256 for [Adam](https://arxiv.org/pdf/1412.6980.pdf). The optimized implementation accumulates 1024 gradient batches in phase 1 and 4096 steps in phase 2 before updating weights once. This results in a 15% training speedup. On multi-node systems, LAMB allows scaling up to 1024 GPUs resulting in training speedups of up to 72x in comparison to Adam. Adam has limitations on the learning rate that can be used since it is applied globally on all parameters, whereas LAMB follows a layerwise learning rate strategy. - + +[LDDL](https://github.com/NVIDIA/LDDL) is a library that enables scalable data preprocessing and loading. LDDL is used by this PaddlePaddle BERT example. + ### Mixed precision training @@ -193,7 +199,7 @@ The following section lists the requirements you need to meet to start training This repository contains a Dockerfile that extends the CUDA NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: * [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -* [PaddlePaddle 22.08-py3 NGC container](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/paddlepaddle) or newer +* [PaddlePaddle 22.12-py3 NGC container](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/paddlepaddle) or newer * Supported GPUs: * [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) @@ -204,7 +210,11 @@ DGX Documentation: * [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/dgx/user-guide/index.html#accessing_registry) For those unable to use the PaddlePaddle NGC container, to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/dgx/support-matrix/index.html). + +For multi-node, the sample provided in this repository requires [Enroot](https://github.com/NVIDIA/enroot) and [Pyxis](https://github.com/NVIDIA/pyxis) set up on a [SLURM](https://slurm.schedmd.com) cluster. +More information on how to set up and launch can be found in the [Multi-node Documentation](https://docs.nvidia.com/ngc/multi-node-bert-user-guide). + ## Quick Start Guide @@ -218,7 +228,10 @@ cd DeepLearningExamples/PaddlePaddle/LanguageModeling/BERT ``` 2. Download the NVIDIA pre-trained checkpoint. -Pre-trained checkpoints link is coming soon. +If you want to use a pre-trained checkpoint, visit [NGC](https://catalog.ngc.nvidia.com/orgs/nvidia/teams/dle/models/bert_large_paddle_ckpt_mode-pretrain/files). This pre-trained checkpoint is used to fine-tune on SQuAD. Ensure you unzip the downloaded file and place the checkpoint in the `checkpoints/` folder. For a checkpoint already fine-tuned for QA on SQuAD v1.1 visit [NGC](https://catalog.ngc.nvidia.com/orgs/nvidia/teams/dle/models/bert_large_paddle_ckpt_mode-qa_ds-squad11/files). + + + 3. Build BERT on top of the NGC container. ``` @@ -235,36 +248,23 @@ By default: - Paddle native logs are stored in the `log/` folder. - DLLogger's outputs are stored in the `results/` folder. -5. Download and preprocess the dataset. +5. Download the dataset. This repository provides scripts to download, verify, and extract the following datasets: -- [SQuAD](https://rajpurkar.github.io/SQuAD-explorer/) (fine-tuning for question answering) -- Wikipedia (pre-training) -- BookCorpus (pre-training) +- [SQuAD](https://rajpurkar.github.io/SQuAD-explorer/) (fine-tuning for question answering) +- Wikipedia (pre-training) + -To download, verify, extract the datasets, and create the shards in `.hdf5` format, run: +To download, verify, extract the datasets, run: ```shell bash data/create_datasets_from_start.sh ``` -Note: For fine tuning only, Wikipedia and Bookscorpus dataset download and preprocessing can be skipped by commenting it out. +Note: For fine-tuning only, downloading the Wikipedia dataset can be skipped by commenting it out. -- Download Wikipedia only for pretraining - -The pretraining dataset is 170GB+ and takes 15+ hours to download. The BookCorpus server, most of the time, gets overloaded and contains broken links resulting in HTTP 403 and 503 errors. Hence, it is recommended to skip downloading BookCorpus data by running: -```shell -bash data/create_datasets_from_start.sh wiki_only -``` - -- Download Wikipedia and BookCorpus - -Users are welcome to download BookCorpus from other sources to match our accuracy or repeatedly try our script until the required number of files are downloaded by running the following: -```shell -bash data/create_datasets_from_start.sh wiki_books -``` - -Note: Ensure a complete Wikipedia download. If, in any case, the download breaks, remove the output file `wikicorpus_en.xml.bz2` and start again. If a partially downloaded file exists, the script assumes a successful download, which causes the extraction to fail. Not using BookCorpus can potentially change the final accuracy on a few downstream tasks. +Note: Ensure a complete Wikipedia download. But if the download failed in LDDL, +remove the output directory `data/wikipedia/` and start over again. 6. Start pre-training. @@ -276,16 +276,18 @@ bash scripts/run_pretraining.sh The default hyperparameters are set to run on 8x A100 80G cards. +To run on multiple nodes, refer to the [Multi-node](#multi-node) section. + 7. Start fine-tuning with the SQuAD dataset. The above pre-trained BERT representations can be fine-tuned with just one additional output layer for a state-of-the-art question answering system. Running the following script launches fine-tuning for question answering with the SQuAD dataset. ``` -bash scripts/run_squad.sh +bash scripts/run_squad.sh /workspace/bert/checkpoints/ ``` 8. Start validation/evaluation. -For SQuAD, validation can be performed with the `bash scripts/run_squad.sh `, setting `mode` to `eval` in `scripts/run_squad.sh` as follows: +For SQuAD, validation can be performed with the `bash scripts/run_squad.sh /workspace/bert/checkpoints/`, setting `mode` to `eval` in `scripts/run_squad.sh` as follows: ``` mode=${12:-"eval"} @@ -293,7 +295,7 @@ mode=${12:-"eval"} 9. Start inference/predictions. -Inference can be performed with the `bash scripts/run_squad.sh `, setting `mode` to `prediction` in `scripts/run_squad.sh` as follows: +Inference can be performed with the `bash scripts/run_squad.sh /workspace/bert/checkpoints/`, setting `mode` to `prediction` in `scripts/run_squad.sh` as follows: ``` mode=${12:-"prediction"} @@ -366,6 +368,8 @@ The complete list of the available parameters for the `run_pretraining.py` scrip Global: --input-dir INPUT_DIR The input data directory. Should be specified by users and contain .hdf5 files for the task. (default: None) + --vocab-file VOCAB_FILE + Vocabulary mapping/file BERT was pretrainined on. (default: None) --output-dir OUTPUT_DIR The output directory where the model checkpoints will be written. Should be specified by users. (default: None) --bert-model {bert-base-uncased,bert-base-cased,bert-large-uncased,bert-large-cased,custom} @@ -433,6 +437,7 @@ Advanced Training: --use-dynamic-loss-scaling Enable dynamic loss scaling in AMP training, only applied when --amp is set. (default: False) --use-pure-fp16 Enable pure FP16 training, only applied when --amp is set. (default: False) + --fuse-mha Enable multihead attention fusion. Require cudnn version >= 8.9.1. ``` @@ -459,6 +464,7 @@ Default arguments are listed below in the order `scripts/run_squad.sh` expects: - Enable benchmark - The default is `false`. - Benchmark steps - The default is `100`. - Benchmark warmup steps - The default is `100`. +- Fuse MHA fusion - The default is `true` The script saves the final checkpoint to the `/results/bert-large-uncased/squad` folder. @@ -466,6 +472,24 @@ Note: - For SQuAD fine-tuning, `<--max-steps>` is not required since it's usually trained for two or three epochs. If `<--max-steps>` is not set or set to -1, it will be trained for `<--epochs>` epochs. If `<--max-steps>` is set to a positive number, the total training steps is calculated by: `total_steps = min(max_steps, epochs * steps_per_epoch)`. - For pre-training, `<--max-steps>` is required and `<--epochs>` is deprecated. Because We typically train for a specified number of steps rather than epochs. +#### Multi-node +Multi-node runs can be launched on a pyxis/enroot Slurm cluster (refer to [Requirements](#requirements)) with the `run.sub` script with the following command for a 4-node DGX-A100 example for both phase 1 and phase 2: + +``` +TRAIN_BATCH_SIZE=256 GRADIENT_ACCUMULATION_STEPS=8 PHASE=1 sbatch -N4 run.sub +TRAIN_BATCH_SIZE=32 GRADIENT_ACCUMULATION_STEPS=32 PHASE=2 sbatch -N4 run.sub +``` + +Checkpoints after phase 1 will be saved in `checkpointdir` specified in `run.sub`. The checkpoint will be automatically picked up to resume training on phase 2. Note that phase 2 should be run after phase 1. + + +The batch variables `BATCHSIZE`, `GRADIENT_STEPS`,`PHASE` refer to the Python arguments `--batch-size`, `--gradient-merge-steps`, `--phase1/--phase2` respectively. + +Note that the `run.sub` script is a starting point that has to be adapted depending on the environment. In particular, variables such as `datadir` handle the location of the files for each phase. + +Refer to the file’s contents to find the full list of variables to adjust for your system. + + ### Command-line options To view the full list of available options and their descriptions, use the `-h` or `--help` command-line option, for example: @@ -477,27 +501,25 @@ To view the full list of available options and their descriptions, use the `-h` Detailed descriptions of command-line options can be found in the [Parameters](#parameters) section. ### Getting the data -For pre-training BERT, we use the concatenation of Wikipedia (2500M words) and BookCorpus (800M words). For Wikipedia, we extract only the text passages and ignore headers, lists, and tables. BERT requires that datasets are structured as a document-level corpus rather than a shuffled sentence-level corpus because it is critical to extract long contiguous sentences. - -The preparation of the pre-training dataset is described in the `bertPrep.py` script found in the `data/` folder. The component steps in the automated scripts to prepare the datasets are as follows: - -1. Data download and extract - the dataset is downloaded and extracted. - -2. Clean and format - document tags, and so on. are removed from the dataset. - -3. Sentence segmentation - the corpus text file is processed into separate sentences. - -4. Sharding - the sentence segmented corpus file is split into a number of uniformly distributed smaller text documents. - -5. `hdf5` file creation - each text file shard is processed by the `create_pretraining_data.py` script to produce a corresponding `hdf5` file. The script generates input data and labels for masked language modeling and sentence prediction tasks for the input text shard. - -The tools used for preparing the BookCorpus and Wikipedia datasets can be applied to prepare an arbitrary corpus. The `create_datasets_from_start.sh` script in the `data/` directory applies sentence segmentation, sharding, and `hdf5` file creation given an arbitrary text file containing a document-separated text corpus. - -For fine-tuning a pre-trained BERT model for specific tasks, by default this repository prepares the following dataset: + +For pre-training BERT, we use the Wikipedia (2500M words) dataset. We extract +only the text passages and ignore headers, lists, and tables. BERT requires that +datasets are structured as a document level corpus rather than a shuffled +sentence-level corpus because it is critical to extract long contiguous +sentences. `data/create_datasets_from_start.sh` uses the LDDL downloader to +download the Wikipedia dataset, and `scripts/run_pretraining.sh` uses the LDDL +preprocessor and load balancer to preprocess the Wikipedia dataset into Parquet +shards which are then streamed during the pre-training by the LDDL data loader. +Refer to [LDDL's README](https://github.com/NVIDIA/LDDL/blob/main/README.md) for more +information on how to use LDDL. Depending on the speed of your internet +connection, downloading and extracting the Wikipedia dataset takes a few hours, +and running the LDDL preprocessor and load balancer takes half an hour on a +single DGXA100 node. + +For fine-tuning a pre-trained BERT model for specific tasks, by default, this repository prepares the following dataset: - [SQuAD](https://rajpurkar.github.io/SQuAD-explorer/): for question answering - -Depending on the speed of your internet connection, this process takes about a day to complete. The BookCorpus server could sometimes get overloaded and also contain broken links resulting in HTTP 403 and 503 errors. You can either skip the missing files or retry downloading at a later time. + #### Dataset guidelines @@ -511,8 +533,6 @@ BERT pre-training optimizes for two unsupervised classification tasks. The first The second task is next sentence prediction. One training instance of BERT pre-training is two sentences (a sentence pair). A sentence pair may be constructed by simply taking two adjacent sentences from a single document or by pairing up two random sentences with equal probability. The goal of this task is to predict whether or not the second sentence followed the first in the original document. -The `create_pretraining_data.py` script takes in raw text and creates training instances for both pre-training tasks. - ### Training process @@ -522,7 +542,7 @@ The training process consists of two steps: pre-training and fine-tuning. Pre-training is performed using the `run_pretraining.py` script along with parameters defined in the `scripts/run_pretraining.sh`. -The `run_pretraining.sh` script runs a job on a single node that trains the BERT-large model from scratch using Wikipedia and BookCorpus datasets as training data using the LAMB optimizer. By default, the training script runs two phases of training with a hyperparameter recipe specific to 8x A100 80G cards: +The `run_pretraining.sh` script runs a job on a single node that trains the BERT-large model from scratch using Wikipedia datasets as training data using the LAMB optimizer. By default, the training script runs two phases of training with a hyperparameter recipe specific to 8x A100 80G cards: Phase 1: (Maximum sequence length of 128) - Runs on 8 GPUs with a training batch size of 256 per GPU. @@ -565,10 +585,18 @@ bash run_pretraining.sh \ \ \ \ + \ + \ + \ + \ + \ + \ + \ \ \ \ - + \ + ``` Where: @@ -593,8 +621,16 @@ Where: - `` is the root path to bert code. - `` is the path to the checkpoint to start the pretraining routine on (Usually a BERT pre-trained checkpoint). +- `wikipedia_source` is the path to the 'source' subdirectory for the Wikipedia corpus. +- `num_dask_workers` is the number of dask workers to preprocess the bert dataset. +- `num_shards_per_workers` is the number of the output parquet/txt shards per worker. +- `num_workers` is the number of workers for dataloading. +- `sample_ratio` is the ratio of how many articles/documents are sampled from each corpus. +- `phase2_bin_size` is the stride of the sequence length for each binbin size for phase2. +- `masking` LDDL supports both static and dynamic masking. Refer to [LDDL's README](https://github.com/NVIDIA/LDDL/blob/main/README.md) for more information. - `` is the path to the bert config file. - `` a flag to enable benchmark. The train process will warmup for `` and then measure the throughput of the following ``. +- `` a flag to enable cuDNN MHA fusion. Note that: - If users follow [Quick Start Guide](#quick-start-guide) to set up container and dataset, there is no need to set any parameters. For example: @@ -609,7 +645,10 @@ bash scripts/run_pretraining.sh \ /path/to/dataset/phase1 \ /path/to/dataset/phase2 \ /workspace/bert \ - None None false + None \ + /path/to/wikipedia/source \ + 32 128 4 0.9 64 static \ + None false ``` To run the pre-training routine on an initial checkpoint, point the `from-checkpoint` variable to the location of the checkpoint folder in `scripts/run_pretraining.sh`. @@ -622,6 +661,7 @@ python3 -m paddle.distributed.launch \ --gpus="0,1,2,3,4,5,6,7" \ ./run_pretraining.py \ --input-dir=/path/to/dataset/phase1 \ + --vocab-file=vocab/bert-large-uncased-vocab.txt \ --output-dir=./results \ --bert-model=bert-large-uncased \ --from-checkpoint=./results/bert-large-uncased/phase1 \ @@ -634,6 +674,7 @@ python3 -m paddle.distributed.launch \ --max-predictions-per-seq=20 \ --gradient-merge-steps=32 \ --amp \ + --fuse-mha \ --use-dynamic-loss-scaling \ --optimizer=Lamb \ --phase1 \ @@ -733,7 +774,8 @@ bash scripts/run_squad.sh \ \ \ \ - + \ + ``` By default, the `mode` argument is set to `train eval`. Refer to the [Quick Start Guide](#quick-start-guide) for explanations of each positional argument. @@ -773,7 +815,10 @@ bash scripts/run_pretraining.sh \ /path/to/dataset/phase1 \ /path/to/dataset/phase2 \ /workspace/bert \ - None None true 10 10 + None \ + /path/to/wikipedia/source \ + 32 128 4 0.9 64 static \ + None true 10 10 true ``` To benchmark the training performance on a specific batch size for SQuAD, refer to [Fine-tuning](#fine-tuning) and turn on the `` flags. An example call to run training for 200 steps (100 steps for warmup and 100 steps to measure), and generate throughput numbers: @@ -786,7 +831,7 @@ bash scripts/run_squad.sh \ results/checkpoints \ train \ bert_configs/bert-large-uncased.json \ - -1 true 100 100 + -1 true 100 100 true ``` #### Inference performance benchmark @@ -802,7 +847,8 @@ bash scripts/run_squad.sh \ \ eval \ \ - + \ + ``` An example call to run inference and generate throughput numbers: @@ -815,7 +861,7 @@ bash scripts/run_squad.sh \ results/checkpoints \ eval \ bert_configs/bert-large-uncased.json \ - -1 true 100 100 + -1 true 100 100 true ``` @@ -831,8 +877,8 @@ Our results were obtained by running the `scripts/run_squad.sh` and `scripts/run | DGX System | GPUs / Node | Precision | Accumulated Batch size / GPU (Phase 1 and Phase 2) | Accumulation steps (Phase 1 and Phase 2) | Final Loss | Time to train(hours) | Time to train speedup (TF32 to mixed precision) | |--------------------|-------------|-----------|----------------------------------------------------|------------------------------------------|-------------------|----------------------|-------------------------------------------------| -| 1 x DGX A100 80GB | 8 | AMP | 256 and 32 | 32 and 128 | 1.409 | ~ 50 hours | 1.72 | -| 1 x DGX A100 80GB | 8 | TF32 | 128 and 16 | 64 and 256 | 1.421 | ~ 86 hours | 1 | +| 32 x DGX A100 80GB | 8 | AMP | 256 and 128 | 1 and 4 | 1.409 | ~ 1.1 hours | 2.27 | +| 32 x DGX A100 80GB | 8 | TF32 | 128 and 16b | 2 and 8 | 1.421 | ~ 2.5 hours | 1 | ##### Pre-training loss curves @@ -869,16 +915,34 @@ Training stability with 8 GPUs, FP16 computations, batch size of 32: ##### Training performance: NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the script `run_pretraining.sh` in the PaddlePaddle:22.08-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in sequences per second) were averaged over a few training iterations. +Our results were obtained by running the script `run_pretraining.sh` in the PaddlePaddle:22.12-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in sequences per second) were averaged over a few training iterations. ###### Pre-training NVIDIA DGX A100 (8x A100 80GB) | GPUs | Batch size / GPU (TF32 and FP16) | Accumulation steps (TF32 and FP16) | Sequence length | Throughput - TF32(sequences/sec) | Throughput - mixed precision(sequences/sec) | Throughput speedup (TF32 - mixed precision) | Weak scaling - TF32 | Weak scaling - mixed precision | |------|----------------------------------|------------------------------------|-----------------|----------------------------------|---------------------------------------------|---------------------------------------------|---------------------|--------------------------------| -| 1 | 8192 and 8192 | 64 and 32 | 128 | 304 | 529 | 1.74 | 1.00 | 1.00 | -| 8 | 8192 and 8192 | 64 and 32 | 128 | 2410 | 4200 | 1.74 | 7.93 | 7.94 | -| 1 | 4096 and 4096 | 256 and 128 | 512 | 59 | 103 | 1.75 | 1.00 | 1.00 | -| 8 | 4096 and 4096 | 256 and 128 | 512 | 469 | 823 | 1.75 | 7.95 | 7.99 | +| 1 | 8192 and 8192 | 64 and 32 | 128 | 307 | 694 | 2.26 | 1.00 | 1.00 | +| 8 | 8192 and 8192 | 64 and 32 | 128 | 2428 | 5541 | 2.28 | 7.91 | 7.98 | +| 1 | 4096 and 4096 | 256 and 128 | 512 | 107 | 264 | 2.47 | 1.00 | 1.00 | +| 8 | 4096 and 4096 | 256 and 128 | 512 | 851 | 2109 | 2.48 | 7.95 | 7.99 | + + +###### Pre-training NVIDIA DGX A100 (8x A100 80GB) Multi-node Scaling + +| Nodes | GPUs / node | Batch size / GPU (TF32 and FP16) | Accumulated Batch size / GPU (TF32 and FP16) | Accumulation steps (TF32 and FP16) | Sequence length | Mixed Precision Throughput | Mixed Precision Strong Scaling | TF32 Throughput | TF32 Strong Scaling | Speedup (Mixed Precision to TF32) | +|-------|-------------|----------------------------------|------------------------------------|-----------------|----------------------------|--------------------------------|-----------------|---------------------|-----------------------------------|-----| +| 1 | 8 | 126 and 256 | 8192 and 8192 | 64 and 32 | 128 | 5541 | 1 | 2428 | 1 | 2.28 | +| 2 | 8 | 126 and 256 | 4096 and 4096 | 32 and 16 | 128 | 10646 | 1.92 | 4638 | 1.91 | 2.29 | +| 4 | 8 | 126 and 256 | 2048 and 2048 | 16 and 8 | 128 | 21389 | 3.86 | 9445 | 3.89 | 2.26 | +| 8 | 8 | 126 and 256 | 1024 and 1024 | 8 and 4 | 128 | 41681 | 7.52 | 18335 | 7.55 | 2.27 | +| 16 | 8 | 126 and 256 | 512 and 512 | 4 and 2 | 128 | 79023 | 14.26 | 35526 | 14.63 | 2.22 | +| 32 | 8 | 126 and 256 | 256 and 256 | 2 and 1 | 128 | 157952 | 28.51 | 69701 | 28.71 | 2.27 | +| 1 | 8 | 16 and 32 | 4096 and 4096 | 256 and 128 | 512 | 2109 | 1 | 851 | 1 | 2.48 | +| 2 | 8 | 16 and 32 | 2048 and 2048 | 128 and 64 | 512 | 4051 | 1.92 | 1601 | 1.88 | 2.53 | +| 4 | 8 | 16 and 32 | 1024 and 1024 | 64 and 32 | 512 | 7972 | 3.78 | 3240 | 3.81 | 2.46 | +| 8 | 8 | 16 and 32 | 512 and 512 | 32 and 16 | 512 | 15760 | 7.47 | 6329 | 7.44 | 2.49 | +| 16 | 8 | 16 and 32 | 256 and 256 | 16 and 8 | 512 | 31129 | 14.76 | 12273 | 14.42 | 2.54 | +| 32 | 8 | 16 and 32 | 128 and 128 | 8 and 4 | 512 | 60206 | 28.55 | 24047 | 28.26 | 2.50 | ###### Fine-tuning NVIDIA DGX A100 (8x A100 80GB) @@ -887,8 +951,8 @@ Our results were obtained by running the script `run_pretraining.sh` in the Padd | GPUs | Batch size / GPU (TF32 and FP16) | Throughput - TF32(sequences/sec) | Throughput - mixed precision(sequences/sec) | Throughput speedup (TF32 - mixed precision) | Weak scaling - TF32 | Weak scaling - mixed precision | |------|----------------------------------|----------------------------------|---------------------------------------------|---------------------------------------------|---------------------|--------------------------------| -| 1 | 32 and 32 | 83 | 120 | 1.45 | 1.00 | 1.00 | -| 8 | 32 and 32 | 629 | 876 | 1.39 | 7.59 | 7.30 | +| 1 | 32 and 32 | 83 | 123 | 1.48 | 1.00 | 1.00 | +| 8 | 32 and 32 | 629 | 929 | 1.48 | 7.59 | 7.55 | #### Inference performance results @@ -912,7 +976,11 @@ The inference performance metrics used were items/second. ## Release notes ### Changelog - + +January 2023 +- [Pre-training using Language Datasets and Data Loaders (LDDL)](https://github.com/NVIDIA/LDDL) +- Binned pretraining for phase2 with LDDL using a bin size of 64 + August 2022 - Pre-training support with LAMB optimizer. - Updated Data download and Preprocessing. @@ -922,6 +990,13 @@ August 2022 - SQuAD finetune support with AdamW optimizer. - Updated accuracy and performance tables tested on A100. - Initial release. + +March 2023 +- Pre-training using [Language Datasets and Data Loaders (LDDL)](https://github.com/NVIDIA/LDDL) +- Binned pretraining for phase2 with LDDL using a bin size of 64 + +July 2023 +- Optimize AMP training with cuDNN fused dot product attention kernel. ### Known issues diff --git a/PaddlePaddle/LanguageModeling/BERT/data/create_datasets_from_start.sh b/PaddlePaddle/LanguageModeling/BERT/data/create_datasets_from_start.sh index 72557ed7e..5caff41e2 100644 --- a/PaddlePaddle/LanguageModeling/BERT/data/create_datasets_from_start.sh +++ b/PaddlePaddle/LanguageModeling/BERT/data/create_datasets_from_start.sh @@ -13,36 +13,5 @@ # limitations under the License. #Download -to_download=${1:-"wiki_only"} - -#Download -if [ "$to_download" = "wiki_books" ] ; then - python3 /workspace/bert/data/bertPrep.py --action download --dataset bookscorpus -fi - -python3 /workspace/bert/data/bertPrep.py --action download --dataset wikicorpus_en +download_wikipedia --outdir ${BERT_PREP_WORKING_DIR}/wikipedia/ python3 /workspace/bert/data/bertPrep.py --action download --dataset squad - -# Properly format the text files -if [ "$to_download" = "wiki_books" ] ; then - python3 /workspace/bert/data/bertPrep.py --action text_formatting --dataset bookscorpus -fi -python3 /workspace/bert/data/bertPrep.py --action text_formatting --dataset wikicorpus_en - -if [ "$to_download" = "wiki_books" ] ; then - DATASET="books_wiki_en_corpus" -else - DATASET="wikicorpus_en" - # Shard the text files -fi - -# Shard the text files -python3 /workspace/bert/data/bertPrep.py --action sharding --dataset $DATASET - -# Create HDF5 files Phase 1 -python3 /workspace/bert/data/bertPrep.py --action create_hdf5_files --dataset $DATASET --max_seq_length 128 \ ---max_predictions_per_seq 20 --vocab_file /workspace/bert/vocab/bert-large-uncased-vocab.txt --do_lower_case 1 - -# Create HDF5 files Phase 2 -python3 /workspace/bert/data/bertPrep.py --action create_hdf5_files --dataset $DATASET --max_seq_length 512 \ ---max_predictions_per_seq 80 --vocab_file /workspace/bert/vocab/bert-large-uncased-vocab.txt --do_lower_case 1 diff --git a/PaddlePaddle/LanguageModeling/BERT/loss.py b/PaddlePaddle/LanguageModeling/BERT/loss.py index 6d8a6c529..73594ccdf 100644 --- a/PaddlePaddle/LanguageModeling/BERT/loss.py +++ b/PaddlePaddle/LanguageModeling/BERT/loss.py @@ -13,7 +13,6 @@ # limitations under the License. import paddle -import paddle.nn.functional as F class CrossEntropyLossForSQuAD(paddle.nn.Layer): @@ -53,7 +52,7 @@ def __init__(self, vocab_size): self.vocab_size = vocab_size def forward(self, prediction_scores, seq_relationship_score, - masked_lm_labels, next_sentence_labels, masked_lm_scale): + masked_lm_labels, next_sentence_labels): """ Args: prediction_scores(Tensor): @@ -80,12 +79,11 @@ def forward(self, prediction_scores, seq_relationship_score, Its data type should be float32 and its shape is [1]. """ with paddle.static.amp.fp16_guard(): - masked_lm_loss = F.cross_entropy( - prediction_scores, - masked_lm_labels, - reduction='none', - ignore_index=-1) - masked_lm_loss = masked_lm_loss / masked_lm_scale - next_sentence_loss = F.cross_entropy( - seq_relationship_score, next_sentence_labels, reduction='none') - return paddle.sum(masked_lm_loss) + paddle.mean(next_sentence_loss) + masked_lm_labels_flat = masked_lm_labels.reshape([-1]) + mlm_labels = masked_lm_labels_flat[masked_lm_labels_flat != -1] + masked_lm_loss = self.loss_fn(prediction_scores, mlm_labels) + if next_sentence_labels.ndim == 1: + next_sentence_labels = next_sentence_labels.unsqueeze(axis=-1) + next_sentence_loss = self.loss_fn(seq_relationship_score, + next_sentence_labels) + return masked_lm_loss + next_sentence_loss diff --git a/PaddlePaddle/LanguageModeling/BERT/modeling.py b/PaddlePaddle/LanguageModeling/BERT/modeling.py index a8650694e..423542d63 100644 --- a/PaddlePaddle/LanguageModeling/BERT/modeling.py +++ b/PaddlePaddle/LanguageModeling/BERT/modeling.py @@ -89,17 +89,15 @@ def __init__(self, bert_config): self.layer_norm = nn.LayerNorm(bert_config.hidden_size, epsilon=1e-12) self.dropout = nn.Dropout(bert_config.hidden_dropout_prob) - def forward(self, input_ids, token_type_ids=None, position_ids=None): + def forward(self, input_ids, token_type_ids=None): """ Args: See class `BertModel`. """ - if position_ids is None: - ones = paddle.ones_like(input_ids, dtype="int64") - seq_length = paddle.cumsum(ones, axis=-1) - - position_ids = seq_length - ones - position_ids.stop_gradient = True + ones = paddle.ones_like(input_ids, dtype="int64") + seq_length = paddle.cumsum(ones, axis=-1) + position_ids = seq_length - ones + position_ids.stop_gradient = True if token_type_ids is None: token_type_ids = paddle.zeros_like(input_ids, dtype="int64") @@ -175,17 +173,13 @@ def __init__(self, bert_config): activation=bert_config.hidden_act, attn_dropout=bert_config.attention_probs_dropout_prob, act_dropout=0, - enable_cudnn=False) + fuse_qkv=bert_config.fuse_mha) self.encoder = nn.TransformerEncoder(encoder_layer, bert_config.num_hidden_layers) self.pooler = BertPooler(bert_config.hidden_size) - def forward(self, - input_ids, - token_type_ids=None, - position_ids=None, - attention_mask=None): + def forward(self, input_ids, token_type_ids=None, attention_mask=None): """ Args: input_ids(Tensor): @@ -198,11 +192,6 @@ def forward(self, to a `sentence A` and type 1 corresponds to a `sentence B` token. (see BERT paper for more details). Its data type should be `int64` Defaults: None, which means we don't add segment embeddings. - position_ids(Tensor, optional): - An optional Tensor of shape [batch_size, num_tokens] with the position - indices of each input sequence tokens in the position embeddings. - Selected in the range [0, max_position_embeddings - 1]. - Its data type should be `int64`. Defaults: None. attention_mask(Tensor, optional): An optional Tensor of shape [batch_size, sequence_length] with indices of mask used in multi-head attention to avoid performing attention on to some @@ -234,9 +223,7 @@ def forward(self, attention_mask = attention_mask.unsqueeze(axis=[1, 2]) embedding_output = self.embeddings( - input_ids=input_ids, - position_ids=position_ids, - token_type_ids=token_type_ids) + input_ids=input_ids, token_type_ids=token_type_ids) if self.fuse: encoder_output = embedding_output @@ -263,11 +250,7 @@ def __init__(self, bert_config): self.bert = BertModel(bert_config) self.classifier = nn.Linear(bert_config.hidden_size, 2) - def forward(self, - input_ids, - token_type_ids=None, - position_ids=None, - attention_mask=None): + def forward(self, input_ids, token_type_ids=None, attention_mask=None): """ Args: See class `BertModel`. @@ -282,7 +265,6 @@ def forward(self, encoder_output, _ = self.bert( input_ids, token_type_ids=token_type_ids, - position_ids=position_ids, attention_mask=attention_mask) logits = self.classifier(encoder_output) @@ -322,13 +304,7 @@ def __init__(self, self.decoder_bias = self.create_parameter( shape=[vocab_size], dtype=self.decoder_weight.dtype, is_bias=True) - def forward(self, hidden_states, masked_positions=None): - if masked_positions is not None: - hidden_states = paddle.reshape(hidden_states, - [-1, hidden_states.shape[-1]]) - hidden_states = paddle.tensor.gather(hidden_states, - masked_positions) - # gather masked tokens might be more quick + def forward(self, hidden_states): hidden_states = self.transform(hidden_states) hidden_states = self.activation(hidden_states) hidden_states = self.layer_norm(hidden_states) @@ -362,7 +338,7 @@ def __init__(self, activation, embedding_weights) self.seq_relationship = nn.Linear(hidden_size, 2) - def forward(self, encoder_output, pooled_output, masked_positions=None): + def forward(self, encoder_output, pooled_output, masked_lm_labels): """ Args: sequence_output(Tensor): @@ -384,7 +360,12 @@ def forward(self, encoder_output, pooled_output, masked_positions=None): A Tensor of shape [batch_size, 2] with the scores of next sentence prediction. Its data type should be float32. """ - prediction_scores = self.predictions(encoder_output, masked_positions) + + sequence_flattened = paddle.index_select( + encoder_output.reshape([-1, encoder_output.shape[-1]]), + paddle.nonzero(masked_lm_labels.reshape([-1]) != -1).squeeze(), + axis=0) + prediction_scores = self.predictions(sequence_flattened) seq_relationship_score = self.seq_relationship(pooled_output) return prediction_scores, seq_relationship_score @@ -406,18 +387,13 @@ def __init__(self, bert_config): bert_config.hidden_act, embedding_weights=self.bert.embeddings.word_embeddings.weight) - def forward(self, - input_ids, - token_type_ids=None, - position_ids=None, - attention_mask=None, - masked_positions=None): + def forward(self, input_ids, token_type_ids, attention_mask, + masked_lm_labels): """ Args: input_ids(Tensor): See class `BertModel`. token_type_ids(Tensor, optional): See class `BertModel`. - position_ids(Tensor, optional): See class `BertModel`. attention_mask(Tensor, optional): See class `BertModel`. masked_positions(Tensor, optional): See class `BertPretrainingHeads`. @@ -434,9 +410,8 @@ def forward(self, outputs = self.bert( input_ids, token_type_ids=token_type_ids, - position_ids=position_ids, attention_mask=attention_mask) sequence_output, pooled_output = outputs[:2] prediction_scores, seq_relationship_score = self.cls( - sequence_output, pooled_output, masked_positions) + sequence_output, pooled_output, masked_lm_labels) return prediction_scores, seq_relationship_score diff --git a/PaddlePaddle/LanguageModeling/BERT/pretraining_dataset.py b/PaddlePaddle/LanguageModeling/BERT/pretraining_dataset.py deleted file mode 100644 index 66e69b66a..000000000 --- a/PaddlePaddle/LanguageModeling/BERT/pretraining_dataset.py +++ /dev/null @@ -1,169 +0,0 @@ -# Copyright (c) 2022 NVIDIA Corporation. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import random -import h5py -import numpy as np -import paddle -from paddle.io import DataLoader, Dataset -from utils.collate import Stack - - -def create_pretraining_dataset(args, - input_file, - data_holders, - worker_init=None, - places=None): - train_data = PretrainingDataset( - input_file=input_file, max_pred_length=args.max_predictions_per_seq) - train_batch_sampler = paddle.io.BatchSampler( - train_data, batch_size=args.batch_size, shuffle=True) - - def _collate_data(data, stack_fn=Stack()): - num_fields = len(data[0]) - out = [None] * num_fields - [ - input_ids, segment_ids, input_mask, masked_lm_positions, - masked_lm_labels, next_sentence_labels, masked_lm_scale - ] = [0, 1, 2, 3, 4, 5, 6] - for i in (input_ids, segment_ids, input_mask, next_sentence_labels): - out[i] = stack_fn([x[i] for x in data]) - _, seq_length = out[input_ids].shape - size = sum(len(x[masked_lm_positions]) for x in data) - if size % 8 != 0: - size += 8 - (size % 8) - out[masked_lm_positions] = np.full(size, 0, dtype=np.int32) - out[masked_lm_labels] = np.full([size, 1], -1, dtype=np.int64) - mask_token_num = 0 - for i, x in enumerate(data): - for j, pos in enumerate(x[masked_lm_positions]): - out[masked_lm_positions][mask_token_num] = i * seq_length + pos - out[masked_lm_labels][mask_token_num] = x[masked_lm_labels][j] - mask_token_num += 1 - # The value of masked_lm_scale is equal to mask_token_num, - # which would be used to compute average masked_lm_loss. - out.append(np.asarray([mask_token_num], dtype=np.float32)) - if args.amp and args.use_pure_fp16: - #out[input_mask] = out[input_mask].astype(np.float16) - out[masked_lm_scale] = out[masked_lm_scale].astype(np.float16) - return out - - train_data_loader = DataLoader( - dataset=train_data, - places=places, - feed_list=data_holders, - batch_sampler=train_batch_sampler, - collate_fn=_collate_data, - num_workers=0, - worker_init_fn=worker_init, - return_list=False) - - return train_data_loader - - -def create_pretraining_data_holder(): - input_ids = paddle.static.data( - name="input_ids", shape=[-1, -1], dtype="int64") - segment_ids = paddle.static.data( - name="segment_ids", shape=[-1, -1], dtype="int64") - input_mask = paddle.static.data( - name="input_mask", shape=[-1, 1, 1, -1], dtype="int64") - masked_lm_positions = paddle.static.data( - name="masked_lm_positions", shape=[-1], dtype="int32") - masked_lm_labels = paddle.static.data( - name="masked_lm_labels", shape=[-1, 1], dtype="int64") - next_sentence_labels = paddle.static.data( - name="next_sentence_labels", shape=[-1, 1], dtype="int64") - masked_lm_scale = paddle.static.data( - name="masked_lm_scale", shape=[-1, 1], dtype="float32") - return [ - input_ids, segment_ids, input_mask, masked_lm_positions, - masked_lm_labels, next_sentence_labels, masked_lm_scale - ] - - -def select_dataset_file_for_each_worker(files, f_start_id, num_trainers, - trainer_id): - """ - Spliting the train file according to the worker index. - """ - num_files = len(files) - if num_trainers > num_files: - remainder = num_trainers % num_files - data_file = files[( - f_start_id * num_trainers + trainer_id + remainder * f_start_id) % - num_files] - else: - data_file = files[(f_start_id * num_trainers + trainer_id) % num_files] - return data_file - - -class WorkerInitObj: - "Construct the object with different seed, and the Dataloader will generate the data " - "with different seed in each worker." - - def __init__(self, seed): - self.seed = seed - - def __call__(self, pid): - np.random.seed(seed=self.seed + pid) - random.seed(self.seed + pid) - - -class PretrainingDataset(Dataset): - def __init__(self, input_file, max_pred_length): - self.input_file = input_file - self.max_pred_length = max_pred_length - f = h5py.File(input_file, "r") - keys = [ - 'input_ids', 'input_mask', 'segment_ids', 'masked_lm_positions', - 'masked_lm_ids', 'next_sentence_labels' - ] - self.inputs = [np.asarray(f[key][:]) for key in keys] - f.close() - - def __len__(self): - 'Denotes the total number of samples' - return len(self.inputs[0]) - - def __getitem__(self, index): - # convert next_sentence_labels (index=5) to np.ndarray type - [ - input_ids, input_mask, segment_ids, masked_lm_positions, - masked_lm_ids, next_sentence_labels - ] = [ - input[index].astype(np.int64) - if indice < 5 else np.asarray(input[index].astype(np.int64)) - for indice, input in enumerate(self.inputs) - ] - # input_mask = (1 - np.reshape( - # input_mask.astype(np.float32), [1, 1, input_mask.shape[0]])) * -1e4 - input_mask = np.reshape(input_mask, [1, 1, input_mask.shape[0]]) - - index = self.max_pred_length - padded_mask_indices = (masked_lm_positions == 0).nonzero()[0] - if len(padded_mask_indices) != 0: - index = padded_mask_indices[0].item() - else: - index = self.max_pred_length - masked_lm_labels = masked_lm_ids[:index] - masked_lm_positions = masked_lm_positions[:index] - # softmax_with_cross_entropy enforce last dim size equal 1 - masked_lm_labels = np.expand_dims(masked_lm_labels, axis=-1) - next_sentence_labels = np.expand_dims(next_sentence_labels, axis=-1) - - return [ - input_ids, segment_ids, input_mask, masked_lm_positions, - masked_lm_labels, next_sentence_labels - ] diff --git a/PaddlePaddle/LanguageModeling/BERT/program.py b/PaddlePaddle/LanguageModeling/BERT/program.py index 4c1d17afa..2e46d01e3 100644 --- a/PaddlePaddle/LanguageModeling/BERT/program.py +++ b/PaddlePaddle/LanguageModeling/BERT/program.py @@ -12,29 +12,44 @@ # See the License for the specific language governing permissions and # limitations under the License. -from concurrent.futures import ThreadPoolExecutor import os import time import logging import shutil -import numpy as np import paddle import paddle.distributed.fleet as fleet from modeling import BertForPretraining, BertConfig from loss import BertPretrainingCriterion from utils.save_load import save_model -from utils.utility import get_num_trainers, get_trainer_id +from utils.utility import get_trainer_id from lr_scheduler import build_lr_scheduler from optimizer import build_optimizer -from pretraining_dataset import create_pretraining_dataset, select_dataset_file_for_each_worker, WorkerInitObj import dllogger -def create_strategy(use_distributed_fused_lamb=False): +def create_pretraining_data_holder(): + input_ids = paddle.static.data( + name="input_ids", shape=[-1, -1], dtype="int64") + token_type_ids = paddle.static.data( + name="token_type_ids", shape=[-1, -1], dtype="int64") + attention_mask = paddle.static.data( + name="attention_mask", shape=[-1, 1, 1, -1], dtype="int64") + next_sentence_labels = paddle.static.data( + name="next_sentence_labels", shape=[-1, 1], dtype="int64") + masked_lm_labels = paddle.static.data( + name="masked_lm_labels", shape=[-1, -1], dtype="int64") + return [ + input_ids, token_type_ids, attention_mask, next_sentence_labels, + masked_lm_labels + ] + + +def create_strategy(args, use_distributed_fused_lamb=False): """ Create paddle.static.BuildStrategy and paddle.static.ExecutionStrategy with arguments. Args: + args(Namespace): Arguments obtained from ArgumentParser. use_distributed_fused_lamb(bool, optional): Whether to use distributed fused lamb. Returns: build_strategy(paddle.static.BuildStrategy): A instance of BuildStrategy. @@ -44,6 +59,9 @@ def create_strategy(use_distributed_fused_lamb=False): exec_strategy = paddle.static.ExecutionStrategy() build_strategy.enable_addto = True + if args.amp: + build_strategy.fuse_gemm_epilogue = True + build_strategy.fuse_dot_product_attention = args.fuse_mha if use_distributed_fused_lamb: build_strategy.fuse_all_reduce_ops = False @@ -69,7 +87,8 @@ def dist_optimizer(args, optimizer): optimizer(fleet.distributed_optimizer): A distributed optimizer. """ use_distributed_fused_lamb = True if args.optimizer == 'DistributedFusedLamb' else False - build_strategy, exec_strategy = create_strategy(use_distributed_fused_lamb) + build_strategy, exec_strategy = create_strategy(args, + use_distributed_fused_lamb) dist_strategy = fleet.DistributedStrategy() if use_distributed_fused_lamb: @@ -111,45 +130,47 @@ def dist_optimizer(args, optimizer): return optimizer -def build(args, main_prog, startup_prog, feeds, is_train=True): +def build(args, main_prog, startup_prog, is_train=True): """ Build a executable paddle.static.Program via following 3 steps: - 1. Create model. - 2. Create loss. - 3. Create optimizer if is_train==True. + 1. Create feeds. + 2. Create model. + 3. Create loss. + 4. Create optimizer if is_train==True. Args: args(Namespace): Arguments obtained from ArgumentParser. main_prog(paddle.static.Program):The main program. startup_prog(paddle.static.Program):The startup program. - feeds(dict): A dict of mapping variables' names to their values is_train(bool, optional): Whether the main programe created is for training. Default: True. Returns: model(paddle.nn.Layer): An instance of BERT Model defined in modeling.py. lr_scheduler(paddle.optimizer.lr.LRScheduler): A learning rate scheduler. optimizer(Optimizer): An optimizer with distributed/AMP strategy. loss(variable): The output variable of loss function. + feeds(dict): A dict of mapping variables' names to their values """ with paddle.static.program_guard(main_prog, startup_prog): with paddle.utils.unique_name.guard(): + feeds = create_pretraining_data_holder() [ - input_ids, segment_ids, input_mask, masked_lm_positions, - masked_lm_labels, next_sentence_labels, masked_lm_scale + input_ids, token_type_ids, attention_mask, + next_sentence_labels, masked_lm_labels ] = feeds bert_config = BertConfig.from_json_file(args.config_file) if bert_config.vocab_size % 8 != 0: bert_config.vocab_size += 8 - (bert_config.vocab_size % 8) + bert_config.fuse_mha = args.fuse_mha model = BertForPretraining(bert_config) criterion = BertPretrainingCriterion(bert_config.vocab_size) prediction_scores, seq_relationship_score = model( input_ids=input_ids, - token_type_ids=segment_ids, - attention_mask=input_mask, - masked_positions=masked_lm_positions) + token_type_ids=token_type_ids, + attention_mask=attention_mask, + masked_lm_labels=masked_lm_labels) loss = criterion(prediction_scores, seq_relationship_score, - masked_lm_labels, next_sentence_labels, - masked_lm_scale) + masked_lm_labels, next_sentence_labels) lr_scheduler = None optimizer = None @@ -158,10 +179,16 @@ def build(args, main_prog, startup_prog, feeds, is_train=True): optimizer = build_optimizer(args, lr_scheduler) optimizer = dist_optimizer(args, optimizer) optimizer.minimize(loss) - return model, lr_scheduler, optimizer, loss + return model, lr_scheduler, optimizer, loss, feeds -def run(exe, program, args, lr_scheduler, loss, feeds, progress=None): +def run(exe, + program, + args, + lr_scheduler, + loss, + train_dataloader, + progress=None): """ Execute program. @@ -172,20 +199,14 @@ def run(exe, program, args, lr_scheduler, loss, feeds, progress=None): lr_scheduler(paddle.optimizer.lr.LRScheduler): A learning rate scheduler. Default: None. loss(variable): The output variable of loss function. - feeds(dict): A dict of mapping variables' names to their values progress(dict, optional): A dict to record the training progress of checkpoint. Returns: global_step(int): Final step id of this run. loss_return(float): Final loss of this run. train_time_raw(float): Time to train of this run. """ - pool = ThreadPoolExecutor(1) - - num_trainers = get_num_trainers() trainer_id = get_trainer_id() - worker_init = WorkerInitObj(args.seed + trainer_id) - batch_size_per_gpu = args.batch_size log_steps = args.log_freq save_steps = args.num_steps_per_checkpoint @@ -195,115 +216,88 @@ def run(exe, program, args, lr_scheduler, loss, feeds, progress=None): last_step = args.last_step_of_checkpoint train_iter = 0 epoch = 0 - resume_from_ckpt = False + train_time_raw = 0 if progress is None: progress = dict() else: - resume_from_ckpt = True - last_step = progress.get('global_step', 0) epoch = progress.get('epoch', 0) global_step = 0 + last_step logging.info(f"Training will start at the {last_step+1}th step") max_steps = args.max_steps + steps_this_run = max_steps if args.steps_this_run is not None: if args.steps_this_run + last_step > max_steps: logging.info( f"Only {max_steps - last_step} steps will be performed in this run due to the limit of --max-steps." ) else: - max_steps = args.steps_this_run + last_step + steps_this_run = args.steps_this_run + max_steps = steps_this_run + last_step logging.warning( - f"{args.steps_this_run} steps will be performed in this run.") + f"{steps_this_run} steps will be performed in this run.") + + if args.benchmark: + max_steps = args.benchmark_warmup_steps + args.benchmark_steps + last_step + + total_samples = 0 + raw_train_start = time.time() step_start = time.time() - raw_train_start = None + avg_loss = 0 while True: - input_dir = args.input_dir - if not resume_from_ckpt or progress.get('files', None) is None: - files = [ - os.path.join(input_dir, f) for f in os.listdir(input_dir) - if os.path.isfile(os.path.join(input_dir, f)) and "training" in - f - ] - files.sort() - np.random.shuffle(files) - f_start_id = 0 - else: - f_start_id = progress['f_id'] - files = progress['files'] - resume_from_ckpt = False - - # Select one file for each worker and create the DataLoader for the file - data_file = select_dataset_file_for_each_worker( - files, f_start_id, num_trainers, trainer_id) - train_data_loader = create_pretraining_dataset( - args, data_file, feeds, worker_init, paddle.static.cuda_places()) - - for f_id in range(f_start_id + 1, len(files)): - data_file = select_dataset_file_for_each_worker( - files, f_id, num_trainers, trainer_id) - dataset_future = pool.submit(create_pretraining_dataset, args, - data_file, feeds, worker_init, - paddle.static.cuda_places()) - - if raw_train_start is None: + for batch in train_dataloader: + + train_iter += 1 + loss_return = exe.run(program, feed=batch, fetch_list=[loss]) + total_samples += batch_size_per_gpu + avg_loss += loss_return[0].item() + + lr = lr_scheduler.get_lr() + + if train_iter % (log_steps * gradient_merge_steps) == 0: + step_cost = time.time() - step_start + dllogger_it_data = { + 'loss': avg_loss / gradient_merge_steps, + 'learning_rate': lr, + 'step_cost': step_cost, + 'step_samples': total_samples, + 'seqs_per_sec': total_samples / step_cost, + } + dllogger.log((epoch, global_step + 1), data=dllogger_it_data) + total_samples = 0 + step_start = time.time() + + if train_iter % gradient_merge_steps == 0: + global_step += 1 + lr_scheduler.step() + avg_loss = 0 + + if args.benchmark and train_iter == (args.benchmark_warmup_steps * + gradient_merge_steps): raw_train_start = time.time() - for batch in train_data_loader: - train_iter += 1 - loss_return = exe.run(program, feed=batch, fetch_list=[loss]) - total_samples += batch_size_per_gpu - - lr = lr_scheduler.get_lr() - if train_iter % gradient_merge_steps == 0: - global_step += 1 - lr_scheduler.step() - - if train_iter % (log_steps * gradient_merge_steps) == 0: - step_cost = time.time() - step_start - dllogger_it_data = { - 'loss': loss_return[0].item(), - 'learning_rate': lr, - 'step_cost': step_cost, - 'step_samples': total_samples, - 'seqs_per_sec': total_samples / step_cost, + if train_iter % (save_steps * gradient_merge_steps + ) == 0 or global_step >= max_steps: + train_time_raw = time.time() - raw_train_start + if trainer_id == 0: + model_path = os.path.join( + args.output_dir, args.bert_model, "phase1" + if args.phase1 else "phase2", f"{global_step}") + progress = { + 'epoch': epoch, + 'global_step': global_step, + 'phase': 1 if args.phase1 else 2, } - dllogger.log((epoch, global_step), data=dllogger_it_data) - total_samples = 0 - step_start = time.time() - - if args.benchmark and train_iter == ( - args.benchmark_warmup_steps * gradient_merge_steps): - raw_train_start = time.time() - - if train_iter % (save_steps * gradient_merge_steps - ) == 0 or global_step >= max_steps: - if trainer_id == 0: - model_path = os.path.join( - args.output_dir, args.bert_model, "phase1" - if args.phase1 else "phase2", f"{global_step}") - progress = { - 'files': files, - 'epoch': epoch, - 'global_step': global_step, - 'f_id': f_id, - 'phase': 1 if args.phase1 else 2, - } - save_model(program, model_path, args.model_prefix, - progress) - most_recent_ckpts_paths.append(model_path) - if len(most_recent_ckpts_paths) > 3: - ckpt_to_be_removed = most_recent_ckpts_paths.pop(0) - shutil.rmtree(ckpt_to_be_removed) - if (global_step >= max_steps) or ( - args.benchmark and global_step >= - args.benchmark_steps + args.benchmark_warmup_steps): - train_time_raw = time.time() - raw_train_start - del train_data_loader - return global_step, loss_return[0].item(), train_time_raw - del train_data_loader - train_data_loader = dataset_future.result(timeout=None) + save_model(program, model_path, args.model_prefix, + progress) + most_recent_ckpts_paths.append(model_path) + if len(most_recent_ckpts_paths) > 3: + ckpt_to_be_removed = most_recent_ckpts_paths.pop(0) + shutil.rmtree(ckpt_to_be_removed) + if global_step >= max_steps: + actual_steps_this_run = global_step - last_step + return global_step, actual_steps_this_run, loss_return[0].item(), train_time_raw epoch += 1 diff --git a/PaddlePaddle/LanguageModeling/BERT/requirements.txt b/PaddlePaddle/LanguageModeling/BERT/requirements.txt deleted file mode 100644 index 3b7de667a..000000000 --- a/PaddlePaddle/LanguageModeling/BERT/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -nltk -h5py -tqdm -git+https://github.com/NVIDIA/dllogger#egg=dllogger diff --git a/PaddlePaddle/LanguageModeling/BERT/run.sub b/PaddlePaddle/LanguageModeling/BERT/run.sub new file mode 100644 index 000000000..dd520a5a4 --- /dev/null +++ b/PaddlePaddle/LanguageModeling/BERT/run.sub @@ -0,0 +1,268 @@ +#!/bin/bash +#SBATCH --exclusive +#SBATCH --mem=0 +#SBATCH --overcommit +#SBATCH --parsable + +# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eux + +# +# Job Configurations +# +# Tag to the built image. +IMAGE_VERSION=${IMAGE_VERSION:-"22.12-py3"} +# Number of processes per node used for the LDDL preprocessor. +DASK_TASKS_PER_NODE=${DASK_TASKS_PER_NODE:-128} +# 1 or 2 . +PHASE=${PHASE:-1} +# An integer that specifies the pretraining seed. +SEED=${SEED:-42} +# The percentage of the articles from the Wikipedia dataset to sample and used +# for pretraining. 0 < ${SAMPLE_RATIO} < 1.0 +SAMPLE_RATIO=${SAMPLE_RATIO:-0.9} +# Number of GPUs per node. 0 < ${GPUS} <= 8. +GPUS=${GPUS:-"8"} +# The bin size for binned LDDL data loading. 'none' or an integer that divides +# 128 (for Phase1) or 512 (for Phase2). +BIN_SIZE=${BIN_SIZE:-"none"} +# Number of parquet shards per each LDDL data loader worker process. 'none' or +# an integer. +NUM_SHARDS_PER_WORKER=${NUM_SHARDS_PER_WORKER:-"none"} +# Number of LDDL data loader worker processes per rank. +NUM_WORKERS=${NUM_WORKERS:-4} +# Should we rerun the LDDL preprocessor every time? 'true' or 'false' . +RERUN_DASK=${RERUN_DASK:-"true"} +# 'static' or 'dynamic' . +MASKING=${MASKING:-"static"} +# Should we use jemalloc for the LDDL preprocessor? 'true' or 'false' . +USE_JEMALLOC=${USE_JEMALLOC:-"true"} +# 'fp16' or 'tf32' . +PRECISION=${PRECISION:-"fp16"} +# The path to the initial checkpoint (from Phase1) used to start Phase2. 'none' +# or an absolute path. +INIT_CHECKPOINT=${INIT_CHECKPOINT:-"none"} +# The per-rank batch size before being divided by the gradient accumulation +# steps. +TRAIN_BATCH_SIZE=${TRAIN_BATCH_SIZE:-"256"} +# The gradient accumulation steps. +GRADIENT_ACCUMULATION_STEPS=${GRADIENT_ACCUMULATION_STEPS:-"32"} + +# +# Static Configurations +# +# Container URL. +# Replace this with the URL of the docker image that you build +# with scripts/docker/build.sh . +readonly docker_image="bert:${IMAGE_VERSION}" +# Where the datasets are stored on the system. +readonly host_datadir="/home/${USER}/datasets" +readonly container_datadir="/datasets" +# Replace these with the path to the 'source' subdirectory of the LDDL Wikipedia +# dataset. +readonly host_wikipedia_source="${host_datadir}/wikipedia/source" +readonly container_wikipedia_source="${container_datadir}/wikipedia/source" +readonly wikipedia_mount="${host_wikipedia_source}:${container_wikipedia_source}" +# Replace these with where you want to store the Parquet shards in case +# ${RERUN_DASK} is 'false'. +readonly host_pretrain="${host_datadir}/pretrain" +readonly container_pretrain="${container_datadir}/pretrain" +readonly pretrain_mount="${host_pretrain}:${container_pretrain}" +# Replace these with where you want to store the pretrained checkpoints on +# the system. +readonly host_output="$PWD/results/${SLURM_JOB_ID}" +mkdir -p "${host_output}" +readonly container_output="/results" +readonly output_mount="${host_output}:${container_output}" +# If INIT_CHECKPOINT is 'none', infer INIT_CHECKPOINT based on job dependency. +if [ "${INIT_CHECKPOINT}" == "none" ] && [ "${PHASE}" == "2" ] ; then + INIT_CHECKPOINT="$PWD/results/${SLURM_JOB_DEPENDENCY}/bert-large-uncased/phase1/7038" +fi +# Define mounts. +mounts="${PWD}:/workspace/bert,${wikipedia_mount},${pretrain_mount},${output_mount}" +# Add the mount path of the initial checkpoint for Phase2. +if [ "${PHASE}" == "1" ]; then + echo "No init. mounted for Phase1!" + readonly container_init_checkpoint="" +elif [ "${PHASE}" == "2" ]; then + if [ ! -f "${INIT_CHECKPOINT}" ]; then + echo "No init. checkpoint found for Phase2!" + exit 1 + else + mounts="${mounts},$(dirname "${INIT_CHECKPOINT}"):/checkpoints" + readonly container_init_checkpoint="/checkpoints" + fi +else + echo "\${PHASE} = ${PHASE} unknown!" + exit 1 +fi +# Determine where the parquet shards should be stored. +if [ "${RERUN_DASK}" == "true" ]; then + # Always rerun the dask pipeline. Therefore, use the output directory to store + # the parquets. + readonly host_pretrain_parquet="${host_output}/parquet" + readonly container_pretrain_parquet="${container_output}/parquet" +elif [ "${RERUN_DASK}" == "false" ]; then + echo "Use existing parquets if they exists." + if [ "${BIN_SIZE}" == "none" ]; then + readonly host_pretrain_parquet="${host_pretrain}/phase${PHASE}/unbinned/parquet" + readonly container_pretrain_parquet="${container_pretrain}/phase${PHASE}/unbinned/parquet" + else + readonly host_pretrain_parquet="${host_pretrain}/phase${PHASE}/bin_size_${BIN_SIZE}/parquet" + readonly container_pretrain_parquet="${container_pretrain}/phase${PHASE}/bin_size_${BIN_SIZE}/parquet" + fi +else + echo "\${RERUN_DASK} = ${RERUN_DASK} unknown!" + exit 1 +fi + +readonly PHASE1="\ + --learning-rate=6e-3 \ + --warmup-proportion=0.2843 \ + --phase1 \ + --max-seq-length=128 \ + --max-predictions-per-seq=20 \ + --max-steps=7038 \ + --num-steps-per-checkpoint=2500 \ + " + +readonly PHASE2="\ + --learning-rate=4e-3 \ + --warmup-proportion=0.128 \ + --phase2 \ + --max-seq-length=512 \ + --max-predictions-per-seq=80 \ + --max-steps=1563 \ + --num-steps-per-checkpoint=1000 \ + --from-pretrained-params=${container_init_checkpoint} \ + " + +# Arguments for fp16. +if [ "${PRECISION}" == "fp16" ]; then + readonly fp16_flags="--amp --use-dynamic-loss-scaling --scale-loss=1048576" +elif [ "${PRECISION}" == "tf32" ]; then + readonly fp16_flags="" +else + echo "\${PRECISION} = ${PRECISION} unknown!" + exit 1 +fi + +# Get the ip address of all nodes. +IP_CMD="hostname -i" +IP_STR=$(srun -pmix --ntasks-per-node=1 bash -c "${IP_CMD}") +IP_STR=$(echo $IP_STR | sed 's/ /,/g') +echo "\${IP_STR} = ${IP_STR}" + +# Get the actual pretraining command. +readonly PHASES=( "$PHASE1" "$PHASE2" ) +readonly BERT_CMD="\ + python -m paddle.distributed.launch \ + --gpus=0,1,2,3,4,5,6,7 \ + --ips="${IP_STR}" \ + /workspace/bert/run_pretraining.py \ + ${PHASES[$((PHASE - 1))]} \ + --batch-size=${TRAIN_BATCH_SIZE} \ + --input-dir=${container_pretrain_parquet} \ + --output-dir=${container_output} \ + --vocab-file=/workspace/bert/vocab/bert-large-uncased-vocab.txt \ + --bert-model=bert-large-uncased \ + --config-file=/workspace/bert/bert_configs/bert-large-uncased.json \ + --gradient-merge-steps=${GRADIENT_ACCUMULATION_STEPS} \ + --log-freq=1 \ + --seed=12345 \ + --optimizer=Lamb \ + ${fp16_flags} " + +echo "nodes: ${SLURM_JOB_NUM_NODES}, TRAIN_BATCH_SIZE: ${TRAIN_BATCH_SIZE}, GRADIENT_ACCUMULATION_STEPS: ${GRADIENT_ACCUMULATION_STEPS}" + +# +# Running the LDDL preprocessor and load balancer. +# +# Determine the number of parquet shards in total. +if [ "${NUM_SHARDS_PER_WORKER}" == "none" ]; then + readonly num_blocks=4096 +else + readonly num_blocks=$((NUM_SHARDS_PER_WORKER * $(( NUM_WORKERS > 0 ? NUM_WORKERS : 1 )) * SLURM_JOB_NUM_NODES * GPUS)) +fi +echo "num_blocks: ${num_blocks}" +# Run the LDDL preprocessor and load balancer only when there is no file in +# where the parquets are supposed to be stored. +if [ ! -d "${host_pretrain_parquet}" ] || [ -z "$(ls -A "${host_pretrain_parquet}")" ]; then + # The sequence length is 128 for Phase1, but 512 for Phase2. + if [ "${PHASE}" == "1" ]; then + readonly target_seq_len_flag="" + elif [ "${PHASE}" == "2" ]; then + readonly target_seq_len_flag="--target-seq-length 512" + else + echo "\${PHASE} = ${PHASE} unknown!" + exit 1 + fi + # Should we use sequence binning? + if [ "${BIN_SIZE}" == "none" ]; then + readonly bin_size_flag="" + else + readonly bin_size_flag="--bin-size ${BIN_SIZE}" + fi + # Static masking or dynamic masking? + if [ "${MASKING}" == "dynamic" ]; then + readonly masking_flag="" + elif [ "${MASKING}" == "static" ]; then + readonly masking_flag="--masking" + else + echo "\${MASKING} = ${MASKING} unknown!" + exit 1 + fi + # Should we use jemalloc for the LDDL preprocessor? + if [ "${USE_JEMALLOC}" == "true" ]; then + readonly use_jemalloc_flag="--export=ALL,LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so" + elif [ "${USE_JEMALLOC}" == "false" ]; then + readonly use_jemalloc_flag="" + else + echo "\${USE_JEMALLOC} = ${USE_JEMALLOC} unknown!" + exit 1 + fi + # Run the LDDL preprocessor. + srun -l \ + --mpi=pmix \ + --container-image="${docker_image}" \ + --container-mounts="${mounts}" \ + --ntasks-per-node="${DASK_TASKS_PER_NODE}" \ + ${use_jemalloc_flag} \ + preprocess_bert_pretrain \ + --schedule mpi \ + ${target_seq_len_flag} \ + --wikipedia ${container_wikipedia_source} \ + --sink "${container_pretrain_parquet}" \ + --vocab-file /workspace/bert/vocab/bert-large-uncased-vocab.txt \ + --num-blocks "${num_blocks}" \ + --sample-ratio "${SAMPLE_RATIO}" \ + ${bin_size_flag} \ + ${masking_flag} \ + --seed "${SEED}" + # Run the LDDL load balancer. + srun -l \ + --mpi=pmix \ + --container-image="${docker_image}" \ + --container-mounts="${mounts}" \ + --ntasks-per-node="${DASK_TASKS_PER_NODE}" \ + balance_dask_output \ + --indir "${container_pretrain_parquet}" \ + --num-shards "${num_blocks}" +fi + +# +# Run pretraining. +# +srun -l -pmix --container-image="${docker_image}" --container-mounts="${mounts}" --ntasks-per-node=1 bash -c "${BERT_CMD}" \ No newline at end of file diff --git a/PaddlePaddle/LanguageModeling/BERT/run_pretraining.py b/PaddlePaddle/LanguageModeling/BERT/run_pretraining.py index b66f89a54..d6f9f4adc 100644 --- a/PaddlePaddle/LanguageModeling/BERT/run_pretraining.py +++ b/PaddlePaddle/LanguageModeling/BERT/run_pretraining.py @@ -12,11 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os import time +import logging import paddle import paddle.distributed.fleet as fleet -from pretraining_dataset import create_pretraining_data_holder from utils.config import parse_args, print_args from utils.save_load import init_program from utils.logger import setup_loggers @@ -24,6 +25,7 @@ from utils.utility import set_seed, get_trainer_id, get_num_trainers import program import dllogger +from lddl.paddle import get_bert_pretrain_data_loader def main(): @@ -42,12 +44,11 @@ def main(): if args.show_config: print_args(args) + device = paddle.set_device('gpu') fleet.init(is_collective=True) if args.enable_cpu_affinity: set_cpu_affinity() - device = paddle.set_device('gpu') - # Create the random seed for the worker set_seed(args.seed + get_trainer_id()) @@ -60,30 +61,44 @@ def main(): main_program = paddle.static.default_main_program() startup_program = paddle.static.default_startup_program() - feeds = create_pretraining_data_holder() - - model, lr_scheduler, optimizer, loss = program.build( - args, main_program, startup_program, feeds) + model, lr_scheduler, optimizer, loss, feeds = program.build( + args, main_program, startup_program) exe = paddle.static.Executor(device) exe.run(startup_program) progress = init_program(args, program=main_program, exe=exe, model=model) + train_dataloader = get_bert_pretrain_data_loader( + args.input_dir, + vocab_file=args.vocab_file, + data_loader_kwargs={ + 'batch_size': args.batch_size, + 'num_workers': args.num_workers, + 'persistent_workers': True, + 'feed_list': feeds + }, + base_seed=args.seed, + log_dir=None if args.output_dir is None else + os.path.join(args.output_dir, 'lddl_log'), + log_level=logging.WARNING, + start_epoch=0 if progress is None else progress.get("epoch", 0), + sequence_length_alignment=64) if args.amp: optimizer.amp_init(device) - global_step, final_loss, train_time_raw = program.run( - exe, main_program, args, lr_scheduler, loss, feeds, progress) + global_step, actual_steps_this_run, final_loss, train_time_raw = program.run( + exe, main_program, args, lr_scheduler, loss, train_dataloader, + progress) if get_trainer_id() == 0: e2e_time = time.time() - now if args.benchmark: training_perf = args.batch_size * args.gradient_merge_steps * ( - global_step - args.benchmark_warmup_steps + actual_steps_this_run - args.benchmark_warmup_steps ) * get_num_trainers() / train_time_raw else: - training_perf = args.batch_size * args.gradient_merge_steps * global_step * get_num_trainers( + training_perf = args.batch_size * args.gradient_merge_steps * actual_steps_this_run * get_num_trainers( ) / train_time_raw dllogger.log(step=tuple(), data={ diff --git a/PaddlePaddle/LanguageModeling/BERT/run_squad.py b/PaddlePaddle/LanguageModeling/BERT/run_squad.py index 601676c68..48d2694a5 100644 --- a/PaddlePaddle/LanguageModeling/BERT/run_squad.py +++ b/PaddlePaddle/LanguageModeling/BERT/run_squad.py @@ -186,9 +186,11 @@ def main(args): with paddle.static.program_guard(main_program, startup_program): bert_config = BertConfig.from_json_file(args.config_file) + bert_config.fuse_mha = args.fuse_mha if bert_config.vocab_size % 8 != 0: bert_config.vocab_size += 8 - (bert_config.vocab_size % 8) + model = BertForQuestionAnswering(bert_config) criterion = CrossEntropyLossForSQuAD() logits = model(input_ids=input_ids, token_type_ids=segment_ids) diff --git a/PaddlePaddle/LanguageModeling/BERT/scripts/configs/pretrain_config.sh b/PaddlePaddle/LanguageModeling/BERT/scripts/configs/pretrain_config.sh index 6300e6412..e2c76de35 100644 --- a/PaddlePaddle/LanguageModeling/BERT/scripts/configs/pretrain_config.sh +++ b/PaddlePaddle/LanguageModeling/BERT/scripts/configs/pretrain_config.sh @@ -30,14 +30,22 @@ dgxa100-80g_8gpu_amp () warmup_proportion_phase2="0.128" train_steps_phase2=1563 gradient_accumulation_steps_phase2=128 - DATASET=hdf5_lower_case_1_seq_len_128_max_pred_20_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en # change this for other datasets + DATASET=pretrain/phase1/unbinned/parquet # change this for other datasets DATA_DIR_PHASE1="$BERT_PREP_WORKING_DIR/${DATASET}/" - DATASET2=hdf5_lower_case_1_seq_len_512_max_pred_80_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en # change this for other datasets + DATASET2=pretrain/phase2/bin_size_64/parquet # change this for other datasets DATA_DIR_PHASE2="$BERT_PREP_WORKING_DIR/${DATASET2}/" CODEDIR=/workspace/bert init_checkpoint="None" + VOCAB_FILE=vocab/bert-large-uncased-vocab.txt RESULTS_DIR=$CODEDIR/results CHECKPOINTS_DIR=$RESULTS_DIR + wikipedia_source=$BERT_PREP_WORKING_DIR/wikipedia/source/ + num_dask_workers=128 + num_shards_per_worker=128 + num_workers=4 + sample_ratio="0.9" + phase2_bin_size=64 + masking=static BERT_CONFIG=bert_configs/bert-large-uncased.json enable_benchmark="false" benchmark_steps=10 # It takes effect only after the enable_benchmark is set to true @@ -45,9 +53,11 @@ dgxa100-80g_8gpu_amp () echo $train_batch_size $learning_rate $precision $num_gpus \ $warmup_proportion $train_steps $save_checkpoint_steps \ $create_logfile $gradient_accumulation_steps $seed $job_name \ - $train_batch_size_phase2 $learning_rate_phase2 \ + $train_batch_size_phase2 $learning_rate_phase2 \ $warmup_proportion_phase2 $train_steps_phase2 $gradient_accumulation_steps_phase2 \ $DATA_DIR_PHASE1 $DATA_DIR_PHASE2 $CODEDIR $init_checkpoint \ + $wikipedia_source $num_dask_workers $num_shards_per_worker $num_workers \ + $sample_ratio $phase2_bin_size $masking \ $BERT_CONFIG $enable_benchmark $benchmark_steps $benchmark_warmup_steps } @@ -69,14 +79,22 @@ dgxa100-80g_8gpu_tf32 () warmup_proportion_phase2="0.128" train_steps_phase2=1563 gradient_accumulation_steps_phase2=256 - DATASET=hdf5_lower_case_1_seq_len_128_max_pred_20_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en # change this for other datasets + DATASET=pretrain/phase1/unbinned/parquet # change this for other datasets DATA_DIR_PHASE1="$BERT_PREP_WORKING_DIR/${DATASET}/" - DATASET2=hdf5_lower_case_1_seq_len_512_max_pred_80_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en # change this for other datasets + DATASET2=pretrain/phase2/bin_size_64/parquet # change this for other datasets DATA_DIR_PHASE2="$BERT_PREP_WORKING_DIR/${DATASET2}/" CODEDIR=/workspace/bert init_checkpoint="None" + VOCAB_FILE=vocab/bert-large-uncased-vocab.txt RESULTS_DIR=$CODEDIR/results CHECKPOINTS_DIR=$RESULTS_DIR + wikipedia_source=$BERT_PREP_WORKING_DIR/wikipedia/source/ + num_dask_workers=128 + num_shards_per_worker=128 + num_workers=4 + sample_ratio="0.9" + phase2_bin_size=64 + masking=static BERT_CONFIG=bert_configs/bert-large-uncased.json enable_benchmark="false" benchmark_steps=10 # It takes effect only after the enable_benchmark is set to true @@ -84,8 +102,10 @@ dgxa100-80g_8gpu_tf32 () echo $train_batch_size $learning_rate $precision $num_gpus \ $warmup_proportion $train_steps $save_checkpoint_steps \ $create_logfile $gradient_accumulation_steps $seed $job_name \ - $train_batch_size_phase2 $learning_rate_phase2 \ + $train_batch_size_phase2 $learning_rate_phase2 \ $warmup_proportion_phase2 $train_steps_phase2 $gradient_accumulation_steps_phase2 \ $DATA_DIR_PHASE1 $DATA_DIR_PHASE2 $CODEDIR $init_checkpoint \ + $wikipedia_source $num_dask_workers $num_shards_per_worker $num_workers \ + $sample_ratio $phase2_bin_size $masking \ $BERT_CONFIG $enable_benchmark $benchmark_steps $benchmark_warmup_steps } diff --git a/PaddlePaddle/LanguageModeling/BERT/scripts/docker/build.sh b/PaddlePaddle/LanguageModeling/BERT/scripts/docker/build.sh index cda6c187c..dd5ef4374 100644 --- a/PaddlePaddle/LanguageModeling/BERT/scripts/docker/build.sh +++ b/PaddlePaddle/LanguageModeling/BERT/scripts/docker/build.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (c) 2022 NVIDIA Corporation. All rights reserved. +# Copyright (c) 2023 NVIDIA Corporation. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,4 +14,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -docker build --network=host . --rm --pull --no-cache -t bert +URL=${1:-"bert"} +PUSH=${2:-"none"} # 'push' or 'none' + +set -e + +docker build \ + --network=host \ + --rm \ + --pull \ + --no-cache \ + -t ${URL} \ + . + +if [ "${PUSH}" == "push" ]; then + docker push ${URL} +elif [ "${PUSH}" == "none" ]; then + echo "Keep the built image locally." +else + echo "Invalid \${PUSH} option: ${PUSH} !" + exit 1 +fi diff --git a/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining.sh b/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining.sh index 6ab426d07..bd6da1240 100644 --- a/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining.sh +++ b/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining.sh @@ -32,25 +32,88 @@ warmup_proportion_phase2=${14:-"0.128"} train_steps_phase2=${15:-1563} gradient_accumulation_steps_phase2=${16:-128} #change this for other datasets -DATASET=hdf5_lower_case_1_seq_len_128_max_pred_20_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en +DATASET=pretrain/phase1/unbinned/parquet DATA_DIR_PHASE1=${17:-$BERT_PREP_WORKING_DIR/${DATASET}/} #change this for other datasets -DATASET2=hdf5_lower_case_1_seq_len_512_max_pred_80_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en +DATASET2=pretrain/phase2/bin_size_64/parquet DATA_DIR_PHASE2=${18:-$BERT_PREP_WORKING_DIR/${DATASET2}/} CODEDIR=${19:-"/workspace/bert"} init_checkpoint=${20:-"None"} +VOCAB_FILE=vocab/bert-large-uncased-vocab.txt RESULTS_DIR=$CODEDIR/results CHECKPOINTS_DIR=$RESULTS_DIR -BERT_CONFIG=${21:-"None"} -enable_benchmark=${22:-"false"} -benchmark_steps=${23:-"10"} -benchmark_warmup_steps=${24:-"10"} +wikipedia_source=${21:-$BERT_PREP_WORKING_DIR/wikipedia/source/} +num_dask_workers=${22:-$(nproc)} +num_shards_per_worker=${23:-128} +num_workers=${24:-4} +num_nodes=1 +sample_ratio=${25:-0.9} +phase2_bin_size=${26:-64} +masking=${27:-static} +BERT_CONFIG=${28:-"None"} +enable_benchmark=${29:-"false"} +benchmark_steps=${30:-"10"} +benchmark_warmup_steps=${31:-"10"} +fuse_mha=${32:-"true"} + +# Calculate the total number of shards. +readonly num_blocks=$((num_shards_per_worker * $(( num_workers > 0 ? num_workers : 1 )) * num_nodes * num_gpus)) + +if [ "${phase2_bin_size}" == "none" ]; then + readonly phase2_bin_size_flag="" +elif [[ "${phase2_bin_size}" =~ ^(32|64|128|256|512)$ ]]; then + readonly phase2_bin_size_flag="--bin-size ${phase2_bin_size}" +else + echo "Error! phase2_bin_size=${phase2_bin_size} not supported!" + return -1 +fi + +if [ "${masking}" == "static" ]; then + readonly masking_flag="--masking" +elif [ "${masking}" == "dynamic" ]; then + readonly masking_flag="" +else + echo "Error! masking=${masking} not supported!" + return -1 +fi mkdir -p $CHECKPOINTS_DIR -if [ ! -d "$DATA_DIR_PHASE1" ] ; then - echo "Warning! $DATA_DIR_PHASE1 directory missing. Training cannot start" +if [ ! -d "${DATA_DIR_PHASE1}" ] || [ -z "$(ls -A ${DATA_DIR_PHASE1})" ]; then + echo "Warning! ${DATA_DIR_PHASE1} directory missing." + if [ ! -d "${wikipedia_source}" ] || [ -z "$(ls -A ${wikipedia_source})" ]; then + echo "Error! ${wikipedia_source} directory missing. Training cannot start!" + return -1 + fi + preprocess_cmd=" \ + mpirun \ + --oversubscribe \ + --allow-run-as-root \ + -np ${num_dask_workers} \ + -x LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so \ + preprocess_bert_pretrain \ + --schedule mpi \ + --vocab-file ${VOCAB_FILE} \ + --wikipedia ${wikipedia_source} \ + --sink ${DATA_DIR_PHASE1} \ + --num-blocks ${num_blocks} \ + --sample-ratio ${sample_ratio} \ + ${masking_flag} \ + --seed ${seed}" + echo "Running ${preprocess_cmd} ..." + ${preprocess_cmd} + + balance_load_cmd=" \ + mpirun \ + --oversubscribe \ + --allow-run-as-root \ + -np ${num_dask_workers} \ + balance_dask_output \ + --indir ${DATA_DIR_PHASE1} \ + --num-shards ${num_blocks}" + echo "Running ${balance_load_cmd} ..." + ${balance_load_cmd} fi if [ ! -d "$RESULTS_DIR" ] ; then echo "Error! $RESULTS_DIR directory missing." @@ -68,8 +131,12 @@ if [ "$BERT_CONFIG" != "None" ] ; then fi PREC="" +FUSE_MHA="" if [ "$precision" = "amp" ] ; then PREC="--amp --use-dynamic-loss-scaling --scale-loss=1048576" + if [ "$fuse_mha" = "true" ] ; then + FUSE_MHA="--fuse-mha" + fi elif [ "$precision" = "fp32" ] ; then PREC="" elif [ "$precision" = "tf32" ] ; then @@ -119,6 +186,7 @@ echo $DATA_DIR_PHASE1 INPUT_DIR=$DATA_DIR_PHASE1 CMD=" $CODEDIR/run_pretraining.py" CMD+=" --input-dir=$DATA_DIR_PHASE1" +CMD+=" --vocab-file=$VOCAB_FILE" CMD+=" --output-dir=$CHECKPOINTS_DIR" CMD+=" $CONFIG " CMD+=" --bert-model=bert-large-uncased" @@ -134,6 +202,7 @@ CMD+=" --log-freq=1" CMD+=" --optimizer=Lamb" CMD+=" --phase1" CMD+=" $PREC" +CMD+=" $FUSE_MHA" CMD+=" $ACCUMULATE_GRADIENTS" CMD+=" $INIT_CHECKPOINT" CMD+=" $BENCH" @@ -180,11 +249,49 @@ fi ACCUMULATE_GRADIENTS="--gradient-merge-steps=$gradient_accumulation_steps_phase2" +if [ ! -d "${DATA_DIR_PHASE2}" ] || [ -z "$(ls -A ${DATA_DIR_PHASE2})" ]; then + echo "Warning! ${DATA_DIR_PHASE2} directory missing." + if [ ! -d "${wikipedia_source}" ] || [ -z "$(ls -A ${wikipedia_source})" ]; then + echo "Error! ${wikipedia_source} directory missing. Training cannot start!" + return -1 + fi + preprocess_cmd=" \ + mpirun \ + --oversubscribe \ + --allow-run-as-root \ + -np ${num_dask_workers} \ + -x LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so \ + preprocess_bert_pretrain \ + --schedule mpi \ + --vocab-file ${VOCAB_FILE} \ + --wikipedia ${wikipedia_source} \ + --sink ${DATA_DIR_PHASE2} \ + --target-seq-length 512 \ + --num-blocks ${num_blocks} \ + --sample-ratio ${sample_ratio} \ + ${phase2_bin_size_flag} \ + ${masking_flag} \ + --seed ${seed}" + echo "Running ${preprocess_cmd} ..." + ${preprocess_cmd} + + balance_load_cmd=" \ + mpirun \ + --oversubscribe \ + --allow-run-as-root \ + -np ${num_dask_workers} \ + balance_dask_output \ + --indir ${DATA_DIR_PHASE2} \ + --num-shards ${num_blocks}" + echo "Running ${balance_load_cmd} ..." + ${balance_load_cmd} +fi echo $DATA_DIR_PHASE2 INPUT_DIR=$DATA_DIR_PHASE2 PHASE1_END_CKPT_DIR="${CHECKPOINTS_DIR}/bert-large-uncased/phase1/${train_steps}" CMD=" $CODEDIR/run_pretraining.py" CMD+=" --input-dir=$DATA_DIR_PHASE2" +CMD+=" --vocab-file=$VOCAB_FILE" CMD+=" --output-dir=$CHECKPOINTS_DIR" CMD+=" $CONFIG " CMD+=" --bert-model=bert-large-uncased" diff --git a/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p1.sh b/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p1.sh index 18e237ec6..efc77ba06 100644 --- a/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p1.sh +++ b/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p1.sh @@ -15,7 +15,8 @@ python3 -m paddle.distributed.launch \ --gpus="0,1,2,3,4,5,6,7" \ ./run_pretraining.py \ ---input-dir=./data/hdf5_lower_case_1_seq_len_128_max_pred_20_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en \ +--input-dir=pretrain/phase1/unbinned/parquet \ +--vocab-file=vocab/bert-large-uncased-vocab.txt \ --output-dir=./results/checkpoints \ --bert-model=bert-large-uncased \ --from-checkpoint=./results/checkpoints/bert-large-uncased/phase1 \ @@ -30,6 +31,7 @@ python3 -m paddle.distributed.launch \ --amp \ --use-dynamic-loss-scaling \ --optimizer=Lamb \ +--fuse-mha \ --phase1 \ --scale-loss=1048576 \ --learning-rate=6e-3 \ diff --git a/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p2.sh b/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p2.sh index f0e788cf2..76a9398b7 100644 --- a/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p2.sh +++ b/PaddlePaddle/LanguageModeling/BERT/scripts/run_pretraining_p2.sh @@ -15,7 +15,8 @@ python3 -m paddle.distributed.launch \ --gpus="0,1,2,3,4,5,6,7" \ ./run_pretraining.py \ ---input-dir=./data/hdf5_lower_case_1_seq_len_512_max_pred_80_masked_lm_prob_0.15_random_seed_12345_dupe_factor_5/wikicorpus_en \ +--input-dir=pretrain/phase2/bin_size_64/parquet \ +--vocab-file=vocab/bert-large-uncased-vocab.txt \ --output-dir=./results/checkpoints \ --bert-model=bert-large-uncased \ --from-checkpoint=./results/checkpoints/bert-large-uncased/phase2 \ @@ -31,6 +32,7 @@ python3 -m paddle.distributed.launch \ --amp \ --use-dynamic-loss-scaling \ --optimizer=Lamb \ +--fuse-mha \ --phase2 \ --scale-loss=1048576 \ --learning-rate=4e-3 \ diff --git a/PaddlePaddle/LanguageModeling/BERT/scripts/run_squad.sh b/PaddlePaddle/LanguageModeling/BERT/scripts/run_squad.sh index 4d0d46da0..5234f16c1 100644 --- a/PaddlePaddle/LanguageModeling/BERT/scripts/run_squad.sh +++ b/PaddlePaddle/LanguageModeling/BERT/scripts/run_squad.sh @@ -31,6 +31,7 @@ max_steps=${14:-"-1"} enable_benchmark=${15:-"false"} benchmark_steps=${16:-"100"} benchmark_warmup_steps=${17:-"100"} +fuse_mha=${18:-"true"} echo "out dir is $OUT_DIR" @@ -41,9 +42,13 @@ if [ ! -d "$OUT_DIR" ]; then fi amp="" +FUSE_MHA="" if [ "$precision" = "amp" ] ; then echo "amp activated!" amp=" --amp --use-dynamic-loss-scaling --scale-loss=128.0" + if [ "$fuse_mha" = "true" ] ; then + FUSE_MHA="--fuse-mha" + fi fi CONFIG="" @@ -119,6 +124,7 @@ CMD+=" --max-steps=$max_steps " CMD+=" --optimizer=AdamW " CMD+=" --log-freq=100 " CMD+=" $amp " +CMD+=" $FUSE_MHA " CMD+=" $BENCH " CMD+=" --report-file $OUT_DIR/dllogger_${num_gpus}_${precision}.json " diff --git a/PaddlePaddle/LanguageModeling/BERT/utils/config.py b/PaddlePaddle/LanguageModeling/BERT/utils/config.py index 2b1564fb0..8a402a291 100644 --- a/PaddlePaddle/LanguageModeling/BERT/utils/config.py +++ b/PaddlePaddle/LanguageModeling/BERT/utils/config.py @@ -18,6 +18,7 @@ import distutils.util import logging import dllogger +import paddle from utils.task import Task from utils.save_load import _PDOPT_SUFFIX, _PDPARAMS_SUFFIX, _PROGRESS_SUFFIX @@ -27,7 +28,7 @@ 'bert-large-uncased': './bert_configs/bert-large-uncased.json', 'bert-large-cased': './bert_configs/bert-large-cased.json', 'bert-base-uncased': './bert_configs/bert-base-uncased.json', - 'bert-base-cased': './bert_configs/bert-base-cased.json' + 'bert-base-cased': './bert_configs/bert-base-cased.json', } @@ -41,28 +42,34 @@ def _check_file_exist(path_with_prefix): pdparams_path = path_with_prefix + _PDPARAMS_SUFFIX progress_path = path_with_prefix + _PROGRESS_SUFFIX found = False - if os.path.exists(pdopt_path) and os.path.exists( - pdparams_path) and os.path.exists(progress_path): + if ( + os.path.exists(pdopt_path) + and os.path.exists(pdparams_path) + and os.path.exists(progress_path) + ): found = True return found, pdopt_path, pdparams_path, progress_path if not os.path.exists(args.from_checkpoint): logging.warning( - f"Start training from scratch since no checkpoint is found.") + f"Start training from scratch since no checkpoint is found." + ) args.from_checkpoint = None args.last_step_of_checkpoint = 0 return - target_from_checkpoint = os.path.join(args.from_checkpoint, - args.model_prefix) + target_from_checkpoint = os.path.join( + args.from_checkpoint, args.model_prefix + ) if args.last_step_of_checkpoint is None: args.last_step_of_checkpoint = 0 elif args.last_step_of_checkpoint == _AUTO_LAST_EPOCH: folders = os.listdir(args.from_checkpoint) args.last_step_of_checkpoint = 0 for folder in folders: - tmp_ckpt_path = os.path.join(args.from_checkpoint, folder, - args.model_prefix) + tmp_ckpt_path = os.path.join( + args.from_checkpoint, folder, args.model_prefix + ) try: folder = int(folder) @@ -72,23 +79,32 @@ def _check_file_exist(path_with_prefix): ) continue - if folder > args.last_step_of_checkpoint and \ - _check_file_exist(tmp_ckpt_path)[0]: + if ( + folder > args.last_step_of_checkpoint + and _check_file_exist(tmp_ckpt_path)[0] + ): args.last_step_of_checkpoint = folder - step_with_prefix = os.path.join(str(args.last_step_of_checkpoint), args.model_prefix) \ - if args.last_step_of_checkpoint > 0 else args.model_prefix - target_from_checkpoint = os.path.join(args.from_checkpoint, - step_with_prefix) + step_with_prefix = ( + os.path.join(str(args.last_step_of_checkpoint), args.model_prefix) + if args.last_step_of_checkpoint > 0 + else args.model_prefix + ) + target_from_checkpoint = os.path.join( + args.from_checkpoint, step_with_prefix + ) else: try: args.last_step_of_checkpoint = int(args.last_step_of_checkpoint) except ValueError: - raise ValueError(f"The value of --last-step-of-checkpoint should be None, {_AUTO_LAST_EPOCH}" \ - f" or integer >= 0, but receive {args.last_step_of_checkpoint}") + raise ValueError( + f"The value of --last-step-of-checkpoint should be None, {_AUTO_LAST_EPOCH}" + f" or integer >= 0, but receive {args.last_step_of_checkpoint}" + ) args.from_checkpoint = target_from_checkpoint found, pdopt_path, pdparams_path, progress_path = _check_file_exist( - args.from_checkpoint) + args.from_checkpoint + ) if not found: args.from_checkpoint = None args.last_step_of_checkpoint = 0 @@ -98,19 +114,28 @@ def _check_file_exist(path_with_prefix): def _get_full_path_of_pretrained_params(args, task=Task.pretrain): - if args.from_pretrained_params is None and args.from_phase1_final_params is None: + if ( + args.from_pretrained_params is None + and args.from_phase1_final_params is None + ): args.last_step_of_checkpoint = 0 return - if task == Task.pretrain and args.from_phase1_final_params is not None and args.last_step_of_checkpoint == 0: + if ( + task == Task.pretrain + and args.from_phase1_final_params is not None + and args.last_step_of_checkpoint == 0 + ): args.from_pretrained_params = args.from_phase1_final_params - args.from_pretrained_params = os.path.join(args.from_pretrained_params, - args.model_prefix) + args.from_pretrained_params = os.path.join( + args.from_pretrained_params, args.model_prefix + ) pdparams_path = args.from_pretrained_params + _PDPARAMS_SUFFIX if not os.path.exists(pdparams_path): args.from_pretrained_params = None logging.warning( - f"Cannot find {pdparams_path}, disable --from-pretrained-params.") + f"Cannot find {pdparams_path}, disable --from-pretrained-params." + ) args.last_step_of_checkpoint = 0 @@ -121,20 +146,28 @@ def print_args(args): def check_and_process_args(args, task=Task.pretrain): if task == Task.pretrain: - assert not (args.from_checkpoint is not None and \ - args.from_pretrained_params is not None), \ - "--from-pretrained-params and --from-checkpoint should " \ - "not be set simultaneously." - assert not (args.phase1 and args.phase2), \ - "--phase1 and --phase2 should not be set simultaneously in bert pretraining." + assert not ( + args.from_checkpoint is not None + and args.from_pretrained_params is not None + ), ( + "--from-pretrained-params and --from-checkpoint should " + "not be set simultaneously." + ) + assert not ( + args.phase1 and args.phase2 + ), "--phase1 and --phase2 should not be set simultaneously in bert pretraining." if args.from_phase1_final_params is not None: - assert args.phase2, "--from-phase1-final-params should only be used in phase2" + assert ( + args.phase2 + ), "--from-phase1-final-params should only be used in phase2" # SQuAD finetuning does not support suspend-resume yet.(TODO) _get_full_path_of_ckpt(args) if args.bert_model == 'custom': - assert args.config_file is not None, "--config-file must be specified if --bert-model=custom" + assert ( + args.config_file is not None + ), "--config-file must be specified if --bert-model=custom" elif args.config_file is None: args.config_file = _DEFAULT_BERT_CONFIG[args.bert_model] logging.info( @@ -144,7 +177,19 @@ def check_and_process_args(args, task=Task.pretrain): _get_full_path_of_pretrained_params(args, task) assert os.path.isfile( - args.config_file), f"Cannot find config file in {args.config_file}" + args.config_file + ), f"Cannot find config file in {args.config_file}" + + # cudnn mha fusion is only supported after v8.9.1 on Ampere and Hopper GPU + device_capability = paddle.device.cuda.get_device_capability() + cudnn_mha_supported = paddle.get_cudnn_version() >= 8901 and ( + device_capability == (8, 0) or device_capability == (9, 0) + ) + if (not cudnn_mha_supported or args.amp is False) and args.fuse_mha is True: + logging.info( + f"cudnn mha fusion is not supported, fall back to unfused mha" + ) + args.fuse_mha = False def add_global_args(parser, task=Task.pretrain): @@ -155,144 +200,165 @@ def add_global_args(parser, task=Task.pretrain): type=str, default=None, required=True, - help='The input data directory. Should be specified by users and contain .hdf5 files for the task.' + help='The input data directory. Should be specified by users and contain .hdf5 files for the task.', ) + group.add_argument('--num-workers', default=1, type=int) if task == Task.squad: group.add_argument( '--train-file', type=str, default=None, - help='SQuAD json for training. E.g., train-v1.1.json') + help='SQuAD json for training. E.g., train-v1.1.json', + ) group.add_argument( '--predict-file', type=str, default=None, - help='SQuAD json for predictions. E.g., dev-v1.1.json or test-v1.1.json' + help='SQuAD json for predictions. E.g., dev-v1.1.json or test-v1.1.json', ) - group.add_argument( - '--vocab-file', - type=str, - default=None, - required=True, - help="Vocabulary mapping/file BERT was pretrainined on") group.add_argument( "--eval-script", help="Script to evaluate squad predictions", default="evaluate.py", - type=str) + type=str, + ) group.add_argument( '--epochs', type=int, default=3, - help='The number of epochs for training.') + help='The number of epochs for training.', + ) + group.add_argument( + '--vocab-file', + type=str, + default=None, + required=True, + help="Vocabulary mapping/file BERT was pretrainined on", + ) group.add_argument( '--output-dir', type=str, default=None, required=True, - help='The output directory where the model checkpoints will be written. Should be specified by users.' + help='The output directory where the model checkpoints will be written. Should be specified by users.', ) group.add_argument( '--bert-model', type=str, default='bert-large-uncased', - choices=('bert-base-uncased', 'bert-base-cased', 'bert-large-uncased', - 'bert-large-cased', 'custom'), + choices=( + 'bert-base-uncased', + 'bert-base-cased', + 'bert-large-uncased', + 'bert-large-cased', + 'custom', + ), help='Specifies the type of BERT model to use. If it is set as custom, ' - 'the path to the config file must be given by specifying --config-file') + 'the path to the config file must be given by specifying --config-file', + ) group.add_argument( '--config-file', type=str, default=None, - help='The BERT model config. If set to None, `<--bert-model>.json` in folder `bert_configs` will be used.' + help='The BERT model config. If set to None, `<--bert-model>.json` in folder `bert_configs` will be used.', ) group.add_argument( '--max-steps', type=int, default=None, required=True if task == Task.pretrain else False, - help='Total number of training steps to perform.') + help='Total number of training steps to perform.', + ) group.add_argument( - '--log-freq', type=int, default=10, help='Frequency of logging loss.') + '--log-freq', type=int, default=10, help='Frequency of logging loss.' + ) group.add_argument( '--num-steps-per-checkpoint', type=int, default=100, - help='Number of update steps until a model checkpoint is saved to disk.' + help='Number of update steps until a model checkpoint is saved to disk.', ) # Init model group.add_argument( '--from-pretrained-params', type=str, default=None, - help='Path to pretrained parameters. If set to None, no pretrained params will be used.' + help='Path to pretrained parameters. If set to None, no pretrained params will be used.', ) group.add_argument( '--from-checkpoint', type=str, default=None, - help='A checkpoint path to resume training. If set to None, no checkpoint will be used. ' \ - 'If not None, --from-pretrained-params will be ignored.') + help='A checkpoint path to resume training. If set to None, no checkpoint will be used. ' + 'If not None, --from-pretrained-params will be ignored.', + ) group.add_argument( '--last-step-of-checkpoint', type=str, default=None, - help='The step id of the checkpoint given by --from-checkpoint. ' \ - 'It should be None, auto, or integer > 0. If it is set as ' \ - 'None, then training will start from the 1-th epoch. If it is set as ' \ - 'auto, then it will search largest integer-convertable folder ' \ - ' --from-checkpoint, which contains required checkpoint. ' + help='The step id of the checkpoint given by --from-checkpoint. ' + 'It should be None, auto, or integer > 0. If it is set as ' + 'None, then training will start from the 1-th epoch. If it is set as ' + 'auto, then it will search largest integer-convertable folder ' + ' --from-checkpoint, which contains required checkpoint. ', ) if task == Task.pretrain: group.add_argument( '--from-phase1-final-params', type=str, default=None, - help='Path to final checkpoint of phase1, which will be used to ' \ - 'initialize the parameter in the first step of phase2, and ' \ - 'ignored in the rest steps of phase2.' + help='Path to final checkpoint of phase1, which will be used to ' + 'initialize the parameter in the first step of phase2, and ' + 'ignored in the rest steps of phase2.', ) group.add_argument( '--steps-this-run', type=int, default=None, - help='If provided, only run this many steps before exiting.' \ + help='If provided, only run this many steps before exiting.', ) group.add_argument( - '--seed', type=int, default=42, help="random seed for initialization") + '--seed', type=int, default=42, help="random seed for initialization" + ) group.add_argument( '--report-file', type=str, default='./report.json', - help='A file in which to store JSON experiment report.') + help='A file in which to store JSON experiment report.', + ) group.add_argument( '--model-prefix', type=str, default='bert_paddle', - help='The prefix name of model files to save/load.') + help='The prefix name of model files to save/load.', + ) group.add_argument( '--show-config', type=distutils.util.strtobool, default=True, - help='To show arguments.') + help='To show arguments.', + ) group.add_argument( '--enable-cpu-affinity', type=distutils.util.strtobool, default=True, - help='To enable in-built GPU-CPU affinity.') + help='To enable in-built GPU-CPU affinity.', + ) group.add_argument( - '--benchmark', action='http://github.com/store_true', help='To enable benchmark mode.') + '--benchmark', action='http://github.com/store_true', help='To enable benchmark mode.' + ) group.add_argument( '--benchmark-steps', type=int, default=20, - help='Steps for a benchmark run, only applied when --benchmark is set.') + help='Steps for a benchmark run, only applied when --benchmark is set.', + ) group.add_argument( '--benchmark-warmup-steps', type=int, default=20, - help='Warmup steps for a benchmark run, only applied when --benchmark is set.' + help='Warmup steps for a benchmark run, only applied when --benchmark is set.', ) return parser @@ -304,145 +370,166 @@ def add_training_args(parser, task=Task.pretrain): default='Lamb', metavar="OPTIMIZER", choices=('Lamb', 'AdamW'), - help='The name of optimizer. It should be one of {Lamb, AdamW}.') + help='The name of optimizer. It should be one of {Lamb, AdamW}.', + ) group.add_argument( '--gradient-merge-steps', type=int, default=1, - help="Number of update steps to accumualte before performing a backward/update pass." + help="Number of update steps to accumualte before performing a backward/update pass.", ) group.add_argument( '--learning-rate', type=float, default=1e-4, - help='The initial learning rate.') + help='The initial learning rate.', + ) group.add_argument( '--warmup-start-lr', type=float, default=0.0, - help='The initial learning rate for warmup.') + help='The initial learning rate for warmup.', + ) group.add_argument( '--warmup-proportion', type=float, default=0.01, help='Proportion of training to perform linear learning rate warmup for. ' - 'For example, 0.1 = 10%% of training.') + 'For example, 0.1 = 10%% of training.', + ) group.add_argument( '--beta1', type=float, default=0.9, - help='The exponential decay rate for the 1st moment estimates.') + help='The exponential decay rate for the 1st moment estimates.', + ) group.add_argument( '--beta2', type=float, default=0.999, - help='The exponential decay rate for the 2st moment estimates.') + help='The exponential decay rate for the 2st moment estimates.', + ) group.add_argument( '--epsilon', type=float, default=1e-6, - help='A small float value for numerical stability.') + help='A small float value for numerical stability.', + ) group.add_argument( '--weight-decay', type=float, default=0.01, - help='The weight decay coefficient.') + help='The weight decay coefficient.', + ) group.add_argument( '--max-seq-length', default=512, type=int, help='The maximum total input sequence length after WordPiece tokenization. \n' 'Sequences longer than this will be truncated, and sequences shorter \n' - 'than this will be padded.') + 'than this will be padded.', + ) if task == Task.pretrain: group.add_argument( '--batch-size', type=int, default=32, - help='The batch size for training') + help='The batch size for training', + ) group.add_argument( '--phase1', action='http://github.com/store_true', - help='The phase of BERT pretraining. It should not be set ' \ - 'with --phase2 at the same time.' + help='The phase of BERT pretraining. It should not be set ' + 'with --phase2 at the same time.', ) group.add_argument( '--phase2', action='http://github.com/store_true', - help='The phase of BERT pretraining. It should not be set ' \ - 'with --phase1 at the same time.' + help='The phase of BERT pretraining. It should not be set ' + 'with --phase1 at the same time.', ) group.add_argument( '--max-predictions-per-seq', default=80, type=int, - help='The maximum total of masked tokens in the input sequence') + help='The maximum total of masked tokens in the input sequence', + ) if task == Task.squad: group.add_argument( - "--do-train", action='http://github.com/store_true', help="Whether to run training.") + "--do-train", action='http://github.com/store_true', help="Whether to run training." + ) group.add_argument( "--do-predict", action='http://github.com/store_true', - help="Whether to run eval on the dev set.") + help="Whether to run eval on the dev set.", + ) group.add_argument( "--do-eval", action='http://github.com/store_true', - help="Whether to use evaluate accuracy of predictions") + help="Whether to use evaluate accuracy of predictions", + ) group.add_argument( "--train-batch-size", default=32, type=int, - help="Total batch size for training.") + help="Total batch size for training.", + ) group.add_argument( "--predict-batch-size", default=8, type=int, - help="Total batch size for predictions.") + help="Total batch size for predictions.", + ) group.add_argument( "--verbose-logging", action='http://github.com/store_true', help="If true, all of the warnings related to data processing will be printed. " - "A number of warnings are expected for a normal SQuAD evaluation.") + "A number of warnings are expected for a normal SQuAD evaluation.", + ) group.add_argument( "--doc-stride", default=128, type=int, help="When splitting up a long document into chunks, how much stride to take " - "between chunks.") + "between chunks.", + ) group.add_argument( "--max-query-length", default=64, type=int, help="The maximum number of tokens for the question. Questions longer than this " - "will be truncated to this length.") + "will be truncated to this length.", + ) group.add_argument( "--n-best-size", default=20, type=int, help="The total number of n-best predictions to generate in the nbest_predictions.json " - "output file.") + "output file.", + ) group.add_argument( "--max-answer-length", default=30, type=int, help="The maximum length of an answer that can be generated. This is needed because the start " - "and end predictions are not conditioned on one another.") + "and end predictions are not conditioned on one another.", + ) group.add_argument( "--do-lower-case", action='http://github.com/store_true', - help="Whether to lower case the input text. True for uncased models, False for cased models." + help="Whether to lower case the input text. True for uncased models, False for cased models.", ) group.add_argument( '--version-2-with-negative', action='http://github.com/store_true', - help='If true, the SQuAD examples contain some that do not have an answer.' + help='If true, the SQuAD examples contain some that do not have an answer.', ) group.add_argument( '--null-score-diff-threshold', type=float, default=0.0, - help="If null_score - best_non_null is greater than the threshold predict null." + help="If null_score - best_non_null is greater than the threshold predict null.", ) return parser @@ -452,22 +539,29 @@ def add_advance_args(parser): group.add_argument( '--amp', action='http://github.com/store_true', - help='Enable automatic mixed precision training (AMP).') + help='Enable automatic mixed precision training (AMP).', + ) group.add_argument( '--scale-loss', type=float, default=1.0, - help='The loss scalar for AMP training, only applied when --amp is set.' + help='The loss scalar for AMP training, only applied when --amp is set.', ) group.add_argument( '--use-dynamic-loss-scaling', action='http://github.com/store_true', - help='Enable dynamic loss scaling in AMP training, only applied when --amp is set.' + help='Enable dynamic loss scaling in AMP training, only applied when --amp is set.', ) group.add_argument( '--use-pure-fp16', action='http://github.com/store_true', - help='Enable pure FP16 training, only applied when --amp is set.') + help='Enable pure FP16 training, only applied when --amp is set.', + ) + group.add_argument( + '--fuse-mha', + action='http://github.com/store_true', + help='Enable multihead attention fusion. Require cudnn version >= 8.9.1', + ) return parser @@ -475,8 +569,10 @@ def add_advance_args(parser): def parse_args(task=Task.pretrain): parser = argparse.ArgumentParser( description="PaddlePaddle BERT pretraining script" - if task == Task.pretrain else "PaddlePaddle SQuAD finetuning script", - formatter_class=argparse.ArgumentDefaultsHelpFormatter) + if task == Task.pretrain + else "PaddlePaddle SQuAD finetuning script", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) parser = add_global_args(parser, task) parser = add_training_args(parser, task) diff --git a/PyTorch/Classification/ConvNets/image_classification/dataloaders.py b/PyTorch/Classification/ConvNets/image_classification/dataloaders.py index 47a25862a..7f3249b4d 100644 --- a/PyTorch/Classification/ConvNets/image_classification/dataloaders.py +++ b/PyTorch/Classification/ConvNets/image_classification/dataloaders.py @@ -34,6 +34,7 @@ import torchvision.transforms as transforms from PIL import Image from functools import partial +from torchvision.transforms.functional import InterpolationMode from image_classification.autoaugment import AutoaugmentImageNetPolicy @@ -422,9 +423,10 @@ def get_pytorch_train_loader( prefetch_factor=2, memory_format=torch.contiguous_format, ): - interpolation = {"bicubic": Image.BICUBIC, "bilinear": Image.BILINEAR}[ - interpolation - ] + interpolation = { + "bicubic": InterpolationMode.BICUBIC, + "bilinear": InterpolationMode.BILINEAR, + }[interpolation] traindir = os.path.join(data_path, "train") transforms_list = [ transforms.RandomResizedCrop(image_size, interpolation=interpolation), @@ -474,9 +476,10 @@ def get_pytorch_val_loader( memory_format=torch.contiguous_format, prefetch_factor=2, ): - interpolation = {"bicubic": Image.BICUBIC, "bilinear": Image.BILINEAR}[ - interpolation - ] + interpolation = { + "bicubic": InterpolationMode.BICUBIC, + "bilinear": InterpolationMode.BILINEAR, + }[interpolation] valdir = os.path.join(data_path, "val") val_dataset = datasets.ImageFolder( valdir, diff --git a/PyTorch/Classification/ConvNets/image_classification/models/resnet.py b/PyTorch/Classification/ConvNets/image_classification/models/resnet.py index 47e58022f..fbfd13c71 100644 --- a/PyTorch/Classification/ConvNets/image_classification/models/resnet.py +++ b/PyTorch/Classification/ConvNets/image_classification/models/resnet.py @@ -63,14 +63,16 @@ def __init__( stride=1, cardinality=1, downsample=None, + fused_se=True, last_bn_0_init=False, + trt=False, ): super(BasicBlock, self).__init__() - self.conv1 = builder.conv3x3(inplanes, planes, stride, cardinality=cardinality) + self.conv1 = builder.conv3x3(inplanes, planes, stride, groups=cardinality) self.bn1 = builder.batchnorm(planes) self.relu = builder.activation() self.conv2 = builder.conv3x3( - planes, planes * expansion, cardinality=cardinality + planes, planes * expansion, groups=cardinality ) self.bn2 = builder.batchnorm(planes * expansion, zero_init=last_bn_0_init) self.downsample = downsample diff --git a/PyTorch/Classification/GPUNet/README.md b/PyTorch/Classification/GPUNet/README.md index 02d272741..6a8a4ba20 100644 --- a/PyTorch/Classification/GPUNet/README.md +++ b/PyTorch/Classification/GPUNet/README.md @@ -413,7 +413,7 @@ We benchmark the training results following the steps in [Training](#training). ##### NVIDIA DGX V100 (8x V100 32GB) | **Model**|**Batch**| **Epochs** | **GPUs** | **FP32 Top1** | **AMP Top1** | **FP32 (hours)
Train Time** | **AMP (hours)
Train Time** | **Training speedup
(FP32 / AMP)** | |:--------:|:------:|:----------:|:--------:|:--------------:|:--------------:|:-------------------:|:-----------------------:|:--------------------------------:| -| GPUNet-0 |192 | 450 | 8 | 77.90+/-0.03 | 77.96+/-0.05 |71.63|46.56| 1.54 x | +| GPUNet-0 |192 | 450 | 8 | 78.90+/-0.03 | 78.96+/-0.05 |71.63|46.56| 1.54 x | | GPUNet-1 |192 | 450 | 8 | 80.4-+/-0.03 | 80.5+/-0.03 |67.5 |43.5 | 1.55 x | | GPUNet-2 |192 | 450 | 8 | 82.1-+/-0.04 | 82.2+/-0.04 |171 |84.25| 2.03 x | diff --git a/PyTorch/Detection/Efficientdet/data/dataset.py b/PyTorch/Detection/Efficientdet/data/dataset.py index de3ee474f..b01a01264 100644 --- a/PyTorch/Detection/Efficientdet/data/dataset.py +++ b/PyTorch/Detection/Efficientdet/data/dataset.py @@ -43,7 +43,7 @@ class CocoDetection(data.Dataset): def __init__(self, root, ann_file, config, transform=None): super(CocoDetection, self).__init__() - if isinstance(root, torch._six.string_classes): + if isinstance(root, (str, bytes)): root = os.path.expanduser(root) self.root = root self.transform = transform diff --git a/PyTorch/Detection/Efficientdet/train.py b/PyTorch/Detection/Efficientdet/train.py index 7ca278b57..b59472cc3 100755 --- a/PyTorch/Detection/Efficientdet/train.py +++ b/PyTorch/Detection/Efficientdet/train.py @@ -521,12 +521,14 @@ def train_epoch( model.train() + torch.cuda.synchronize() end = time.time() last_idx = steps_per_epoch - 1 num_updates = epoch * steps_per_epoch for batch_idx in range(steps_per_epoch): input, target = next(loader_iter) last_batch = batch_idx == last_idx + torch.cuda.synchronize() data_time_m.update(time.time() - end) with torch.cuda.amp.autocast(enabled=use_amp): @@ -575,6 +577,7 @@ def train_epoch( if lr_scheduler is not None: lr_scheduler.step_update(num_updates=num_updates, metric=losses_m.avg) + torch.cuda.synchronize() end = time.time() if args.benchmark: if batch_idx >= args.benchmark_steps: @@ -597,6 +600,7 @@ def validate(model, loader, args, evaluator=None, epoch=0, log_suffix=''): model.eval() + torch.cuda.synchronize() end = time.time() last_idx = len(loader) - 1 with torch.no_grad(): diff --git a/PyTorch/Detection/Efficientdet/validate.py b/PyTorch/Detection/Efficientdet/validate.py index 6145596c2..06eaa69db 100644 --- a/PyTorch/Detection/Efficientdet/validate.py +++ b/PyTorch/Detection/Efficientdet/validate.py @@ -208,12 +208,14 @@ def validate(args): bench.eval() batch_time = AverageMeter() throughput = AverageMeter() + torch.cuda.synchronize() end = time.time() total_time_start = time.time() with torch.no_grad(): for i, (input, target) in enumerate(loader): with torch.cuda.amp.autocast(enabled=args.amp): output = bench(input, target['img_scale'], target['img_size']) + torch.cuda.synchronize() batch_time.update(time.time() - end) throughput.update(input.size(0) / batch_time.val) evaluator.add_predictions(output, target) @@ -235,6 +237,7 @@ def validate(args): ) end = time.time() + torch.cuda.synchronize() dllogger_metric['total_inference_time'] = time.time() - total_time_start dllogger_metric['inference_throughput'] = throughput.avg dllogger_metric['inference_time'] = 1000 / throughput.avg @@ -245,6 +248,7 @@ def validate(args): mean_ap = evaluator.evaluate() else: evaluator.save_predictions(args.results) + torch.cuda.synchronize() dllogger_metric['map'] = mean_ap dllogger_metric['total_eval_time'] = time.time() - total_time_start else: diff --git a/PyTorch/Detection/SSD/Dockerfile b/PyTorch/Detection/SSD/Dockerfile index baa382bd8..822683b70 100755 --- a/PyTorch/Detection/SSD/Dockerfile +++ b/PyTorch/Detection/SSD/Dockerfile @@ -1,20 +1,14 @@ -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:21.07-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.10-py3 FROM ${FROM_IMAGE_NAME} # Set working directory WORKDIR /workspace/ssd -# Install nv-cocoapi -ENV COCOAPI_VERSION=2.0+nv0.6.0 -RUN export COCOAPI_TAG=$(echo ${COCOAPI_VERSION} | sed 's/^.*+n//') \ - && pip install --no-cache-dir pybind11 \ - && pip install --no-cache-dir git+https://github.com/NVIDIA/cocoapi.git@${COCOAPI_TAG}#subdirectory=PythonAPI -# Install dllogger -RUN pip install --no-cache-dir git+https://github.com/NVIDIA/dllogger.git#egg=dllogger +# Copy the model files +COPY . . -# Install requirements -COPY requirements.txt . -RUN pip install -r requirements.txt -RUN python3 -m pip install pycocotools==2.0.0 +# Install python requirements +RUN pip install --no-cache-dir -r requirements.txt -COPY . . +ENV CUDNN_V8_API_ENABLED=1 +ENV TORCH_CUDNN_V8_API_ENABLED=1 diff --git a/PyTorch/Detection/SSD/README.md b/PyTorch/Detection/SSD/README.md index 402616e5d..b3ad035e7 100644 --- a/PyTorch/Detection/SSD/README.md +++ b/PyTorch/Detection/SSD/README.md @@ -218,11 +218,11 @@ The following section lists the requirements in order to start training the SSD3 ### Requirements -This repository contains `Dockerfile` which extends the PyTorch 21.05 NGC container +This repository contains `Dockerfile` which extends the PyTorch 22.10 NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following software: * [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -* [PyTorch 21.05 NGC container](https://ngc.nvidia.com/registry/nvidia-pytorch) +* [PyTorch 22.10 NGC container](https://ngc.nvidia.com/registry/nvidia-pytorch) * GPU-based architecture: * [NVIDIA Volta](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) * [NVIDIA Turing](https://www.nvidia.com/en-us/geforce/turing/) @@ -235,7 +235,7 @@ Documentation: * [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/dgx/user-guide/index.html#accessing_registry) * [Running PyTorch](https://docs.nvidia.com/deeplearning/dgx/pytorch-release-notes/running.html#running) -For those unable to use the [PyTorch 21.05 NGC container](https://ngc.nvidia.com/registry/nvidia-pytorch), +For those unable to use the [PyTorch 22.10 NGC container](https://ngc.nvidia.com/registry/nvidia-pytorch), to set up the required environment or create your own container, see the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). @@ -475,18 +475,18 @@ to evaluate models on the COCO dataset. We are using these scripts during validation to measure a models performance in AP metric. Metrics below are evaluated using pycocotools’ methodology, in the following format: ``` - Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.250 - Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.423 - Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.257 - Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.076 - Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.269 - Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.399 - Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.237 - Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.342 - Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.358 - Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.118 - Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.394 - Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.548 + Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.27205 + Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.45869 + Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.27884 + Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.08275 + Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.29840 + Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.42722 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.25092 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.36528 + Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.38262 + Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.13577 + Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.42287 + Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.57277 ``` The metric reported in our results is present in the first row. @@ -542,7 +542,7 @@ The training benchmark was run in various scenarios on A100 80GB and V100 16G GP To benchmark training, run: ``` -python -m torch.distributed.launch --nproc_per_node={NGPU} \ +torchrun --nproc_per_node={NGPU} \ main.py --batch-size {bs} \ --mode benchmark-training \ --benchmark-warmup 100 \ @@ -583,37 +583,34 @@ The following sections provide details on how we achieved our performance and ac ##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) Our results were obtained by running the `./examples/SSD300_A100_{FP16,TF32}_{1,4,8}GPU.sh` -script in the `pytorch-21.05-py3` NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. +script in the `pytorch-22.10-py3` NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. |GPUs |Batch size / GPU|Accuracy - TF32|Accuracy - mixed precision|Time to train - TF32|Time to train - mixed precision|Time to train speedup (TF32 to mixed precision)| |-----------|----------------|---------------|---------------------------|--------------------|--------------------------------|------------------------------------------------| -|1 |64 |0.26 |0.26 |07:45:00 |05:09:00 |150.49% | -|4 |64 |0.26 |0.26 |01:59:00 |01:19:00 |149.52% | -|8 |64 |0.25 |0.26 |01:02:00 |00:40:00 |155.64% | -|1 |128 |0.26 |0.26 |07:36:00 |04:57:00 |153.50% | -|4 |128 |0.26 |0.26 |01:55:00 |01:15:00 |152.92% | -|8 |128 |0.26 |0.25 |00:58:00 |00:38:00 |151.89% | -|1 |256 |0.26 |0.26 |07:34:00 |04:53:00 |154.80% | -|4 |256 |0.25 |0.26 |01:54:00 |01:14:00 |152.98% | -|8 |256 |0.248 |0.25 |00:57:00 |00:37:00 |151.46% | +|1 |64 |0.271 |0.272 |03:19:59 |03:18:35 |100% | +|4 |64 |0.270 |0.270 |00:51:22 |00:51:31 | 99% | +|8 |64 |0.270 |0.269 |00:26:10 |00:26:10 | 99% | +|1 |128 |0.274 |0.271 |03:03:56 |03:03:50 |100% | +|4 |128 |0.272 |0.270 |00:46:51 |00:47:01 | 99% | +|8 |128 |0.267 |0.267 |00:23:44 |00:23:46 | 99% | +|1 |256 |0.272 |0.272 |02:56:37 |02:56:44 | 99% | +|4 |256 |0.271 |0.267 |00:45:05 |00:45:07 | 99% | +|8 |256 |0.260 |0.258 |00:22:49 |00:22:56 |100% | ##### Training accuracy: NVIDIA DGX-1 (8x V100 16GB) Our results were obtained by running the `./examples/SSD300_FP{16,32}_{1,4,8}GPU.sh` -script in the `pytorch-21.05-py3` NGC container on NVIDIA DGX-1 with 8x +script in the `pytorch-22.10-py3` NGC container on NVIDIA DGX-1 with 8x V100 16GB GPUs. |GPUs |Batch size / GPU|Accuracy - FP32|Accuracy - mixed precision|Time to train - FP32|Time to train - mixed precision|Time to train speedup (FP32 to mixed precision)| |-----------|----------------|---------------|---------------------------|--------------------|--------------------------------|------------------------------------------------| -|1 |32 |0.26 |0.26 |20:14:00 |10:09:00 |199.30% | -|4 |32 |0.25 |0.25 |05:10:00 |02:40:00 |193.88% | -|8 |32 |0.26 |0.25 |02:35:00 |01:20:00 |192.24% | -|1 |64 | |0.26 |09:34:00 | | | -|4 |64 | |0.26 |02:27:00 | | | -|8 |64 | |0.26 |01:14:00 | | | - - - +|1 |32 |0.269 |0.271 |20:04:48 |07:25:27 |270% | +|4 |32 |0.270 |0.269 |05:08:56 |01:58:41 |260% | +|8 |32 |0.271 |0.269 |02:35:00 |01:00:27 |256% | +|1 |64 | |0.272 | |06:47:58 | | +|4 |64 | |0.270 | |01:46:34 | | +|8 |64 | |0.269 | |00:53:52 | | Due to smaller size, mixed precision models can be trained with bigger batches. In such cases mixed precision speedup is calculated versus FP32 training with maximum batch size for that precision @@ -626,52 +623,51 @@ Here are example graphs of FP32, TF32 and AMP training on 8 GPU configuration: ##### Training stability test The SSD300 v1.1 model was trained for 65 epochs, starting -from 15 different initial random seeds. The training was performed in the `pytorch-21.05-py3` NGC container on +from 15 different initial random seeds. The training was performed in the `pytorch-22.10-py3` NGC container on NVIDIA DGX A100 8x A100 80GB GPUs with batch size per GPU = 128. After training, the models were evaluated on the test dataset. The following table summarizes the final mAP on the test set. |**Precision**|**Average mAP**|**Standard deviation**|**Minimum**|**Maximum**|**Median**| |------------:|--------------:|---------------------:|----------:|----------:|---------:| -| AMP | 0.2514314286 | 0.001498316675 | 0.24456 | 0.25182 | 0.24907 | -| TF32 | 0.2489106667 | 0.001749463047 | 0.24487 | 0.25148 | 0.24848 | - +| AMP | 0.2679503039 | 0.001360494012 | 0.26201 | 0.27013 | 0.26529 | +| TF32 | 0.2670691823 | 0.001639394102 | 0.26181 | 0.27274 | 0.26492 | #### Training performance results ##### Training performance: NVIDIA DGX A100 (8x A100 80GB) Our results were obtained by running the `main.py` script with the `--mode -benchmark-training` flag in the `pytorch-21.05-py3` NGC container on NVIDIA +benchmark-training` flag in the `pytorch-22.10-py3` NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. |GPUs |Batch size / GPU|Throughput - TF32|Throughput - mixed precision|Throughput speedup (TF32 - mixed precision)|Weak scaling - TF32 |Weak scaling - mixed precision | |-----------|----------------|-----------------|-----------------------------|-------------------------------------------|--------------------------------|------------------------------------------------| -|1 |64 |279.85 |428.30 |153.04% |100% |100% | -|4 |64 |1095.17 |1660.59 |151.62% |391% |387% | -|8 |64 |2181.21 |3301.58 |151.36% |779% |770% | -|1 |128 |286.17 |440.74 |154.01% |100% |100% | -|4 |128 |1135.02 |1755.94 |154.70% |396% |398% | -|8 |128 |2264.92 |3510.29 |154.98% |791% |796% | +|1 |64 | 364.27 | 662.91 |181% |100% |100% | +|4 |64 |1432.73 |2581.24 |180% |393% |389% | +|8 |64 |2838.76 |5252.84 |185% |779% |792% | +|1 |128 | 377.18 | 724.41 |192% |100% |100% | +|4 |128 |1493.13 |2885.55 |193% |395% |398% | +|8 |128 |2967.23 |5733.98 |193% |786% |791% | To achieve these same results, follow the [Quick Start Guide](#quick-start-guide) outlined above. ##### Training performance: NVIDIA DGX-1 (8x V100 16GB) Our results were obtained by running the `main.py` script with the `--mode -benchmark-training` flag in the `pytorch-21.05-py3` NGC container on NVIDIA +benchmark-training` flag in the `pytorch-22.10-py3` NGC container on NVIDIA DGX-1 with 8x V100 16GB GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. |GPUs |Batch size / GPU|Throughput - FP32|Throughput - mixed precision|Throughput speedup (FP32 - mixed precision)|Weak scaling - FP32 |Weak scaling - mixed precision | |-----------|----------------|-----------------|-----------------------------|-------------------------------------------|--------------------------------|------------------------------------------------| -|1 |32 |108.27 |212.95 |196.68% |100% |100% | -|4 |32 |425.07 |826.38 |194.41% |392% |388% | -|8 |32 |846.58 |1610.82 |190.27% |781% |756% | -|1 |64 | |227.69 | | |100% | -|4 |64 | |891.27 | | |391% | -|8 |64 | |1770.09 | | |777% | +|1 |32 |107.22 | 296.80 |276% |100% |100% | +|4 |32 |419.54 |1115.59 |265% |391% |375% | +|8 |32 |840.35 |2153.96 |256% |783% |725% | +|1 |64 | | 322.81 | | |100% | +|4 |64 | |1238.27 | | |383% | +|8 |64 | |2520.50 | | |780% | Due to smaller size, mixed precision models can be trained with bigger batches. In such cases mixed precision speedup is calculated versus FP32 training with maximum batch size for that precision @@ -682,35 +678,35 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ##### Inference performance: NVIDIA DGX A100 (1x A100 80GB) Our results were obtained by running the `main.py` script with `--mode -benchmark-inference` flag in the pytorch-21.05-py3 NGC container on NVIDIA +benchmark-inference` flag in the pytorch-22.10-py3 NGC container on NVIDIA DGX A100 (1x A100 80GB) GPU. |Batch size |Throughput - TF32|Throughput - mixed precision|Throughput speedup (TF32 - mixed precision)|Weak scaling - TF32 |Weak scaling - mixed precision | |-----------|-----------------|-----------------------------|-------------------------------------------|--------------------|--------------------------------| -|1 |105.53 | 90.62 | 85% |100% | 100% | -|2 |197.77 | 168.41 | 85% |187% | 185% | -|4 |332.10 | 323.68 | 97% |314% | 357% | -|8 |526.12 | 523.96 | 99% |498% | 578% | -|16 |634.50 | 816.91 |128% |601% | 901% | -|32 |715.35 | 956.91 |133% |677% |1055% | -|64 |752.57 |1053.39 |139% |713% |1162% | +|1 |158.83 | 142.67 | 89% |100% |100% | +|2 |308.31 | 261.21 | 84% |194% |183% | +|4 |481.69 | 454.95 | 94% |303% |318% | +|8 |597.72 | 742.05 |124% |376% |520% | +|16 |590.44 | 887.01 |150% |371% |621% | +|32 |708.97 | 970.27 |136% |446% |680% | +|64 |798.16 |1057.51 |132% |502% |741% | To achieve these same results, follow the [Quick Start Guide](#quick-start-guide) outlined above. ##### Inference performance: NVIDIA DGX-1 (1x V100 16GB) Our results were obtained by running the `main.py` script with `--mode -benchmark-inference` flag in the pytorch-21.05-py3 NGC container on NVIDIA +benchmark-inference` flag in the pytorch-22.10-py3 NGC container on NVIDIA DGX-1 with (1x V100 16GB) GPU. |Batch size |Throughput - FP32|Throughput - mixed precision|Throughput speedup (FP32 - mixed precision)|Weak scaling - FP32 |Weak scaling - mixed precision | |-----------|-----------------|-----------------------------|-------------------------------------------|--------------------|--------------------------------| -|1 | 75.05 | 57.03 | 75% |100% |100% | -|2 |138.39 |117.12 | 84% |184% |205% | -|4 |190.74 |185.38 | 97% |254% |325% | -|8 |237.34 |368.48 |155% |316% |646% | -|16 |285.32 |504.77 |176% |380% |885% | -|32 |306.22 |548.87 |179% |408% |962% | +|1 | 93.21 | 84.59 | 90% |100% |100% | +|2 |148.61 |165.30 |111% |159% |195% | +|4 |206.82 |304.77 |147% |221% |360% | +|8 |242.55 |447.25 |184% |260% |528% | +|16 |292.44 |541.05 |185% |313% |639% | +|32 |311.61 |605.30 |194% |334% |715% | To achieve these same results, follow the [Quick Start Guide](#quick-start-guide) outlined above. @@ -718,6 +714,32 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ### Changelog +October 2022 + * upgrade the PyTorch container to 22.10 + * switched to using torchvision IMAGENET1K_V2 backbone weights + * added a flag to control for torchvision weight enums + * added a flag to control TF32 computations + * fixed various depreciation warnings + * set `TORCH_CUDNN_V8_API_ENABLED` environment variable which replaces `CUDNN_V8_API_ENABLED` from older containers + * updated [nv-cocoapi](https://github.com/NVIDIA/cocoapi/) from 0.6.0 to 0.7.3 + * updated python dependencies + +June 2022 + * upgrade the PyTorch container to 22.05 + * fixed DALI depreciation warnings + +January 2022 + * upgrade the PyTorch container to 22.01 + * made AMP the default data precision + * added --data-layout option (channels_first is the recommended layout with --no-amp) + * updated README with new performance numbers + +November 2021 + * upgrade the PyTorch container to 21.11 + * switched data layout from NCHW (channels first) to NHWC (channels last) + * replaced `torch.distributed.launch` with `torchrun` + * updated README with new performance numbers + May 2021 * upgrade the PyTorch container to 21.05 * replaced APEX AMP with native PyTorch AMP diff --git a/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_1GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_1GPU.sh index 1754a4aa5..3b880fc3f 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_1GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_1GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP16 on 1 GPUs using 256 batch size # Usage bash SSD300_FP16_1GPU.sh -python $1/main.py --backbone resnet50 --warmup 300 --bs 256 --amp --data $2 ${@:3} +python $1/main.py --backbone resnet50 --warmup 300 --bs 256 --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_4GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_4GPU.sh index 1aa66e10b..23580ed3d 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_4GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_4GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP16 on 4 GPUs using 1024 batch size (256 per GPU) # Usage ./SSD300_FP16_4GPU.sh -python -m torch.distributed.launch --nproc_per_node=4 $1/main.py --backbone resnet50 --learning-rate 2.7e-3 --warmup 1200 --bs 256 --amp --data $2 ${@:3} +torchrun --nproc_per_node=4 $1/main.py --backbone resnet50 --learning-rate 2.7e-3 --warmup 1200 --bs 256 --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_8GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_8GPU.sh index 2857d0943..95007f6a9 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_8GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_A100_FP16_8GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP16 on 8 GPUs using 1024 batch size (128 per GPU) # Usage ./SSD300_FP16_8GPU.sh -python -m torch.distributed.launch --nproc_per_node=8 $1/main.py --backbone resnet50 --learning-rate 2.7e-3 --warmup 1200 --bs 128 --amp --data $2 ${@:3} +torchrun --nproc_per_node=8 $1/main.py --backbone resnet50 --learning-rate 2.7e-3 --warmup 1200 --bs 128 --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_A100_FP32_8GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_A100_FP32_8GPU.sh index 72c8e438f..eb455cab5 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_A100_FP32_8GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_A100_FP32_8GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP32 on 8 GPUs using 1024 batch size (128 per GPU) # Usage ./SSD300_FP32_8GPU.sh -python -m torch.distributed.launch --nproc_per_node=8 $1/main.py --backbone resnet50 --learning-rate 2.7e-3 --warmup 1200 --bs 128 --data $2 ${@:3} +torchrun --nproc_per_node=8 $1/main.py --backbone resnet50 --learning-rate 2.7e-3 --warmup 1200 --bs 128 --no-amp --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP16_1GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_FP16_1GPU.sh index b2b4b9859..64037b569 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP16_1GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP16_1GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP16 on 1 GPUs using 64 batch size # Usage bash SSD300_FP16_1GPU.sh -python $1/main.py --backbone resnet50 --warmup 300 --bs 64 --amp --data $2 ${@:3} +python $1/main.py --backbone resnet50 --warmup 300 --bs 64 --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP16_4GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_FP16_4GPU.sh index f015bf3c2..dc1b40070 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP16_4GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP16_4GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP16 on 4 GPUs using 256 batch size (64 per GPU) # Usage ./SSD300_FP16_4GPU.sh -python -m torch.distributed.launch --nproc_per_node=4 $1/main.py --backbone resnet50 --warmup 300 --bs 64 --amp --data $2 ${@:3} +torchrun --nproc_per_node=4 $1/main.py --backbone resnet50 --warmup 300 --bs 64 --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP16_8GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_FP16_8GPU.sh index 4434e8e3c..d62e60012 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP16_8GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP16_8GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP16 on 8 GPUs using 512 batch size (64 per GPU) # Usage ./SSD300_FP16_8GPU.sh -python -m torch.distributed.launch --nproc_per_node=8 $1/main.py --backbone resnet50 --warmup 300 --bs 64 --amp --data $2 ${@:3} +torchrun --nproc_per_node=8 $1/main.py --backbone resnet50 --warmup 300 --bs 64 --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP16_EVAL.sh b/PyTorch/Detection/SSD/examples/SSD300_FP16_EVAL.sh index 96adfbf50..1b233942c 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP16_EVAL.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP16_EVAL.sh @@ -1,4 +1,4 @@ # This script evaluates SSD300 model in FP16 using 32 batch size on 1 GPU # Usage: ./SSD300_FP16_EVAL.sh -python $1/main.py --backbone resnet50 --amp --ebs 32 --data $2 --mode evaluation --checkpoint $3 ${@:4} +python $1/main.py --backbone resnet50 --ebs 32 --data $2 --mode evaluation --checkpoint $3 ${@:4} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP16_INFERENCE_BENCHMARK.sh b/PyTorch/Detection/SSD/examples/SSD300_FP16_INFERENCE_BENCHMARK.sh index c26b80072..75fe322a8 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP16_INFERENCE_BENCHMARK.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP16_INFERENCE_BENCHMARK.sh @@ -1,4 +1,4 @@ # This script launches SSD300 inference benchmark in FP16 on 1 GPU with 64 batch size # Usage bash SSD300_FP16_INFERENCE_BENCHMARK.sh -python $1/main.py --backbone resnet50 --mode benchmark-inference --bs 64 --amp --data $2 ${@:3} +python $1/main.py --backbone resnet50 --mode benchmark-inference --bs 64 --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP32_1GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_FP32_1GPU.sh index ea5240a76..d7e148dfd 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP32_1GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP32_1GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP32 on 1 GPUs using 32 batch size # Usage ./SSD300_FP32_1GPU.sh -python $1/main.py --backbone resnet50 --bs 32 --warmup 300 --data $2 ${@:3} +python $1/main.py --backbone resnet50 --bs 32 --warmup 300 --no-amp --data-layout channels_first --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP32_4GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_FP32_4GPU.sh index 29159557a..96b6a92bd 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP32_4GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP32_4GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP32 on 4 GPUs using 128 batch size (32 per GPU) # Usage ./SSD300_FP32_4GPU.sh -python -m torch.distributed.launch --nproc_per_node=4 $1/main.py --backbone resnet50 --warmup 300 --bs 32 --data $2 ${@:3} +torchrun --nproc_per_node=4 $1/main.py --backbone resnet50 --warmup 300 --bs 32 --no-amp --data-layout channels_first --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP32_8GPU.sh b/PyTorch/Detection/SSD/examples/SSD300_FP32_8GPU.sh index 441efd9d0..b880359c9 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP32_8GPU.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP32_8GPU.sh @@ -1,4 +1,4 @@ # This script launches SSD300 training in FP32 on 8 GPUs using 256 batch size (32 per GPU) # Usage ./SSD300_FP32_8GPU.sh -python -m torch.distributed.launch --nproc_per_node=8 $1/main.py --backbone resnet50 --warmup 300 --bs 32 --data $2 ${@:3} +torchrun --nproc_per_node=8 $1/main.py --backbone resnet50 --warmup 300 --bs 32 --no-amp --data-layout channels_first --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP32_EVAL.sh b/PyTorch/Detection/SSD/examples/SSD300_FP32_EVAL.sh index b3179c1ed..cd387f777 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP32_EVAL.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP32_EVAL.sh @@ -1,4 +1,4 @@ # This script evaluates SSD300 model in FP32 using 32 batch size on 1 GPU # Usage: ./SSD300_FP32_EVAL.sh -python $1/main.py --backbone resnet50 --ebs 32 --data $2 --mode evaluation --checkpoint $3 ${@:4} +python $1/main.py --backbone resnet50 --ebs 32 --data $2 --mode evaluation --no-amp --data-layout channels_first --checkpoint $3 ${@:4} diff --git a/PyTorch/Detection/SSD/examples/SSD300_FP32_INFERENCE_BENCHMARK.sh b/PyTorch/Detection/SSD/examples/SSD300_FP32_INFERENCE_BENCHMARK.sh index e7c0fa864..8f46338b4 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_FP32_INFERENCE_BENCHMARK.sh +++ b/PyTorch/Detection/SSD/examples/SSD300_FP32_INFERENCE_BENCHMARK.sh @@ -1,4 +1,4 @@ # This script launches SSD300 inference benchmark in FP32 on 1 GPU with 64 batch size # Usage bash SSD300_FP32_INFERENCE_BENCHMARK.sh -python $1/main.py --backbone resnet50 --warmup 300 --mode benchmark-inference --bs 32 --data $2 ${@:3} +python $1/main.py --backbone resnet50 --warmup 300 --mode benchmark-inference --bs 32 --no-amp --data-layout channels_first --data $2 ${@:3} diff --git a/PyTorch/Detection/SSD/examples/SSD300_inference.py b/PyTorch/Detection/SSD/examples/SSD300_inference.py index bc5b20d9c..8681b423f 100644 --- a/PyTorch/Detection/SSD/examples/SSD300_inference.py +++ b/PyTorch/Detection/SSD/examples/SSD300_inference.py @@ -28,7 +28,7 @@ def load_checkpoint(model, model_file): def build_predictor(model_file, backbone='resnet50'): - ssd300 = SSD300(backbone=ResNet(backbone)) + ssd300 = SSD300(backbone=ResNet(backbone=backbone)) load_checkpoint(ssd300, model_file) return ssd300 diff --git a/PyTorch/Detection/SSD/main.py b/PyTorch/Detection/SSD/main.py index c0c4db41b..4c3fc3e69 100644 --- a/PyTorch/Detection/SSD/main.py +++ b/PyTorch/Detection/SSD/main.py @@ -67,6 +67,9 @@ def make_parser(): help='manually set random seed for torch') parser.add_argument('--checkpoint', type=str, default=None, help='path to model checkpoint file') + parser.add_argument('--torchvision-weights-version', type=str, default="IMAGENET1K_V2", + choices=['IMAGENET1K_V1', 'IMAGENET1K_V2', 'DEFAULT'], + help='The torchvision weights version to use when --checkpoint is not specified') parser.add_argument('--save', type=str, default=None, help='save model checkpoints in the specified directory') parser.add_argument('--mode', type=str, default='training', @@ -97,9 +100,19 @@ def make_parser(): ' backbone model declared with the --backbone argument.' ' When it is not provided, pretrained model from torchvision' ' will be downloaded.') - parser.add_argument('--num-workers', type=int, default=4) - parser.add_argument('--amp', action='http://github.com/store_true', - help='Whether to enable AMP ops. When false, uses TF32 on A100 and FP32 on V100 GPUS.') + parser.add_argument('--num-workers', type=int, default=8) + parser.add_argument("--amp", dest='amp', action="http://github.com/store_true", + help="Enable Automatic Mixed Precision (AMP).") + parser.add_argument("--no-amp", dest='amp', action="http://github.com/store_false", + help="Disable Automatic Mixed Precision (AMP).") + parser.set_defaults(amp=True) + parser.add_argument("--allow-tf32", dest='allow_tf32', action="http://github.com/store_true", + help="Allow TF32 computations on supported GPUs.") + parser.add_argument("--no-allow-tf32", dest='allow_tf32', action="http://github.com/store_false", + help="Disable TF32 computations.") + parser.set_defaults(allow_tf32=True) + parser.add_argument('--data-layout', default="channels_last", choices=['channels_first', 'channels_last'], + help="Model data layout. It's recommended to use channels_first with --no-amp") parser.add_argument('--log-interval', type=int, default=20, help='Logging interval.') parser.add_argument('--json-summary', type=str, default=None, @@ -150,7 +163,9 @@ def train(train_loop_func, logger, args): val_dataset = get_val_dataset(args) val_dataloader = get_val_dataloader(val_dataset, args) - ssd300 = SSD300(backbone=ResNet(args.backbone, args.backbone_path)) + ssd300 = SSD300(backbone=ResNet(backbone=args.backbone, + backbone_path=args.backbone_path, + weights=args.torchvision_weights_version)) args.learning_rate = args.learning_rate * args.N_gpu * (args.batch_size / 32) start_epoch = 0 iteration = 0 @@ -223,6 +238,7 @@ def train(train_loop_func, logger, args): obj['model'] = ssd300.module.state_dict() else: obj['model'] = ssd300.state_dict() + os.makedirs(args.save, exist_ok=True) save_path = os.path.join(args.save, f'epoch_{epoch}.pt') torch.save(obj, save_path) logger.log('model path', save_path) @@ -261,6 +277,8 @@ def log_params(logger, args): if args.local_rank == 0: os.makedirs('./models', exist_ok=True) + torch.backends.cuda.matmul.allow_tf32 = args.allow_tf32 + torch.backends.cudnn.allow_tf32 = args.allow_tf32 torch.backends.cudnn.benchmark = True # write json only on the main thread diff --git a/PyTorch/Detection/SSD/requirements.txt b/PyTorch/Detection/SSD/requirements.txt index db0e31dff..636a76589 100644 --- a/PyTorch/Detection/SSD/requirements.txt +++ b/PyTorch/Detection/SSD/requirements.txt @@ -1,3 +1,6 @@ -Cython>=0.28.4 -scikit-image>=0.15.0 -ujson>=4.0.2 +Cython>=0.29.32 +scikit-image>=0.19.3 +ujson>=5.5.0 +pybind11>=2.10.0 +git+https://github.com/NVIDIA/cocoapi.git@v0.7.3#subdirectory=PythonAPI +git+https://github.com/NVIDIA/dllogger.git#egg=dllogger diff --git a/PyTorch/Detection/SSD/ssd/coco_pipeline.py b/PyTorch/Detection/SSD/ssd/coco_pipeline.py index 3e2865b44..88a844422 100644 --- a/PyTorch/Detection/SSD/ssd/coco_pipeline.py +++ b/PyTorch/Detection/SSD/ssd/coco_pipeline.py @@ -21,6 +21,7 @@ # DALI imports import nvidia.dali as dali from nvidia.dali.pipeline import Pipeline +from nvidia.dali.types import to_numpy_type class COCOPipeline(Pipeline): @@ -124,14 +125,14 @@ def define_graph(self): return (images, bboxes.gpu(), labels.gpu()) to_torch_type = { - np.dtype(np.float32) : torch.float32, - np.dtype(np.float64) : torch.float64, - np.dtype(np.float16) : torch.float16, - np.dtype(np.uint8) : torch.uint8, - np.dtype(np.int8) : torch.int8, - np.dtype(np.int16) : torch.int16, - np.dtype(np.int32) : torch.int32, - np.dtype(np.int64) : torch.int64 + np.float32 : torch.float32, + np.float64 : torch.float64, + np.float16 : torch.float16, + np.uint8 : torch.uint8, + np.int8 : torch.int8, + np.int16 : torch.int16, + np.int32 : torch.int32, + np.int64 : torch.int64 } def feed_ndarray(dali_tensor, arr): @@ -242,9 +243,9 @@ def __next__(self): labels_shape[j].append(lshape) # We always need to alocate new memory as bboxes and labels varies in shape - images_torch_type = to_torch_type[np.dtype(images[0].dtype())] - bboxes_torch_type = to_torch_type[np.dtype(bboxes[0][0].dtype())] - labels_torch_type = to_torch_type[np.dtype(labels[0][0].dtype())] + images_torch_type = to_torch_type[to_numpy_type(images[0].dtype)] + bboxes_torch_type = to_torch_type[to_numpy_type(bboxes[0][0].dtype)] + labels_torch_type = to_torch_type[to_numpy_type(labels[0][0].dtype)] torch_gpu_device = torch.device('cuda', dev_id) torch_cpu_device = torch.device('cpu') diff --git a/PyTorch/Detection/SSD/ssd/evaluate.py b/PyTorch/Detection/SSD/ssd/evaluate.py index 20ede8842..e96df0aaf 100644 --- a/PyTorch/Detection/SSD/ssd/evaluate.py +++ b/PyTorch/Detection/SSD/ssd/evaluate.py @@ -52,10 +52,8 @@ def evaluate(model, coco, cocoGt, encoder, inv_map, args): try: result = encoder.decode_batch(ploc_i, plabel_i, 0.50, 200)[0] - except: - # raise - print("") - print("No object detected in idx: {}".format(idx)) + except Exception as e: + print("Skipping idx {}, failed to decode with message {}, Skipping.".format(idx, e)) continue htot, wtot = img_size[0][idx].item(), img_size[1][idx].item() diff --git a/PyTorch/Detection/SSD/ssd/model.py b/PyTorch/Detection/SSD/ssd/model.py index 3da96f486..18a269d83 100644 --- a/PyTorch/Detection/SSD/ssd/model.py +++ b/PyTorch/Detection/SSD/ssd/model.py @@ -18,22 +18,22 @@ class ResNet(nn.Module): - def __init__(self, backbone='resnet50', backbone_path=None): + def __init__(self, backbone='resnet50', backbone_path=None, weights="IMAGENET1K_V1"): super().__init__() if backbone == 'resnet18': - backbone = resnet18(pretrained=not backbone_path) + backbone = resnet18(weights=None if backbone_path else weights) self.out_channels = [256, 512, 512, 256, 256, 128] elif backbone == 'resnet34': - backbone = resnet34(pretrained=not backbone_path) + backbone = resnet34(weights=None if backbone_path else weights) self.out_channels = [256, 512, 512, 256, 256, 256] elif backbone == 'resnet50': - backbone = resnet50(pretrained=not backbone_path) + backbone = resnet50(weights=None if backbone_path else weights) self.out_channels = [1024, 512, 512, 256, 256, 256] elif backbone == 'resnet101': - backbone = resnet101(pretrained=not backbone_path) + backbone = resnet101(weights=None if backbone_path else weights) self.out_channels = [1024, 512, 512, 256, 256, 256] else: # backbone == 'resnet152': - backbone = resnet152(pretrained=not backbone_path) + backbone = resnet152(weights=None if backbone_path else weights) self.out_channels = [1024, 512, 512, 256, 256, 256] if backbone_path: backbone.load_state_dict(torch.load(backbone_path)) @@ -108,7 +108,7 @@ def _init_weights(self): def bbox_view(self, src, loc, conf): ret = [] for s, l, c in zip(src, loc, conf): - ret.append((l(s).view(s.size(0), 4, -1), c(s).view(s.size(0), self.label_num, -1))) + ret.append((l(s).reshape(s.size(0), 4, -1), c(s).reshape(s.size(0), self.label_num, -1))) locs, confs = list(zip(*ret)) locs, confs = torch.cat(locs, 2).contiguous(), torch.cat(confs, 2).contiguous() diff --git a/PyTorch/Detection/SSD/ssd/train.py b/PyTorch/Detection/SSD/ssd/train.py index 011f8210c..fa258f5a5 100644 --- a/PyTorch/Detection/SSD/ssd/train.py +++ b/PyTorch/Detection/SSD/ssd/train.py @@ -44,6 +44,8 @@ def train_loop(model, loss_func, scaler, epoch, optim, train_dataloader, val_dat label = label.view(N, M) with torch.cuda.amp.autocast(enabled=args.amp): + if args.data_layout == 'channels_last': + img = img.to(memory_format=torch.channels_last) ploc, plabel = model(img) ploc, plabel = ploc.float(), plabel.float() @@ -101,6 +103,8 @@ def benchmark_train_loop(model, loss_func, scaler, epoch, optim, train_dataloade label = label.view(N, M) with torch.cuda.amp.autocast(enabled=args.amp): + if args.data_layout == 'channels_last': + img = img.to(memory_format=torch.channels_last) ploc, plabel = model(img) ploc, plabel = ploc.float(), plabel.float() diff --git a/PyTorch/Detection/SSD/ssd/utils.py b/PyTorch/Detection/SSD/ssd/utils.py index ab88bff88..27c2dd1c2 100644 --- a/PyTorch/Detection/SSD/ssd/utils.py +++ b/PyTorch/Detection/SSD/ssd/utils.py @@ -217,7 +217,7 @@ def decode_single(self, bboxes_in, scores_in, criteria, max_output, max_num=200) _, max_ids = scores_out.sort(dim=0) - max_ids = max_ids[-max_output:] + max_ids = max_ids[-max_output:].to("cpu") return bboxes_out[max_ids, :], labels_out[max_ids], scores_out[max_ids] diff --git a/PyTorch/DrugDiscovery/MoFlow/Dockerfile b/PyTorch/DrugDiscovery/MoFlow/Dockerfile new file mode 100644 index 000000000..a95eef054 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/Dockerfile @@ -0,0 +1,29 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.11-py3 +FROM ${FROM_IMAGE_NAME} + +WORKDIR /workspace/ + +RUN python3 -m pip install --upgrade pip +RUN python3 -m pip install git+https://github.com/NVIDIA/dllogger@v1.0.0#egg=dllogger + +RUN python3 -m pip install rdkit-pypi + +ARG WORKSPACE=/workspace/moflow_pyt +WORKDIR ${WORKSPACE} +ADD . ${WORKSPACE} +RUN python3 -m pip install . diff --git a/PyTorch/DrugDiscovery/MoFlow/LICENSE b/PyTorch/DrugDiscovery/MoFlow/LICENSE new file mode 100644 index 000000000..86538fa63 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/LICENSE @@ -0,0 +1,202 @@ +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 NVIDIA Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/PyTorch/DrugDiscovery/MoFlow/NOTICE b/PyTorch/DrugDiscovery/MoFlow/NOTICE new file mode 100644 index 000000000..f4561f45c --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/NOTICE @@ -0,0 +1,3 @@ +MoFlow PyTorch + +This repository includes software from https://github.com/calvin-zcx/moflow licensed under the MIT License. diff --git a/PyTorch/DrugDiscovery/MoFlow/README.md b/PyTorch/DrugDiscovery/MoFlow/README.md new file mode 100644 index 000000000..94e5072f8 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/README.md @@ -0,0 +1,580 @@ +# MoFlow For PyTorch + +This repository provides a script and recipe to train the MoFlow model to achieve state-of-the-art accuracy. The content of this repository is tested and maintained by NVIDIA. + +## Table Of Contents + +- [Model overview](#model-overview) + * [Model architecture](#model-architecture) + * [Default configuration](#default-configuration) + * [Feature support matrix](#feature-support-matrix) + * [Features](#features) + * [Mixed precision training](#mixed-precision-training) + * [Enabling mixed precision](#enabling-mixed-precision) + * [Enabling TF32](#enabling-tf32) + * [Glossary](#glossary) +- [Setup](#setup) + * [Requirements](#requirements) +- [Quick Start Guide](#quick-start-guide) +- [Advanced](#advanced) + * [Scripts and sample code](#scripts-and-sample-code) + * [Parameters](#parameters) + * [Command-line options](#command-line-options) + * [Getting the data](#getting-the-data) + * [Dataset guidelines](#dataset-guidelines) + * [Multi-dataset](#multi-dataset) + * [Training process](#training-process) + * [Inference process](#inference-process) +- [Performance](#performance) + * [Benchmarking](#benchmarking) + * [Training performance benchmark](#training-performance-benchmark) + * [Inference performance benchmark](#inference-performance-benchmark) + * [Results](#results) + * [Training accuracy results](#training-accuracy-results) + * [Training accuracy: NVIDIA DGX A100 (8x A100 80GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-80gb) + * [Training stability test](#training-stability-test) + * [Training performance results](#training-performance-results) + * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-dgx-a100-8x-a100-80gb) + * [Inference performance results](#inference-performance-results) + * [Inference performance: NVIDIA DGX A100 (1x A100 80GB)](#inference-performance-nvidia-dgx-a100-1x-a100-80gb) +- [Release notes](#release-notes) + * [Changelog](#changelog) + * [Known issues](#known-issues) + + + +## Model overview + +MoFlow is a model for molecule generation that leverages Normalizing Flows. +Normalizing Flows is a class of generative neural networks that directly models the probability density of the data. They consist of a sequence of invertible transformations that convert the input data that follow some hard-to-model distribution into a latent code that follows a normal distribution which can then be easily used for sampling. + +MoFlow was first introduced by Chengxi Zang et al. in their paper titled "MoFlow: An Invertible Flow Model for Generating Molecular Graphs" ([link](https://arxiv.org/pdf/2006.10137.pdf)). + +The model enables you to generate novel molecules that have similar properties to your training data. +In the case of [ZINC dataset](https://zinc.docking.org/), which is used in this example, it allows you to navigate the chemical space of drug-like molecules and facilitate de-novo drug design. +The differences between this version and the [original implementation](https://github.com/calvin-zcx/moflow) accompanying the paper are as follows: +* Loss calculation was separated from the neural network +* ActNorm layers were refactored and their initialization was moved outside of the forward pass +* Numerical stability of the training was improved by introducing gradient clipping +* Numerically-stable formulas for 1/sigmoid(x) and log(sigmoid(x)) were used in AffineCoupling and GraphAffineCoupling layers +* Network and data configurations were untangled to allow for more flexibility +* Linear transformations for node features were implemented using native Linear layers instead of custom GraphLinear layers +* Rescaled adjacency matrix was removed as it did not provide any benefit for the training +* Data pre-processing and loading were refactored +* Support for data-parallel multi-GPU training was added +* Option to capture CUDA graphs was added +* Execution of bond and atom models in was put in two parallel CUDA streams +* Option to compile model to TorchScript format was added +* Support for Automatic Mixed Precision training and inference was added +* FusedAdam optimizer from [Apex](https://github.com/NVIDIA/apex) was used instead of Adam +* Training parameters were tuned to achieve better generation quality + +This model is trained with mixed precision using Tensor Cores on the NVIDIA Ampere GPU architectures. Therefore, researchers can get results up to 1.43x faster than training with full precision while experiencing the benefits of mixed precision training. This model is tested against each NGC monthly container release to ensure consistent accuracy and performance over time. + +### Model architecture +![MoFlow architecture](img/moflow.png) + +[Chengxi Zang and Fei Wang. 2020. MoFlow: An Invertible Flow Model for Generating Molecular Graphs. In Proceedings of the 26th ACM SIGKDD](https://arxiv.org/pdf/2006.10137.pdf) + + +The MoFlow model consists of two parts. +The first part, Glow, processes edges to convert an adjacency matrix into a latent vector Z_B. +The second part, Graph Conditional Flow, processes nodes in the context of edges to produce conditional latent vector Z_{A|B}. +Each part is a normalizing flow—a chain of invertible transformations with learnable parameters, which provide the ability to learn the distribution of the data. + +### Default configuration +The MoFlow model is built out of Normalizing Flows. It consists of two parts: Glow for processing edges and Graph Conditional Flow for processing nodes in the context of edges. + + +The following features were implemented in this model: +* Data-parallel multi-GPU training (DDP) +* Mixed precision training (autocast, gradient scaling) +* Just-in-time compilation +* Resumable training +* CUDA graphs capture + +The following performance optimizations were implemented in this model: +- A series of matrix manipulations in the GraphConv layer was replaced with a single torch.einsum +- Tensors are created on the device with the desired dtype whenever possible +- Channels-last memory format was used for Glow +- Stream concurrency was introduced to allow for executing Glow and Graph Conditional Flow at the same time. The concurrency happens in both forward and backward passes, and it hides the runtime of the smaller sub-model. Performance improvement is the most prominent for small batch sizes. +- Number of nodes in the graph is now independent of the maximum number of atoms in the dataset. This provides more flexibility and allows the use of shapes divisible by eight for better Tensor Cores usage. +- FusedAdam optimizer is used instead of native Adam. +- Normalization of the adjacency matrix was removed, as it did not benefit the training and required additional computation. + + +### Feature support matrix + +This model supports the following features:: + +| Feature | MoFlow +|-----------------------|-------------------------- +|Automatic mixed precision (AMP) | Yes +|Distributed data parallel (DDP) | Yes +|CUDA Graphs | Yes + + + + + +#### Features +**Distributed data parallel (DDP)** + +[DistributedDataParallel (DDP)](https://pytorch.org/docs/stable/generated/torch.nn.parallel.DistributedDataParallel.html#torch.nn.parallel.DistributedDataParallel) implements data parallelism at the module level that can run across multiple GPUs or machines. + +**Automatic Mixed Precision (AMP)** + +This implementation uses the native PyTorch AMP implementation of mixed precision training. It allows us to use FP16 training with FP32 master weights by modifying just a few lines of code. A detailed explanation of mixed precision can be found in the next section. + +**CUDA Graphs** + +This feature allows launching multiple GPU operations through a single CPU operation. The result is a vast reduction in CPU overhead. The benefits are particularly pronounced when training with relatively small batch sizes. The CUDA Graphs feature has been available through a [native PyTorch API](https://pytorch.org/docs/master/notes/cuda.html#cuda-graphs) starting from PyTorch v1.10. + + +### Mixed precision training + +Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in NVIDIA Volta, and following with both the NVIDIA Turing and NVIDIA Ampere Architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures. Using [mixed precision training](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) previously required two steps: +1. Porting the model to use the FP16 data type where appropriate. +2. Adding loss scaling to preserve small gradient values. + +AMP enables mixed precision training on NVIDIA Volta, NVIDIA Turing, and NVIDIA Ampere GPU architectures automatically. The PyTorch framework code makes all necessary model changes internally. + +For information about: +- How to train using mixed precision, refer to the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) documentation. +- Techniques used for mixed precision training, refer to the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. +- APEX tools for mixed precision training, refer to the [NVIDIA Apex: Tools for Easy Mixed-Precision Training in PyTorch](https://devblogs.nvidia.com/apex-pytorch-easy-mixed-precision-training/). + + +#### Enabling mixed precision + +Mixed precision is enabled in PyTorch by using the native [Automatic Mixed Precision package](https://pytorch.org/docs/stable/amp.html), which casts variables to half-precision upon retrieval while storing variables in single-precision format. Furthermore, to preserve small gradient magnitudes in backpropagation, a [loss scaling](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html#lossscaling) step must be included when applying gradients. In PyTorch, loss scaling can be applied automatically using a `GradScaler`. +Automatic Mixed Precision makes all the adjustments internally in PyTorch, providing two benefits over manual operations. First, programmers do not need to modify network model code, reducing development and maintenance efforts. Second, using AMP maintains forward and backward compatibility with all the APIs for defining and running PyTorch models. + +To enable mixed precision, you can simply use the `--amp` flag when running the training or inference scripts. + + + +#### Enabling TF32 + +TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math, also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on NVIDIA Volta GPUs. + +TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require a high dynamic range for weights or activations. + +For more information, refer to the [TensorFloat-32 in the A100 GPU Accelerates AI Training, HPC up to 20x](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) blog post. + +TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by default. + + + +### Glossary +**Normalizing flow** - a class of generative neural networks that directly models the probability density of the data. + +**Molecular graph** - representation of a molecule, in which nodes correspond to atoms and edges correspond to chemical bonds + +**SMILES format** - a format that allows representing a molecule with a string of characters +## Setup + +The following section lists the requirements that you need to meet to start training the MoFlow model. + +### Requirements + +This repository contains a Dockerfile that extends the PyTorch 22.11 NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: +- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) +- PyTorch 22.11+ NGC container +- Supported GPUs: + - [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) + - [NVIDIA Turing architecture](https://www.nvidia.com/en-us/design-visualization/technologies/turing-architecture/) + - [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) + +For more information about how to get started with NGC containers, refer to the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: +- [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) +- [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) +- Running [framework name - link to topic] + +For those unable to use the [framework name] NGC container, to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). + +## Quick Start Guide + +To train your model using mixed or TF32 precision with Tensor Cores or using FP32, perform the following steps using the default parameters of the MoFlow model on the ZINC 250k dataset. For the specifics concerning training and inference, refer to the [Advanced](#advanced) section. + +1. Clone the repository. +``` +git clone [https://github.com/NVIDIA/DeepLearningExamples](https://github.com/NVIDIA/DeepLearningExamples) +cd [DeepLearningExamples](https://github.com/NVIDIA/DeepLearningExamples)/PyTorch/DrugDiscovery/MoFlow +``` + +2. Build the MoFlow PyTorch NGC container. +``` +docker build . -t moflow_pyt +``` + +3. Start an interactive session in the NGC container to run training/inference. +Run the following command to launch the Docker container. + +``` +docker run --rm -it --shm-size=8gb --gpus all -v :/results moflow_pyt +``` + +If you want to reuse the dataset between runs, (recommended), use -v :/data to mount your directory inside the container: +``` +docker run --rm -it --shm-size=8gb --gpus all -v :/results -v :/data moflow_pyt +``` +The contents of /data will be downloaded in the following step. + + + +4. Download and preprocess the dataset. +``` +bash scripts/prepare_datasets.sh +``` + +5. Start training and evaluation. +``` +bash scripts/train.sh +``` + +6. Start inference. + +You can train the model yourself (see the prevoius step) or download the pretrained weights from NGC: +``` +wget 'https://api.ngc.nvidia.com/v2/models/nvidia/dle/moflow__pyt_ckpt/versions/22.11.0_amp/files/model_snapshot_epoch_300' -O /results/model_snapshot_epoch_300 +``` +Then you can run the inference: + +``` +bash scripts/predict.sh +``` + +Now that you have your model trained and evaluated, you can choose to compare your training results with our [Training accuracy results](#training-accuracy-results). You can also choose to benchmark your performance to [Training performance benchmark](#training-performance-results), or [Inference performance benchmark](#inference-performance-results). Following the steps in these sections will ensure that you achieve the same accuracy and performance results as stated in the [Results](#results) section. +## Advanced + +The following sections provide greater details of the dataset, running training and inference, and the training results. + +### Scripts and sample code +In the root directory, the most important files are: +- Dockerfile - definition of the Docker image with all dependencies needed to run MoFlow +- setup.py - script that allows installing MoFlow with pip. Note that it does not include dependencies. + +The `moflow` directory contains the definition of the network and tools needed for using it +- `config.py` - configuration of the dataset and network +- `data` - directory with tools needed to process and load the data +- `model` - directory with the definition of the MoFlow’s building blocks and helper functions +- `runtime` - directory that contains code for running experiments, multi-GPU training, and logging. The most important files in this directory are `train.py` and `generate.py`, which allow running training or inference, respectively. +- `utils.py`- various helper functions + +The `scripts` directory contains scripts for running the most typical workflows inside the docker container: +- `benchmark_inference.sh` and `benchmark_training.sh` for measuring the performance of inference or training, respectively +- `data_preprocess.py` for dataset preparation +- `prepare_datasets.sh` for downloading and preprocessing the data (note, that it launches `data_preprocess.py`) +- `train.sh` for launching training +- `predict.sh` for sampling random molecules from the trained model +### Parameters + +The complete list of parameters accepted by the runtime scripts (`moflow/runtime/train.py` and `moflow/runtime/generate.py`) consists of: +* --data_dir - Location for the dataset. +* --config_name - The config to choose. This parameter allows one to switch between different datasets and their dedicated configurations of the neural network. By default, a pre-defined “zinc250k” config is used. +* --results_dir - Directory where checkpoints are stored. +* --predictions_path - Path to store generated molecules. If an empty string is provided, predictions will not be saved (useful for benchmarking and debugging). +* --log_path - Path for DLLogger log. This file will contain information about the speed and accuracy of the model during training and inference. Note that if the file already exists, new logs will be added at the end. +* --log_interval - Frequency for writing logs, expressed in steps. +* --warmup_steps - Number of warmup steps. This value is used for benchmarking and for CUDA graph capture. +* --steps - Number of steps used for training/inference. This parameter allows finishing training earlier than the specified number of epochs. If used with inference, it allows generating more molecules (by default only a single batch of molecules is generated). +* --save_epochs - Frequency for saving checkpoints, expressed in epochs. If -1 is provided, checkpoints will not be saved. +* --eval_epochs - Evaluation frequency, expressed in epochs. If -1 is provided, an evaluation will not be performed. +* --learning_rate - Base learning rate. +* --beta1 - beta1 parameter for the Adam optimizer. +* --beta2 - beta2 parameter for the Adam optimizer. +* --clip - Gradient clipping norm. +* --epochs - Number of training epochs. Note that you can finish training mid-epoch by using “--steps” flag. +* --batch_size - Batch size per GPU. +* --num_workers - Number of workers in the data loader. +* --seed - Random seed used to initialize the distributed loaders. +* --local_rank - rank of the GPU, used to launch distributed training. This argument is specified automatically by `torchrun` and does not have to be provided by the user. +* --temperature - Temperature used for sampling. +* --val_batch_size - Number of molecules to generate during the validation step. +* --allow_untrained - Allow sampling molecules from an untrained network. Useful for performance benchmarking or debugging purposes. +* --correct_validity - Apply validity correction after the generation of the molecules. +* --amp - Use Automatic Mixed Precision +* --cuda_graph - Capture GPU kernels with CUDA graphs. This option allows to speed up training. +* --jit - Compile the model with `torch.jit.script`. Can be used to speed up training or inference. +* --verbosity - Verbosity level. Specify the following values: 0, 1, 2, 3, where 0 means minimal verbosity (errors only) and 3 - maximal (debugging). + + +### Command-line options + +To view the full list of available options and their descriptions, use the `-h` or `--help` command-line option, for example: +`python moflow/runtime/train.py --help` + +The following example output is printed when running the model: +``` +usage: train.py [-h] [--data_dir DATA_DIR] [--config_name {zinc250k}] [--results_dir RESULTS_DIR] [--predictions_path PREDICTIONS_PATH] [--log_path LOG_PATH] [--log_interval LOG_INTERVAL] + [--warmup_steps WARMUP_STEPS] [--steps STEPS] [--save_epochs SAVE_EPOCHS] [--eval_epochs EVAL_EPOCHS] [--learning_rate LEARNING_RATE] [--beta1 BETA1] [--beta2 BETA2] [--clip CLIP] + [--epochs EPOCHS] [--batch_size BATCH_SIZE] [--num_workers NUM_WORKERS] [--seed SEED] [--local_rank LOCAL_RANK] [--temperature TEMPERATURE] [--val_batch_size VAL_BATCH_SIZE] + [--allow_untrained] [--correct_validity] [--amp] [--cuda_graph] [--jit] [--verbosity {0,1,2,3}] + +optional arguments: + -h, --help show this help message and exit + --data_dir DATA_DIR Location for the dataset. + --config_name {zinc250k} + The config to choose. This parameter allows one to switch between different datasets and their dedicated configurations of the neural network. By default, a pre-defined + "zinc250k" config is used. + --results_dir RESULTS_DIR + Directory where checkpoints are stored. + --predictions_path PREDICTIONS_PATH + Path to store generated molecules. If an empty string is provided, predictions will not be saved (useful for benchmarking and debugging). + --log_path LOG_PATH Path for DLLogger log. This file will contain information about the speed and accuracy of the model during training and inference. Note that if the file already exists, new logs + will be added at the end. + --log_interval LOG_INTERVAL + Frequency for writing logs, expressed in steps. + --warmup_steps WARMUP_STEPS + Number of warmup steps. This value is used for benchmarking and for CUDA graph capture. + --steps STEPS Number of steps used for training/inference. This parameter allows finishing training earlier than the specified number of epochs. If used with inference, it allows generating + more molecules (by default only a single batch of molecules is generated). + --save_epochs SAVE_EPOCHS + Frequency for saving checkpoints, expressed in epochs. If -1 is provided, checkpoints will not be saved. + --eval_epochs EVAL_EPOCHS + Evaluation frequency, expressed in epochs. If -1 is provided, an evaluation will not be performed. + --learning_rate LEARNING_RATE + Base learning rate. + --beta1 BETA1 beta1 parameter for the optimizer. + --beta2 BETA2 beta2 parameter for the optimizer. + --clip CLIP Gradient clipping norm. + --epochs EPOCHS Number of training epochs. Note that you can finish training mid-epoch by using "--steps" flag. + --batch_size BATCH_SIZE + Batch size per GPU. + --num_workers NUM_WORKERS + Number of workers in the data loader. + --seed SEED Random seed used to initialize the distributed loaders. + --local_rank LOCAL_RANK + rank of the GPU, used to launch distributed training. This argument is specified automatically by `torchrun` and does not have to be provided by the user. + --temperature TEMPERATURE + Temperature used for sampling. + --val_batch_size VAL_BATCH_SIZE + Number of molecules to generate during validation step. + --allow_untrained Allow sampling molecules from an untrained network. Useful for performance benchmarking or debugging purposes. + --correct_validity Apply validity correction after the generation of the molecules. + --amp Use Automatic Mixed Precision. + --cuda_graph Capture GPU kernels with CUDA graphs. This option allows to speed up training. + --jit Compile the model with `torch.jit.script`. Can be used to speed up training or inference. + --verbosity {0,1,2,3} + Verbosity level. Specify the following values: 0, 1, 2, 3, where 0 means minimal verbosity (errors only) and 3 - maximal (debugging). + +``` +### Getting the data + +The MoFlow model was trained on the ZINC 250k dataset. The original data split was used, with 224569 molecules in the training set and 24887 molecules in the test set. + +This repository contains the `prepare_datasets.sh` script that will automatically download and process the dataset. By default, data will be downloaded to the `/data/` directory. + +#### Dataset guidelines +The dataset preparation is implemented in the `scripts/data_preprocess.py` script, and the parameters for the dataset are defined in the `moflow/config.py` file. The config includes information about data location, the structure of the CSV file, types and numbers of atoms in the molecules, and the number of nodes in the output graphs. + +Initially, the data is stored in a CSV file that contains the molecules in SMILES format, together with their properties (optional). The data is loaded using the `pandas` library, and the SMILES strings are converted to molecules with RDKit. + +Then, the molecules are converted into graphs with features assigned to nodes and edges. The first step is the standardization of molecular structures - each molecule is converted into canonical SMILES and loaded back, and kekulized. Then, two numpy arrays are constructed. The first array is a vector corresponding to graph nodes and contains atomic numbers for all atoms in the molecule. The second array is a 2D square matrix corresponding to graph edges and contains codes for atomic bond orders - 0 if two atoms are not connected, 1 for a single bond, 2 for a double bond, and 3 for a triple bond. + +Both arrays are padded to some predefined size larger than the maximum number of atoms in the molecules in the dataset. For ZINC 250k, the maximum number of atoms is 38, and the output size of the numpy arrays is set to 40 for the nodes array and 40x40 for the edges array. + +This representation of the data is dumped on the disk using the numpy `savez` function. + +During training, the numpy arrays are loaded, and one-hot-encoding is used to represent atomic numbers (node features) and bond orders (edge features). This representation is then used for training the neural network. + +### Training process + +The training script is located in `moflow/runtime/train.py` and it accepts the parameters listed above. + +To make the usage of the model easier, there is also `scripts/train.sh` script that runs training with the default configuration and the evaluation using the trained checkpoint at the end. This script can be run without any arguments - then it launches training on a single GPU and performance optimizations enabled - automatic mixed precision (AMP) and CUDA graph capture. + +``` +./scripts/train.sh +``` + +It is also possible to pass the number of GPUs and precision (“amp” or “full”) that should be used for training. For example, to launch training with eight GPUs and AMP, run: +``` +./scripts/train.sh 8 +``` +and to launch four GPU training with full precision, run: +``` +./scripts/train.sh 4 full +``` +These two arguments can also be followed by extra flags that will be passed to training and evaluation commands. For example, to train on eight GPUs with AMP, batch size of 2048 per GPU and save logs in `/results/dll.json`, run: +``` +./scripts/train.sh 8 amp --batch_size 2048 --log_path /results/dll.json +``` + +Alternatively, you can launch training with `moflow/runtime/train.py`. To run the model with multiple GPUs, run: + +``` +torchrun --nproc_per_node=<# GPUs> moflow/runtime/train.py +``` +To enable mixed precision training, add `--amp`. You can also optimize the performance further by adding `--cuda_graph` or `--jit` flags to enable CUDA graph capture or just-in-time compilation, respectively. + +#### Logs +By default, logs are printed to the screen and not saved on disk. If you want to store the logs, pass `--log_path` flag to `scripts/train.sh` or `moflow/runtime/train.py`. + +#### Checkpoints +By default, the training script saves checkpoints inside `/results` every five epochs. The location of the checkpoints directory can be modified with `--results_dir` flag and saving interval with `--save_epochs` flag (pass -1 if you do not want to save checkpoints). Up to five most recent checkpoints are kept while the older ones are removed. + +#### Evaluation +The following metrics are used to evaluate the model: + +- Validity - the percentage of predictions corresponding to the correct molecular graph. +- Uniqueness - the percentage of valid molecules that is unique. +- Novelty - the percentage of valid and unique molecules not present in the training set. +- N.U.V - the percentage of valid, unique, and novel molecules. + +During training, a single batch of molecules is generated every couple of epochs to assess two metrics: validity and uniqueness, as they are quick to calculate and track the training progress. + +By default, the validation batch size is set to 100 molecules per GPU, and evaluation happens every five epochs. This can be changed with `--val_batch_size` and `--eval_epochs` flags, respectively. To disable evaluation, pass `--eval_epochs -1`. + +If you use `scripts/train.sh`, there is also a final evaluation of the model done on 100 batches of molecules. This larger sample is evaluated with all metrics described above, and we use N.U.V as the main metric. + +Alternatively, you can trigger evaluation manually by running `moflow/runtime/evaluate.py` script. Make sure that you pass the same value for `--results_dir` for both training and evaluation scripts. + +### Inference process + +Inference can be run by launching the `moflow/runtime/generate.py` or `scripts/predict.sh` script. The first one provides more flexibility and accepts the arguments listed above. The second script allows you to easily run the default configuration with performance optimization (`--jit` flag) and molecule validity correction (`--correct_validity`). To generate a single batch of molecules with AMP and batch size of 512, run: +``` +./scripts/predict.sh +``` +You can also provide batch size and precision to use for predictions. For example, to generate 1000 molecules with full precision, run: + +``` +./scripts/predict.sh 1000 full +``` + +The script also allows you to pass extra flags to the generation. For example, to generate 10 batches of 1000 each and save predictions inside /results/predictions.smi, run: +``` +./scripts/predict.sh 1000 amp --steps 10 --predictions_path /results/predictions.smi +``` + + + +## Performance +The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to [NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). + +### Benchmarking + +The following section shows how to run benchmarks measuring the model performance in training and inference modes. + +#### Training performance benchmark + +To benchmark the training performance on a specific number of GPUs, batch size and precision, run: + +``` +bash scripts/benchmark_training.sh <# GPUs> +``` +Eg. running +``` +./scripts/benchmark_training.sh 8 2048 amp +``` +will measure performance for eight GPUs, batch size of 2048 per GPU and mixed precision and running: +``` +./scripts/benchmark_training.sh 1 1024 full +``` +will measure performance for single GPU, batch size of 1024 and full precision. +#### Inference performance benchmark +To benchmark the inference performance on a specific batch size and precision, run: + +``` +bash scripts/benchmark_inference.sh +``` + +Eg. running +``` +./scripts/benchmark_inference.sh 2048 amp +``` +will measure performance for a batch size of 2048 and mixed precision and running: +``` +./scripts/benchmark_inference.sh 1024 full +``` +will measure performance for a batch size of 1024 and full precision. + +### Results + +The following sections provide details on how we achieved our performance and accuracy in training and inference. + +#### Training accuracy results + + +##### Training accuracy: NVIDIA A100 (8x A100 80GB) + +Our results were obtained by running the `scripts/train.sh` training script in the PyTorch 22.11 NGC container on NVIDIA A100 (8x A100 80GB) GPUs. The values presented below were averaged over 20 experiments. + +| GPUs | Batch size / GPU | NUV - TF32 | NUV - mixed precision | Time to train - TF32 | Time to train - mixed precision | Time to train speedup (TF32 to mixed precision) +|---------|------------------|-----------------|----------------------------|-------------------------|----------------------------------|-------------- +| 1 | 512 | 89.63 % | 87.83 % | 5h8min | 4h0min | 1.28x +| 8 | 512 | 87.03 % | 87.90 % | 48min | 40min | 1.20x + + +##### Training stability test + + +The MoFlow model was trained for 300 epochs starting from 20 different initial random seeds. Every five training epochs, the model was evaluated by generating a small sample of molecules (100 molecules per GPU), and validity and uniqueness were calculated. The training was performed in the PyTorch 22.11 Docker container on NVIDIA DGX A100 with 8x A100 80GB GPUs with AMP and CUDA graph capture enabled. The following table summarizes the results of the stability test. + +The following table displays the validity and uniqueness scores after every 50 epochs for different initial random seeds. + +|epoch|validity mean|validity std|validity min|validity max|validity median|uniqueness mean|uniqueness std|uniqueness min|uniqueness max|uniqueness median| +|-----|-------------|------------|------------|------------|---------------|---------------|--------------|--------------|--------------|-----------------| +|50 |68.22 |5.25 |57.38 |74.75 |69.50 |93.64 |8.22 |62.56 |99.82 |95.30 | +|100 |76.91 |4.23 |69.50 |84.38 |77.50 |99.39 |0.92 |96.31 |100.00 |99.83 | +|150 |80.48 |3.80 |73.88 |88.25 |81.75 |99.58 |0.78 |96.64 |100.00 |99.85 | +|200 |83.87 |3.98 |77.00 |90.62 |84.44 |99.76 |0.38 |98.81 |100.00 |100.00 | +|250 |86.08 |4.46 |77.12 |93.12 |86.56 |99.87 |0.21 |99.27 |100.00 |100.00 | +|300 |87.29 |3.70 |77.75 |93.38 |87.69 |99.82 |0.30 |98.70 |100.00 |99.93 | + + + +#### Training performance results + + +##### Training performance: NVIDIA A100 (8x A100 80GB) + +Our results were obtained by running the `scripts/benchmark_training.sh` training script in the PyTorch 22.11 NGC container on NVIDIA A100 (8x A100 80GB) GPUs. Performance numbers (in molecules per second) were averaged over 190 iterations after 10 warm-up steps. + +|GPUs|Batch size / GPU|Throughput - TF32|Throughput - mixed precision|Throughput speedup (TF32 - mixed precision)|Weak scaling - TF32|Weak scaling - mixed precision| +|----|----------------|-----------------|----------------------------|-------------------------------------------|-------------------|------------------------------| +|1 |512 |3499.35 |4524.15 |1.29 | | | +|1 |1024 |3883.49 |5392.78 |1.39 | | | +|1 |2048 |4291.29 |6118.46 |1.43 | | | +|8 |512 |24108.04 |29293.41 |1.22 |6.89 |6.47 | +|8 |1024 |28104.62 |37365.05 |1.33 |7.24 |6.93 | +|8 |2048 |30927.04 |42078.31 |1.36 |7.21 |6.88 | + + + +To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + + +#### Inference performance results + +##### Inference performance: NVIDIA A100 (1x A100 80GB) + +Our results were obtained by running the `scripts/benchmark_inference.sh` inferencing benchmarking script in the PyTorch 22.11 NGC container on the NVIDIA A100 (1x A100 80GB) GPU. + +FP16 +|Batch size|Throughput Avg|Latency Avg|Latency 90%|Latency 95%|Latency 99%| +|----------|--------------|-----------|-----------|-----------|-----------| +|512 |12524.49 |41 |41 |41 |41 | +|1024 |13871.60 |74 |74 |74 |74 | +|2048 |14386.44 |142 |144 |144 |144 | + +TF32 +|Batch size|Throughput Avg|Latency Avg|Latency 90%|Latency 95%|Latency 99%| +|----------|--------------|-----------|-----------|-----------|-----------| +|512 |9696.35 |53 |53 |53 |53 | +|1024 |10242.98 |100 |100 |100 |100 | +|2048 |11174.75 |183 |187 |187 |187 | + + +To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +## Release notes + +### Changelog +January 2023 +- Initial release + +### Known issues + +There is a known issue with the selection of sampling temperature. For some runs, the default value (0.3) might be sub-optimal, and better prediction quality can be achieved when lowering or increasing the value of this parameter. To tune the value of this parameter, run `moflow/runtime/evaluate.py` script passing different values for the `--temperature` flag. diff --git a/PyTorch/DrugDiscovery/MoFlow/img/moflow.png b/PyTorch/DrugDiscovery/MoFlow/img/moflow.png new file mode 100644 index 000000000..e806e1451 Binary files /dev/null and b/PyTorch/DrugDiscovery/MoFlow/img/moflow.png differ diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/__init__.py b/PyTorch/DrugDiscovery/MoFlow/moflow/__init__.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/__init__.py rename to PyTorch/DrugDiscovery/MoFlow/moflow/__init__.py diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/config.py b/PyTorch/DrugDiscovery/MoFlow/moflow/config.py new file mode 100644 index 000000000..8bf4d07c4 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/config.py @@ -0,0 +1,142 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from dataclasses import asdict, dataclass, field +import json +from typing import Dict, List, Optional + +from rdkit import Chem + + +_VALID_IDX_FILE = 'valid_idx_{}.json' +_CSV_FILE = '{}.csv' +_DATASET_FILE = '{}_relgcn_kekulized_ggnp.npz' + +DUMMY_CODE = 0 +CODE_TO_BOND = dict(enumerate([ + 'DUMMY', + Chem.rdchem.BondType.SINGLE, + Chem.rdchem.BondType.DOUBLE, + Chem.rdchem.BondType.TRIPLE, +])) +BOND_TO_CODE = {v: k for k, v in CODE_TO_BOND.items()} +ATOM_VALENCY = {6: 4, 7: 3, 8: 2, 9: 1, 15: 3, 16: 2, 17: 1, 35: 1, 53: 1} + + +@dataclass +class DatasetConfig: + dataset_name: str + atomic_num_list: List[int] + max_num_atoms: int + labels: List[str] + smiles_col: str + code_to_atomic: Dict[int, int] = field(init=False) + atomic_to_code: Dict[int, int] = field(init=False) + valid_idx_file: str = field(init=False) + csv_file: str = field(init=False) + dataset_file: str = field(init=False) + + def __post_init__(self): + self.valid_idx_file = _VALID_IDX_FILE.format(self.dataset_name) + self.csv_file = _CSV_FILE.format(self.dataset_name) + self.dataset_file = _DATASET_FILE.format(self.dataset_name) + + self.code_to_atomic = dict(enumerate(sorted([DUMMY_CODE] + self.atomic_num_list))) + self.atomic_to_code = {v: k for k, v in self.code_to_atomic.items()} + + +@dataclass +class AtomFlowConfig: + n_flow: int + hidden_gnn: List[int] + hidden_lin: List[int] + n_block: int = 1 + mask_row_size_list: List[int] = field(default_factory=lambda: [1]) + mask_row_stride_list: List[int] = field(default_factory=lambda: [1]) + +@dataclass +class BondFlowConfig: + hidden_ch: List[int] + conv_lu: int + n_squeeze: int + n_block: int = 1 + n_flow: int = 10 + + +@dataclass +class ModelConfig: + atom_config: AtomFlowConfig + bond_config: BondFlowConfig + noise_scale: float = 0.6 + learn_dist: bool = True + +@dataclass +class Config: + dataset_config: DatasetConfig + model_config: ModelConfig + max_num_nodes: Optional[int] = None + num_node_features: Optional[int] = None + num_edge_features: int = len(CODE_TO_BOND) + z_dim: int = field(init=False) + + def __post_init__(self): + if self.max_num_nodes is None: + self.max_num_nodes = self.dataset_config.max_num_atoms + if self.num_node_features is None: + self.num_node_features = len(self.dataset_config.code_to_atomic) + bonds_dim = self.max_num_nodes * self.max_num_nodes * self.num_edge_features + atoms_dim = self.max_num_nodes * self.num_node_features + self.z_dim = bonds_dim + atoms_dim + + + def save(self, path): + self.path = path + with open(path, 'w') as f: + json.dump(asdict(self), f, indent=4, sort_keys=True) + + @classmethod + def load(cls, path): + with open(path, 'r') as f: + data = json.load(f) + return cls(**data) + + def __repr__(self) -> str: + return json.dumps(asdict(self), indent=4, separators=(',', ': ')) + + +ZINC250K_CONFIG = Config( + max_num_nodes=40, + dataset_config=DatasetConfig( + dataset_name='zinc250k', + atomic_num_list=[6, 7, 8, 9, 15, 16, 17, 35, 53], + max_num_atoms=38, + labels=['logP', 'qed', 'SAS'], + smiles_col='smiles', + ), + model_config=ModelConfig( + AtomFlowConfig( + n_flow=38, + hidden_gnn=[256], + hidden_lin=[512, 64], + ), + BondFlowConfig( + n_squeeze=20, + hidden_ch=[512, 512], + conv_lu=2 + ), + ) +) + +CONFIGS = {'zinc250k': ZINC250K_CONFIG} diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/__init__.py b/PyTorch/DrugDiscovery/MoFlow/moflow/data/__init__.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/__init__.py rename to PyTorch/DrugDiscovery/MoFlow/moflow/data/__init__.py diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/data/data_frame_parser.py b/PyTorch/DrugDiscovery/MoFlow/moflow/data/data_frame_parser.py new file mode 100644 index 000000000..ba76fc439 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/data/data_frame_parser.py @@ -0,0 +1,109 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +from logging import getLogger +import traceback +from typing import List + +import numpy as np +import pandas as pd +from rdkit import Chem +from tqdm import tqdm + +from moflow.data.encoding import MolEncoder, EncodingError +from moflow.data.data_loader import NumpyTupleDataset + + +class DataFrameParser: + """ + This DataFrameParser parses pandas dataframe containing SMILES and, optionally, some additional features. + + Args: + encoder (MolEncoder): encoder instance + labels (list): labels column that should be loaded + smiles_col (str): smiles column + """ + + def __init__(self, encoder: MolEncoder, + labels: List[str], + smiles_col: str = 'smiles'): + super(DataFrameParser, self).__init__() + self.labels = labels + self.smiles_col = smiles_col + self.logger = getLogger(__name__) + self.encoder = encoder + + def parse(self, df: pd.DataFrame) -> NumpyTupleDataset: + """Parse DataFrame using `encoder` and prepare a dataset instance + + Labels are extracted from `labels` columns and input features are + extracted from smiles information in `smiles` column. + """ + all_nodes = [] + all_edges = [] + + total_count = df.shape[0] + fail_count = 0 + success_count = 0 + for smiles in tqdm(df[self.smiles_col], total=df.shape[0]): + try: + mol = Chem.MolFromSmiles(smiles) + if mol is None: + fail_count += 1 + continue + # Note that smiles expression is not unique. + # we obtain canonical smiles + nodes, edges = self.encoder.encode_mol(mol) + + except EncodingError as e: + fail_count += 1 + continue + except Exception as e: + self.logger.warning('parse(), type: {}, {}' + .format(type(e).__name__, e.args)) + self.logger.info(traceback.format_exc()) + fail_count += 1 + continue + all_nodes.append(nodes) + all_edges.append(edges) + success_count += 1 + + result = [np.array(all_nodes), np.array(all_edges), *(df[label_col].values for label_col in self.labels)] + self.logger.info('Preprocess finished. FAIL {}, SUCCESS {}, TOTAL {}' + .format(fail_count, success_count, total_count)) + + dataset = NumpyTupleDataset(result) + return dataset diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/data/data_loader.py b/PyTorch/DrugDiscovery/MoFlow/moflow/data/data_loader.py new file mode 100644 index 000000000..28f9378ca --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/data/data_loader.py @@ -0,0 +1,110 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import os +import logging +from typing import Any, Callable, Iterable, Optional, Tuple + +import numpy as np +from torch.utils.data import Dataset + + +class NumpyTupleDataset(Dataset): + """Dataset of a tuple of datasets. + + It combines multiple datasets into one dataset. Each example is represented + by a tuple whose ``i``-th item corresponds to the i-th dataset. + And each ``i``-th dataset is expected to be an instance of numpy.ndarray. + + Args: + datasets: Underlying datasets. The ``i``-th one is used for the + ``i``-th item of each example. All datasets must have the same + length. + transform: An optional function applied to an item bofre returning + """ + + def __init__(self, datasets: Iterable[np.ndarray], transform: Optional[Callable] = None) -> None: + if not datasets: + raise ValueError('no datasets are given') + length = len(datasets[0]) + for i, dataset in enumerate(datasets): + if len(dataset) != length: + raise ValueError( + 'dataset of the index {} has a wrong length'.format(i)) + self._datasets = datasets + self._length = length + self.transform = transform + + def __len__(self) -> int: + return self._length + + def __getitem__(self, index: int) -> Tuple[Any]: + item = [dataset[index] for dataset in self._datasets] + + if self.transform: + item = self.transform(item) + return item + + def get_datasets(self) -> Tuple[np.ndarray]: + return self._datasets + + + def save(self, filepath: str) -> None: + """save the dataset to filepath in npz format + + Args: + filepath (str): filepath to save dataset. It is recommended to end + with '.npz' extension. + """ + np.savez(filepath, *self._datasets) + logging.info('Save {} done.'.format(filepath)) + + @classmethod + def load(cls, filepath: str, transform: Optional[Callable] = None): + logging.info('Loading file {}'.format(filepath)) + if not os.path.exists(filepath): + raise ValueError('Invalid filepath {} for dataset'.format(filepath)) + load_data = np.load(filepath) + result = [] + i = 0 + while True: + key = 'arr_{}'.format(i) + if key in load_data.keys(): + result.append(load_data[key]) + i += 1 + else: + break + return cls(result, transform) diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/data/encoding.py b/PyTorch/DrugDiscovery/MoFlow/moflow/data/encoding.py new file mode 100644 index 000000000..d3d71fde9 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/data/encoding.py @@ -0,0 +1,139 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +from typing import Tuple +import numpy as np +from rdkit import Chem + +from moflow.config import BOND_TO_CODE, DUMMY_CODE + + +class MolEncoder: + """Encodes atoms and adjecency matrix. + + Args: + out_size (int): It specifies the size of array returned by + `get_input_features`. + If the number of atoms in the molecule is less than this value, + the returned arrays is padded to have fixed size. + """ + + def __init__(self, out_size: int): + super(MolEncoder, self).__init__() + self.out_size = out_size + + def encode_mol(self, mol: Chem.Mol) -> Tuple[np.ndarray, np.ndarray]: + """get input features + + Args: + mol (Mol): + + Returns: + + """ + mol = self._standardize_mol(mol) + self._check_num_atoms(mol) + atom_array = self.construct_atomic_number_array(mol) + adj_array = self.construct_discrete_edge_matrix(mol) + return atom_array, adj_array + + def _standardize_mol(self, mol: Chem.Mol) -> Chem.Mol: + canonical_smiles = Chem.MolToSmiles(mol, isomericSmiles=False, + canonical=True) + mol = Chem.MolFromSmiles(canonical_smiles) + Chem.Kekulize(mol) + return mol + + def _check_num_atoms(self, mol: Chem.Mol) -> None: + """Check number of atoms in `mol` does not exceed `out_size`""" + num_atoms = mol.GetNumAtoms() + if num_atoms > self.out_size: + raise EncodingError(f'Number of atoms in mol {num_atoms} exceeds num_max_atoms {self.out_size}') + + + def construct_atomic_number_array(self, mol: Chem.Mol) -> np.ndarray: + """Returns atomic numbers of atoms consisting a molecule. + + Args: + mol (rdkit.Chem.Mol): Input molecule. + + Returns: + numpy.ndarray: an array consisting of atomic numbers + of atoms in the molecule. + """ + + atom_list = [a.GetAtomicNum() for a in mol.GetAtoms()] + n_atom = len(atom_list) + if self.out_size < n_atom: + raise EncodingError(f'out_size {self.out_size} is smaller than number of atoms in mol {n_atom}') + atom_array = np.full(self.out_size, DUMMY_CODE, dtype=np.uint8) + atom_array[:n_atom] = atom_list + return atom_array + + + def construct_discrete_edge_matrix(self, mol: Chem.Mol) -> np.ndarray: + """Returns the edge-type dependent adjacency matrix of the given molecule. + + Args: + mol (rdkit.Chem.Mol): Input molecule. + + Returns: + adj_array (numpy.ndarray): The adjacent matrix of the input molecule. + It is symmetrical 2-dimensional array with shape (out_size, out_size), + filled with integers representing bond types. It two atoms are not + conncted, DUMMY_CODE is used instead. + """ + if mol is None: + raise EncodingError('mol is None') + n_atom = mol.GetNumAtoms() + + if self.out_size < n_atom: + raise EncodingError(f'out_size {self.out_size} is smaller than number of atoms in mol {n_atom}') + + adjs = np.full((self.out_size, self.out_size), DUMMY_CODE, dtype=np.uint8) + + for bond in mol.GetBonds(): + bond_type = bond.GetBondType() + # we need to use code here - bond types are rdkit objects + code = BOND_TO_CODE[bond_type] + i = bond.GetBeginAtomIdx() + j = bond.GetEndAtomIdx() + adjs[[i, j], [j, i]] = code + return adjs + + +class EncodingError(Exception): + pass diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/data/transform.py b/PyTorch/DrugDiscovery/MoFlow/moflow/data/transform.py new file mode 100644 index 000000000..eaf3e9e43 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/data/transform.py @@ -0,0 +1,85 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import json +import logging +import numpy as np +import os +from typing import Dict, Tuple + +from moflow.config import CODE_TO_BOND, DUMMY_CODE, Config + + +def _onehot(data: np.ndarray, codes_dict: Dict[int, int], dtype=np.float32) -> np.ndarray: + shape = [len(codes_dict), *data.shape] + encoded = np.zeros(shape, dtype=dtype) + for obj_key, code in codes_dict.items(): + encoded[code, data == obj_key] = 1 + return encoded + + +def encode_nodes(atomic_nums: np.ndarray, config: Config) -> np.ndarray: + padded_data = np.full(config.max_num_nodes, DUMMY_CODE, dtype=np.uint8) + padded_data[:len(atomic_nums)] = atomic_nums + encoded = _onehot(padded_data, config.dataset_config.atomic_to_code).T + return encoded + + +def encode_edges(adj: np.ndarray, config: Config) -> np.ndarray: + padded_data = np.full((config.max_num_nodes, config.max_num_nodes), DUMMY_CODE, dtype=np.uint8) + n, m = adj.shape + assert n == m, 'adjecency matrix should be square' + padded_data[:n, :n] = adj + # we already store codes in the file - bond types are rdkit objects + encoded = _onehot(padded_data, {k:k for k in CODE_TO_BOND}) + return encoded + + +def transform_fn(data: Tuple[np.ndarray], config: Config) -> Tuple[np.ndarray]: + node, adj, *labels = data + node = encode_nodes(node, config) + adj = encode_edges(adj, config) + return (node, adj, *labels) + + +def get_val_ids(config: Config, data_dir: str): + file_path = os.path.join(data_dir, config.dataset_config.valid_idx_file) + logging.info('loading train/valid split information from: {}'.format(file_path)) + with open(file_path) as json_data: + data = json.load(json_data) + + val_ids = [int(idx)-1 for idx in data] + return val_ids diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/__init__.py b/PyTorch/DrugDiscovery/MoFlow/moflow/model/__init__.py similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/__init__.py rename to PyTorch/DrugDiscovery/MoFlow/moflow/model/__init__.py diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/model/basic.py b/PyTorch/DrugDiscovery/MoFlow/moflow/model/basic.py new file mode 100644 index 000000000..f6f0e32bf --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/model/basic.py @@ -0,0 +1,194 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import math +from typing import Tuple +import numpy as np +from scipy import linalg as la +import torch +from torch import nn +from torch.nn import functional as F + +from moflow.runtime.distributed_utils import get_world_size, reduce_tensor + + +class ActNorm(nn.Module): + def __init__(self, num_channels, num_dims, channels_dim=1): + super().__init__() + self.num_channels = num_channels + self.num_dims = num_dims + self.channels_dim = channels_dim + self.shape = [1] * num_dims + self.shape[channels_dim] = num_channels + self.loc = nn.Parameter(torch.zeros(*self.shape)) + self.scale = nn.Parameter(torch.ones(*self.shape)) + + self.register_buffer('initialized', torch.tensor(0, dtype=torch.uint8)) + self.register_buffer('num_elements', torch.tensor(0, dtype=torch.uint8)) + + @torch.jit.ignore + def initialize(self, input): + if self.initialized.item() == 1: + return + + dims = list(input.shape[1:]) + del dims[self.channels_dim -1] + + num_elems = math.prod(dims) + permutation = [self.channels_dim] + [i for i in range(self.num_dims) if i != self.channels_dim] + with torch.no_grad(): + + flatten = input.permute(*permutation).contiguous().view(self.num_channels, -1) + mean = flatten.mean(1).view(self.shape) + std = flatten.std(1).view(self.shape) + + num_gpus = get_world_size() + mean = reduce_tensor(mean, num_gpus) + std = reduce_tensor(std, num_gpus) + self.loc.data.copy_(-mean) + self.scale.data.copy_(1 / (std + 1e-6)) + self.initialized.fill_(1) + self.num_elements.fill_(num_elems) + + def forward(self, input): + log_abs = torch.log(torch.abs(self.scale)) + logdet = self.num_elements * torch.sum(log_abs) + return self.scale * (input + self.loc), logdet + + @torch.jit.export + def reverse(self, output): + return output / self.scale - self.loc + + +class InvConv2d(nn.Module): + def __init__(self, in_channel): + super().__init__() + + weight = torch.randn(in_channel, in_channel) + q, _ = torch.qr(weight) + weight = q.unsqueeze(2).unsqueeze(3) + self.weight = nn.Parameter(weight) + + def forward(self, input): + _, _, height, width = input.shape + + out = F.conv2d(input, self.weight) + logdet = ( + height * width * torch.slogdet(self.weight.squeeze().double())[1].float() + ) + + return out, logdet + + def reverse(self, output): + return F.conv2d( + output, self.weight.squeeze().inverse().unsqueeze(2).unsqueeze(3) + ) + + +class InvConv2dLU(nn.Module): + def __init__(self, in_channel): + super().__init__() + + weight = np.random.randn(in_channel, in_channel) + q, _ = la.qr(weight) + w_p, w_l, w_u = la.lu(q.astype(np.float32)) + w_s = np.diag(w_u) + w_u = np.triu(w_u, 1) + u_mask = np.triu(np.ones_like(w_u), 1) + l_mask = u_mask.T + + w_p = torch.from_numpy(w_p) + w_l = torch.from_numpy(w_l).contiguous() + w_s = torch.from_numpy(w_s) + w_u = torch.from_numpy(w_u) + + self.register_buffer('w_p', w_p) + self.register_buffer('u_mask', torch.from_numpy(u_mask)) + self.register_buffer('l_mask', torch.from_numpy(l_mask)) + self.register_buffer('s_sign', torch.sign(w_s)) + self.register_buffer('l_eye', torch.eye(l_mask.shape[0])) + self.w_l = nn.Parameter(w_l) + self.w_s = nn.Parameter(torch.log(torch.abs(w_s))) + self.w_u = nn.Parameter(w_u) + + def forward(self, input): + _, _, height, width = input.shape + + weight = self.calc_weight() + + out = F.conv2d(input, weight) + logdet = height * width * torch.sum(self.w_s) + + return out, logdet + + def calc_weight(self): + weight = ( + self.w_p + @ (self.w_l * self.l_mask + self.l_eye) + @ ((self.w_u * self.u_mask) + torch.diag(self.s_sign * torch.exp(self.w_s))) + ) + + return weight.unsqueeze(2).unsqueeze(3) + + def reverse(self, output): + weight = self.calc_weight() + dtype = weight.dtype + weight = weight.float() + weight_inv = weight.squeeze().inverse().unsqueeze(2).unsqueeze(3) + weight_inv = weight_inv.to(dtype=dtype) + + return F.conv2d(output, weight_inv) + + +class GraphConv(nn.Module): + def __init__(self, in_channels, out_channels, num_atoms, num_edge_type=4): + super(GraphConv, self).__init__() + + self.graph_linear_self = nn.Linear(in_channels, out_channels) + self.graph_linear_edge = nn.Linear(in_channels, out_channels * num_edge_type) + self.num_edge_type = num_edge_type + self.in_ch = in_channels + self.out_ch = out_channels + self.num_atoms = num_atoms + + def forward(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> torch.Tensor: + adj, nodes = graph + hs = self.graph_linear_self(nodes) + m = self.graph_linear_edge(nodes) + m = m.view(-1, self.num_atoms, self.out_ch, self.num_edge_type) + hr = torch.einsum('bemn,bnce->bmc', adj, m) + hr = hr.unsqueeze(2) + return hs + hr diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/model/coupling.py b/PyTorch/DrugDiscovery/MoFlow/moflow/model/coupling.py new file mode 100644 index 000000000..55a12c633 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/model/coupling.py @@ -0,0 +1,196 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +from typing import Tuple +import torch +import torch.nn as nn +from torch.nn.functional import logsigmoid + +from moflow.model.basic import GraphConv + + +def sigmoid_inverse(x): + """Calculates 1/sigmoid(x) in a more numerically stable way""" + return 1 + torch.exp(-x) + + +class AffineCoupling(nn.Module): # delete + def __init__(self, in_channel, hidden_channels, mask_swap=False): # filter_size=512, --> hidden_channels =(512, 512) + super(AffineCoupling, self).__init__() + + self.mask_swap=mask_swap + # self.norms_in = nn.ModuleList() + last_h = in_channel // 2 + vh = tuple(hidden_channels) + layers = [] + for h in vh: + layers.append(nn.Conv2d(last_h, h, kernel_size=3, padding=1)) + layers.append(nn.BatchNorm2d(h)) + layers.append(nn.ReLU(inplace=True)) + last_h = h + layers.append(nn.Conv2d(last_h, in_channel, kernel_size=3, padding=1)) + self.layers = nn.Sequential(*layers) + + def forward(self, input: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + in_a, in_b = input.chunk(2, 1) # (2,12,32,32) --> (2,6,32,32), (2,6,32,32) + + if self.mask_swap: + in_a, in_b = in_b, in_a + + s_logits, t = self._s_t_function(in_a) + s = torch.sigmoid(s_logits) + out_b = (in_b + t) * s + logdet = torch.sum(logsigmoid(s_logits).reshape(input.shape[0], -1), 1) + + if self.mask_swap: + result = torch.cat([out_b, in_a], 1) + else: + result = torch.cat([in_a, out_b], 1) + + return result, logdet + + @torch.jit.export + def reverse(self, output: torch.Tensor) -> torch.Tensor: + out_a, out_b = output.chunk(2, 1) + if self.mask_swap: + out_a, out_b = out_b, out_a + + s_logits, t = self._s_t_function(out_a) + s_inverse = sigmoid_inverse(s_logits) + in_b = out_b * s_inverse - t + + if self.mask_swap: + result = torch.cat([in_b, out_a], 1) + else: + result = torch.cat([out_a, in_b], 1) + + return result + + def _s_t_function(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + h = self.layers(x) + s_logits, t = h.chunk(2, 1) + return s_logits, t + + +class ConvCouplingBlock(nn.Module): + def __init__(self, in_dim: int, out_dim: int, n_node: int) -> None: + super().__init__() + self.graph_conv = GraphConv(in_dim, out_dim, n_node) + self.bn = nn.BatchNorm2d(n_node) + self.relu = nn.ReLU(inplace=True) + + def forward(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> Tuple[torch.Tensor, torch.Tensor]: + adj, nodes = graph + h = self.graph_conv(graph) + h = h.to(memory_format=torch.channels_last) + h = self.bn(h) + h = self.relu(h) + return adj, h + + +class LinCouplingBlock(nn.Module): + def __init__(self, in_dim: int, out_dim: int, n_node: int) -> None: + super().__init__() + self.lin = nn.Linear(in_dim, out_dim) + self.bn = nn.BatchNorm2d(n_node) + self.relu = nn.ReLU(inplace=True) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + h = self.lin(x) + h = h.to(memory_format=torch.channels_last) + h = self.bn(h) + h = self.relu(h) + return h + + +class GraphAffineCoupling(nn.Module): + def __init__(self, n_node, in_dim, hidden_dim_dict, masked_row): + super(GraphAffineCoupling, self).__init__() + self.n_node = n_node + self.in_dim = in_dim + self.hidden_dim_dict = hidden_dim_dict + self.masked_row = masked_row + + self.hidden_dim_gnn = hidden_dim_dict['gnn'] + self.hidden_dim_linear = hidden_dim_dict['linear'] + + conv_layers = [] + last_dim = in_dim + for out_dim in self.hidden_dim_gnn: + conv_layers.append(ConvCouplingBlock(last_dim, out_dim, n_node)) + last_dim = out_dim + self.net_conv = nn.ModuleList(conv_layers) + + lin_layers = [] + for out_dim in self.hidden_dim_linear: + lin_layers.append(LinCouplingBlock(last_dim, out_dim, n_node)) + last_dim = out_dim + lin_layers.append(nn.Linear(last_dim, in_dim*2)) + self.net_lin = nn.Sequential(*lin_layers) + + mask = torch.ones(n_node, in_dim) + mask[masked_row, :] = 0 # masked_row are kept same, and used for _s_t for updating the left rows + self.register_buffer('mask', mask) + + def forward(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> Tuple[torch.Tensor, torch.Tensor]: + adj, input = graph + masked_x = self.mask * input + masked_x_sq = masked_x.unsqueeze(2) + s_logits, t = self._s_t_function((adj, masked_x_sq)) + s = torch.sigmoid(s_logits) + out = masked_x + (1-self.mask) * (input + t) * s + logdet = torch.sum(logsigmoid(s_logits).reshape(input.shape[0], -1), 1) + return out, logdet + + @torch.jit.export + def reverse(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> torch.Tensor: + adj, output = graph + masked_y = self.mask * output + masked_y_sq = masked_y.unsqueeze(2) + s_logits, t = self._s_t_function((adj, masked_y_sq)) + s_inverse = sigmoid_inverse(s_logits) + input = masked_y + (1 - self.mask) * (output * s_inverse - t) + return input + + def _s_t_function(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> Tuple[torch.Tensor, torch.Tensor]: + for l in self.net_conv: + graph = l(graph) + adj, h = graph + h = self.net_lin(h) + h = h.squeeze(2) + s_logits, t = h.chunk(2, dim=-1) + + return s_logits, t diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/model/glow.py b/PyTorch/DrugDiscovery/MoFlow/moflow/model/glow.py new file mode 100644 index 000000000..eaa69bf84 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/model/glow.py @@ -0,0 +1,270 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +from typing import Tuple +import torch +import torch.nn as nn + +from moflow.model.basic import ActNorm, InvConv2dLU, InvConv2d +from moflow.model.coupling import AffineCoupling, GraphAffineCoupling + + +class Flow(nn.Module): + def __init__(self, in_channel, hidden_channels, conv_lu=2, mask_swap=False): + super(Flow, self).__init__() + + # More stable to support more flows + self.actnorm = ActNorm(num_channels=in_channel, num_dims=4) + + if conv_lu == 0: + self.invconv = InvConv2d(in_channel) + elif conv_lu == 1: + self.invconv = InvConv2dLU(in_channel) + elif conv_lu == 2: + self.invconv = None + else: + raise ValueError("conv_lu in {0,1,2}, 0:InvConv2d, 1:InvConv2dLU, 2:none-just swap to update in coupling") + + self.coupling = AffineCoupling(in_channel, hidden_channels, mask_swap=mask_swap) + + def forward(self, input: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + out, logdet = self.actnorm(input) + if self.invconv is not None: + out, det1 = self.invconv(out) + else: + det1 = 0 + out, det2 = self.coupling(out) + + logdet = logdet + det1 + if det2 is not None: + logdet = logdet + det2 + + return out, logdet + + @torch.jit.export + def reverse(self, output: torch.Tensor) -> torch.Tensor: + input = self.coupling.reverse(output) + if self.invconv is not None: + input = self.invconv.reverse(input) + input = self.actnorm.reverse(input) + + return input + + +class FlowOnGraph(nn.Module): + def __init__(self, n_node, in_dim, hidden_dim_dict, masked_row): + super(FlowOnGraph, self).__init__() + self.n_node = n_node + self.in_dim = in_dim + self.hidden_dim_dict = hidden_dim_dict + self.masked_row = masked_row + self.actnorm = ActNorm(num_channels=n_node, num_dims=3) + self.coupling = GraphAffineCoupling(n_node, in_dim, hidden_dim_dict, masked_row) + + def forward(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> Tuple[torch.Tensor, torch.Tensor]: + adj, input = graph + out, logdet = self.actnorm(input) + det1 = 0 + out, det2 = self.coupling((adj, out)) + + logdet = logdet + det1 + if det2 is not None: + logdet = logdet + det2 + return out, logdet + + @torch.jit.export + def reverse(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> torch.Tensor: + adj, output = graph + input = self.coupling.reverse((adj, output)) + input = self.actnorm.reverse(input) + return input + + +class Block(nn.Module): + def __init__(self, in_channel, n_flow, squeeze_fold, hidden_channels, conv_lu=2): + super(Block, self).__init__() + self.squeeze_fold = squeeze_fold + squeeze_dim = in_channel * self.squeeze_fold * self.squeeze_fold + + self.flows = nn.ModuleList() + for i in range(n_flow): + if conv_lu in (0, 1): + self.flows.append(Flow(squeeze_dim, hidden_channels, + conv_lu=conv_lu, mask_swap=False)) + else: + self.flows.append(Flow(squeeze_dim, hidden_channels, + conv_lu=2, mask_swap=bool(i % 2))) + + def forward(self, input: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + out = self._squeeze(input) + logdet = 0 + + for flow in self.flows: + out, det = flow(out) + logdet = logdet + det + + out = self._unsqueeze(out) + return out, logdet + + @torch.jit.export + def reverse(self, output: torch.Tensor) -> torch.Tensor: + input = self._squeeze(output) + + for flow in self.flows[::-1]: + input = flow.reverse(input) + + unsqueezed = self._unsqueeze(input) + return unsqueezed + + def _squeeze(self, x: torch.Tensor) -> torch.Tensor: + """Trade spatial extent for channels. In forward direction, convert each + 1x4x4 volume of input into a 4x1x1 volume of output. + + Args: + x (torch.Tensor): Input to squeeze or unsqueeze. + reverse (bool): Reverse the operation, i.e., unsqueeze. + + Returns: + x (torch.Tensor): Squeezed or unsqueezed tensor. + """ + assert len(x.shape) == 4 + b_size, n_channel, height, width = x.shape + fold = self.squeeze_fold + + squeezed = x.view(b_size, n_channel, height // fold, fold, width // fold, fold) + squeezed = squeezed.permute(0, 1, 3, 5, 2, 4).contiguous() + out = squeezed.view(b_size, n_channel * fold * fold, height // fold, width // fold) + return out + + def _unsqueeze(self, x: torch.Tensor) -> torch.Tensor: + assert len(x.shape) == 4 + b_size, n_channel, height, width = x.shape + fold = self.squeeze_fold + unsqueezed = x.view(b_size, n_channel // (fold * fold), fold, fold, height, width) + unsqueezed = unsqueezed.permute(0, 1, 4, 2, 5, 3).contiguous() + out = unsqueezed.view(b_size, n_channel // (fold * fold), height * fold, width * fold) + return out + + +class BlockOnGraph(nn.Module): + def __init__(self, n_node, in_dim, hidden_dim_dict, n_flow, mask_row_size=1, mask_row_stride=1): + super(BlockOnGraph, self).__init__() + assert 0 < mask_row_size < n_node + self.flows = nn.ModuleList() + for i in range(n_flow): + start = i * mask_row_stride + masked_row =[r % n_node for r in range(start, start+mask_row_size)] + self.flows.append(FlowOnGraph(n_node, in_dim, hidden_dim_dict, masked_row=masked_row)) + + def forward(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> Tuple[torch.Tensor, torch.Tensor]: + adj, input = graph + out = input + logdet = 0 + for flow in self.flows: + out, det = flow((adj, out)) + logdet = logdet + det + return out, logdet + + @torch.jit.export + def reverse(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> torch.Tensor: + adj, output = graph + input = output + for flow in self.flows[::-1]: + input = flow.reverse((adj, input)) + return input + + +class Glow(nn.Module): + def __init__(self, in_channel, n_flow, n_block, squeeze_fold, hidden_channel, conv_lu=2): + super(Glow, self).__init__() + + self.blocks = nn.ModuleList() + n_channel = in_channel + for i in range(n_block): + self.blocks.append(Block(n_channel, n_flow, squeeze_fold, hidden_channel, conv_lu=conv_lu)) + + def forward(self, input: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + logdet = 0 + out = input + + for block in self.blocks: + out, det = block(out) + logdet = logdet + det + + return out, logdet + + @torch.jit.export + def reverse(self, z: torch.Tensor) -> torch.Tensor: + h = z + for i, block in enumerate(self.blocks[::-1]): + h = block.reverse(h) + + return h + + +class GlowOnGraph(nn.Module): + def __init__(self, n_node, in_dim, hidden_dim_dict, n_flow, n_block, + mask_row_size_list=(2,), mask_row_stride_list=(1,)): + super(GlowOnGraph, self).__init__() + + assert len(mask_row_size_list) == n_block or len(mask_row_size_list) == 1 + assert len(mask_row_stride_list) == n_block or len(mask_row_stride_list) == 1 + if len(mask_row_size_list) == 1: + mask_row_size_list = mask_row_size_list * n_block + if len(mask_row_stride_list) == 1: + mask_row_stride_list = mask_row_stride_list * n_block + self.blocks = nn.ModuleList() + for i in range(n_block): + mask_row_size = mask_row_size_list[i] + mask_row_stride = mask_row_stride_list[i] + self.blocks.append(BlockOnGraph(n_node, in_dim, hidden_dim_dict, n_flow, mask_row_size, mask_row_stride)) + + def forward(self, adj: torch.Tensor, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + logdet = 0 + out = x + for block in self.blocks: + out, det = block((adj, out)) + logdet = logdet + det + return out, logdet + + @torch.jit.export + def reverse(self, graph: Tuple[torch.Tensor, torch.Tensor]) -> torch.Tensor: + adj, z = graph + input = z + for i, block in enumerate(self.blocks[::-1]): + input = block.reverse((adj, input)) + + return input diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/model/model.py b/PyTorch/DrugDiscovery/MoFlow/moflow/model/model.py new file mode 100644 index 000000000..83e39950f --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/model/model.py @@ -0,0 +1,251 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import math +import torch +import torch.nn as nn + +from moflow.config import Config +from moflow.model.glow import Glow, GlowOnGraph + +def gaussian_nll(x, mean, ln_var): + """Computes the negative log-likelihood of a Gaussian distribution. + + Given two variable ``mean`` representing :math:`\\mu` and ``ln_var`` + representing :math:`\\log(\\sigma^2)`, this function computes in + elementwise manner the negative log-likelihood of :math:`x` on a + Gaussian distribution :math:`N(\\mu, S)`, + + .. math:: + + -\\log N(x; \\mu, \\sigma^2) = + \\log\\left(\\sqrt{(2\\pi)^D |S|}\\right) + + \\frac{1}{2}(x - \\mu)^\\top S^{-1}(x - \\mu), + + where :math:`D` is a dimension of :math:`x` and :math:`S` is a diagonal + matrix where :math:`S_{ii} = \\sigma_i^2`. + + Args: + x: Input variable. + mean: Mean of a Gaussian distribution, :math:`\\mu`. + ln_var: Logarithm of variance of a Gaussian distribution, + :math:`\\log(\\sigma^2)`. + + Returns: + torch.Tensor: + Negative log-likelihood. + """ + + x_prec = torch.exp(-ln_var) + x_diff = x - mean + x_power = (x_diff * x_diff) * x_prec * -0.5 + loss = (ln_var + math.log(2 * (math.pi))) / 2 - x_power + return loss + + +class MoFlowLoss(nn.Module): + def __init__(self, config: Config) -> None: + super().__init__() + self.b_n_type = config.num_edge_features + self.a_n_node = config.max_num_nodes + self.a_n_type = config.num_node_features + self.b_size = self.a_n_node * self.a_n_node * self.b_n_type + self.a_size = self.a_n_node * self.a_n_type + + if config.model_config.learn_dist: + self.ln_var = nn.Parameter(torch.zeros(1)) + else: + self.register_buffer('ln_var', torch.zeros(1)) + + def forward(self, h, adj_h, sum_log_det_jacs_x, sum_log_det_jacs_adj): + z = [h, adj_h] + logdet = [sum_log_det_jacs_x, sum_log_det_jacs_adj] + + device = z[0].device + dtype = z[0].dtype + z[0] = z[0].reshape(z[0].shape[0],-1) + z[1] = z[1].reshape(z[1].shape[0], -1) + + logdet[0] = logdet[0] - self.a_size * math.log(2.) + logdet[1] = logdet[1] - self.b_size * math.log(2.) + ln_var_adj = self.ln_var * torch.ones([self.b_size], device=device, dtype=dtype) + ln_var_x = self.ln_var * torch.ones([self.a_size], device=device, dtype=dtype) + nll_adj = torch.mean( + torch.sum(gaussian_nll(z[1], torch.zeros(self.b_size, device=device, dtype=dtype), ln_var_adj), dim=1) + - logdet[1]) + nll_adj = nll_adj / (self.b_size * math.log(2.)) # the negative log likelihood per dim with log base 2 + + nll_x = torch.mean(torch.sum( + gaussian_nll(z[0], torch.zeros(self.a_size, device=device, dtype=dtype), ln_var_x), + dim=1) - logdet[0]) + nll_x = nll_x / (self.a_size * math.log(2.)) # the negative log likelihood per dim with log base 2 + + return nll_x, nll_adj + + +class MoFlow(nn.Module): + def __init__(self, config: Config): + super(MoFlow, self).__init__() + self.config = config + self.b_n_type = config.num_edge_features + self.a_n_node = config.max_num_nodes + self.a_n_type = config.num_node_features + self.b_size = self.a_n_node * self.a_n_node * self.b_n_type + self.a_size = self.a_n_node * self.a_n_type + self.noise_scale = config.model_config.noise_scale + + self.bond_model = Glow( + in_channel=self.b_n_type, + n_flow=config.model_config.bond_config.n_flow, + n_block=config.model_config.bond_config.n_block, + squeeze_fold=config.model_config.bond_config.n_squeeze, + hidden_channel=config.model_config.bond_config.hidden_ch, + conv_lu=config.model_config.bond_config.conv_lu + ) + + self.atom_model = GlowOnGraph( + n_node=self.a_n_node, + in_dim=self.a_n_type, + hidden_dim_dict={ + 'gnn': config.model_config.atom_config.hidden_gnn, + 'linear': config.model_config.atom_config.hidden_lin + }, + n_flow=config.model_config.atom_config.n_flow, + n_block=config.model_config.atom_config.n_block, + mask_row_size_list=config.model_config.atom_config.mask_row_size_list, + mask_row_stride_list=config.model_config.atom_config.mask_row_stride_list, + ) + + self._cuda_graphs = dict() + self.atom_stream = None + self.bond_stream = None + + @torch.jit.ignore + def forward(self, adj: torch.Tensor, x: torch.Tensor, with_cuda_graph: bool = False): + """ + :param adj: (256,4,9,9) + :param x: (256,9,5) + :return: + """ + if with_cuda_graph and self.atom_stream is None: + self.atom_stream = torch.cuda.Stream() + self.bond_stream = torch.cuda.Stream() + h = x + # add uniform noise to node feature matrices + if self.training: + if self.noise_scale == 0: + h = h/2.0 - 0.5 + torch.rand_like(x) * 0.4 + else: + h = h + torch.rand_like(x) * self.noise_scale + if with_cuda_graph: + if self.atom_model not in self._cuda_graphs: + h, sum_log_det_jacs_x = self._forward_graph(self.atom_model, adj, h) + else: + self.atom_stream.wait_stream(torch.cuda.current_stream()) + with torch.cuda.stream(self.atom_stream): + h, sum_log_det_jacs_x = self._forward_graph(self.atom_model, adj, h) + else: + h, sum_log_det_jacs_x = self.atom_model(adj, h) + + # add uniform noise to adjacency tensors + if self.training: + if self.noise_scale == 0: + adj_bond = adj/2.0 - 0.5 + torch.rand_like(adj) * 0.4 + else: + adj_bond = adj + torch.rand_like(adj) * self.noise_scale + else: + adj_bond = adj + if with_cuda_graph: + if self.bond_model not in self._cuda_graphs: + adj_h, sum_log_det_jacs_adj = self._forward_graph(self.bond_model, adj_bond) + else: + self.bond_stream.wait_stream(torch.cuda.current_stream()) + with torch.cuda.stream(self.bond_stream): + adj_h, sum_log_det_jacs_adj = self._forward_graph(self.bond_model, adj_bond) + else: + adj_h, sum_log_det_jacs_adj = self.bond_model(adj_bond) + if with_cuda_graph: + torch.cuda.current_stream().wait_stream(self.atom_stream) + torch.cuda.current_stream().wait_stream(self.bond_stream) + return h, adj_h, sum_log_det_jacs_x, sum_log_det_jacs_adj + + @torch.jit.export + def reverse(self, z): + """ + Returns a molecule, given its latent vector. + :param z: latent vector. Shape: [B, N*N*M + N*T] + B = Batch size, N = number of atoms, M = number of bond types, + T = number of atom types (Carbon, Oxygen etc.) + :return: adjacency matrix and feature matrix of a molecule + """ + batch_size = z.shape[0] + z_x = z[:, :self.a_size] + z_adj = z[:, self.a_size:] + + h_adj = z_adj.reshape(batch_size, self.b_n_type, self.a_n_node, self.a_n_node) + h_adj = h_adj.to(memory_format=torch.channels_last) + h_adj = self.bond_model.reverse(h_adj) + + if self.noise_scale == 0: + h_adj = (h_adj + 0.5) * 2 + adj = h_adj + adj = adj + adj.permute(0, 1, 3, 2) + adj = adj / 2 + adj = adj.softmax(dim=1) + max_bond = adj.max(dim=1).values.reshape(batch_size, -1, self.a_n_node, self.a_n_node) + adj = torch.floor(adj / max_bond) + + adj = adj.to(memory_format=torch.channels_last) + h_x = z_x.reshape(batch_size, self.a_n_node, self.a_n_type) + h_x = self.atom_model.reverse((adj, h_x)) + if self.noise_scale == 0: + h_x = (h_x + 0.5) * 2 + return adj, h_x + + @torch.jit.ignore + def _forward_graph(self, model, *args): + if model not in self._cuda_graphs: + if torch.distributed.is_initialized(): + torch.distributed.barrier() + torch.cuda.synchronize() + self._cuda_graphs[model] = torch.cuda.make_graphed_callables( + model, + args, + ) + torch.cuda.synchronize() + if torch.distributed.is_initialized(): + torch.distributed.barrier() + return self._cuda_graphs[model](*args) diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/model/utils.py b/PyTorch/DrugDiscovery/MoFlow/moflow/model/utils.py new file mode 100644 index 000000000..6f9233040 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/model/utils.py @@ -0,0 +1,42 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import logging +from typing import Iterable +import torch + +def initialize_module(module: torch.nn.Module, inputs: Iterable[torch.Tensor]) -> None: + """Use given sample input to initialize the module. + Module must implement method called `initialize` which takes list of input tensors + """ + assert hasattr(module, 'initialize') + assert len(inputs) == 1, f'{len(inputs)} inputs' + assert module.initialized.item() == 0, 'initialized' + module.initialize(*inputs) + assert module.initialized.item() == 1, 'not initialized' + + +def initialize(model: torch.nn.Module, single_batch: Iterable[torch.Tensor]) -> None: + """Initialize all sub-modules in the model given the sample input batch.""" + hooks = [] + for name, module in model.named_modules(): + if hasattr(module, 'initialize'): + logging.info(f'marking {name} for initialization') + hook = module.register_forward_pre_hook(initialize_module) + hooks.append(hook) + _ = model(*single_batch) + logging.info('all modules initialized, removing hooks') + for hook in hooks: + hook.remove() diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/__init__.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/arguments.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/arguments.py new file mode 100644 index 000000000..9aa610cbc --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/arguments.py @@ -0,0 +1,69 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import argparse +import os + +from moflow.config import CONFIGS +from moflow.runtime.logger import LOGGING_LEVELS + + +PARSER = argparse.ArgumentParser() +PARSER.add_argument('--data_dir', type=str, default='/data', help='Location for the dataset.') +PARSER.add_argument('--config_name', type=str, default='zinc250k', choices=list(CONFIGS), + help='The config to choose. This parameter allows one to switch between different datasets ' + 'and their dedicated configurations of the neural network. By default, a pre-defined "zinc250k" config is used.') +PARSER.add_argument('--results_dir', type=str, default='/results', help='Directory where checkpoints are stored.') +PARSER.add_argument('--predictions_path', type=str, default='/results/predictions.smi', + help='Path to store generated molecules. If an empty string is provided, predictions will not be ' + 'saved (useful for benchmarking and debugging).') +PARSER.add_argument('--log_path', type=str, default=None, + help='Path for DLLogger log. This file will contain information about the speed and ' + 'accuracy of the model during training and inference. Note that if the file ' + 'already exists, new logs will be added at the end.') +PARSER.add_argument('--log_interval', type=int, default=20, help='Frequency for writing logs, expressed in steps.') +PARSER.add_argument('--warmup_steps', type=int, default=20, + help='Number of warmup steps. This value is used for benchmarking and for CUDA graph capture.') +PARSER.add_argument('--steps', type=int, default=-1, + help='Number of steps used for training/inference. This parameter allows finishing ' + 'training earlier than the specified number of epochs. If used with inference, ' + 'it allows generating more molecules (by default only a single batch of molecules is generated).') +PARSER.add_argument('--save_epochs', type=int, default=5, + help='Frequency for saving checkpoints, expressed in epochs. If -1 is provided, checkpoints will not be saved.') +PARSER.add_argument('--eval_epochs', type=int, default=5, + help='Evaluation frequency, expressed in epochs. If -1 is provided, an evaluation will not be performed.') +PARSER.add_argument('--learning_rate', type=float, default=0.0005, help='Base learning rate.') +PARSER.add_argument('--beta1', type=float, default=0.9, help='beta1 parameter for the optimizer.') +PARSER.add_argument('--beta2', type=float, default=0.99, help='beta2 parameter for the optimizer.') +PARSER.add_argument('--clip', type=float, default=1, help='Gradient clipping norm.') +PARSER.add_argument('--epochs', type=int, default=300, + help='Number of training epochs. Note that you can finish training mid-epoch by using "--steps" flag.') +PARSER.add_argument('--batch_size', type=int, default=512, help='Batch size per GPU.') +PARSER.add_argument('--num_workers', type=int, default=4, help='Number of workers in the data loader.') +PARSER.add_argument('--seed', type=int, default=1, help='Random seed used to initialize the distributed loaders.') +PARSER.add_argument('--local_rank', default=os.environ.get('LOCAL_RANK', 0), type=int, + help='rank of the GPU, used to launch distributed training. This argument is specified ' + 'automatically by `torchrun` and does not have to be provided by the user.') +PARSER.add_argument('--temperature', type=float, default=0.3, help='Temperature used for sampling.') +PARSER.add_argument('--val_batch_size', type=int, default=100, help='Number of molecules to generate during validation step.') +PARSER.add_argument('--allow_untrained', action='http://github.com/store_true', + help='Allow sampling molecules from an untrained network. Useful for performance benchmarking or debugging purposes.') +PARSER.add_argument('--correct_validity', action='http://github.com/store_true', help='Apply validity correction after the generation of the molecules.') +PARSER.add_argument('--amp', action='http://github.com/store_true', help='Use Automatic Mixed Precision.') +PARSER.add_argument('--cuda_graph', action='http://github.com/store_true', help='Capture GPU kernels with CUDA graphs. This option allows to speed up training.') +PARSER.add_argument('--jit', action='http://github.com/store_true', help='Compile the model with `torch.jit.script`. Can be used to speed up training or inference.') +PARSER.add_argument('--verbosity', type=int, default=1, choices=list(LOGGING_LEVELS), + help='Verbosity level. Specify the following values: 0, 1, 2, 3, where 0 means minimal ' + 'verbosity (errors only) and 3 - maximal (debugging).') diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/common.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/common.py new file mode 100644 index 000000000..1a31c4d76 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/common.py @@ -0,0 +1,93 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from glob import glob +import logging +import os +from typing import List, Optional, Tuple +import torch + +from moflow.model.model import MoFlow + + +CHECKPOINT_PATTERN = 'model_snapshot_epoch_%s' + + +def _sort_checkpoints(paths: List[str]) -> List[str]: + return sorted(paths, key=lambda x: int(x.split('_')[-1])) + + +def save_state(dir: str, model: MoFlow, optimizer: torch.optim.Optimizer, ln_var: float, epoch: int, keep: int = 1) -> None: + """Save training state in a given dir. This checkpoint can be used to resume training or run inference + with the trained model. This function will keep up to newest checkpoints and remove the oldest ones. + """ + save_path = os.path.join(dir, CHECKPOINT_PATTERN % (epoch + 1)) + state = { + 'model': model.state_dict(), + 'optimizer': optimizer.state_dict(), + 'ln_var': ln_var, + 'epoch': epoch, + } + torch.save(state, save_path) + + if keep > 0: + filenames = glob(os.path.join(dir, CHECKPOINT_PATTERN % '*')) + if len(filenames) <= keep: + return + + to_del = _sort_checkpoints(filenames)[:-keep] + for path in to_del: + os.remove(path) + + +def load_state(path: str, model: MoFlow, device: torch.device, optimizer: Optional[torch.optim.Optimizer] = None) -> Tuple[int, float]: + """Load model's and optimizer's state from a given file. + This function returns the number of epochs the model was trained for and natural logarithm of variance + the for the distribution of the latent space. + """ + state = torch.load(path, map_location=device) + model.load_state_dict(state['model']) + if optimizer is not None: + optimizer.load_state_dict(state['optimizer']) + return state['epoch'], state['ln_var'] + + +def get_newest_checkpoint(model_dir: str, validate: bool = True) -> str: + """Find newest checkpoint in a given directory. + If validate is set to True, this function will also verify that the file can be loaded and + select older checkpoint if neccessary. + """ + filenames = glob(os.path.join(model_dir, CHECKPOINT_PATTERN % '*')) + if len(filenames) == 0: + logging.info(f'No checkpoints available') + return None + + paths = _sort_checkpoints(filenames) + if validate: + for latest_path in paths[::-1]: + try: + torch.load(latest_path, map_location='cpu') + break + except: + logging.info(f'Checkpoint {latest_path} is corrupted') + else: + logging.info(f'All available checkpoints were corrupted') + return None + + else: + latest_path = paths[-1] + + logging.info(f'Found checkpoint {latest_path}') + return latest_path diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/distributed_utils.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/distributed_utils.py new file mode 100644 index 000000000..67ca67e16 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/distributed_utils.py @@ -0,0 +1,71 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import logging +import os + +import torch +import torch.distributed as dist + + +def get_device(local_rank: int) -> torch.device: + if torch.cuda.is_available(): + torch.cuda.set_device(local_rank % torch.cuda.device_count()) + device = torch.device("cuda") + else: + device = torch.device("cpu") + logging.warning("not using a(ny) GPU(s)!") + return device + + +def get_world_size() -> int: + return int(os.environ.get("WORLD_SIZE", 1)) + + +def reduce_tensor(tensor: torch.Tensor, num_gpus: int) -> torch.Tensor: + if num_gpus > 1: + rt = tensor.clone() + dist.all_reduce(rt, op=dist.ReduceOp.SUM) + if rt.is_floating_point(): + rt = rt / num_gpus + else: + rt = rt // num_gpus + return rt + return tensor + + +def init_distributed() -> bool: + world_size = int(os.environ.get("WORLD_SIZE", 1)) + distributed = world_size > 1 + if distributed: + backend = "nccl" if torch.cuda.is_available() else "gloo" + os.environ["NCCL_ASYNC_ERROR_HANDLING"] = "0" # Needed for CUDA graphs + dist.init_process_group(backend=backend, init_method="env://") + assert dist.is_initialized() + + if get_rank() == 0: + logging.info(f"Distributed initialized. World size: {world_size}") + return distributed + + +def get_rank() -> int: + """ + Gets distributed rank or returns zero if distributed is not initialized. + """ + if torch.distributed.is_available() and torch.distributed.is_initialized(): + rank = torch.distributed.get_rank() + else: + rank = 0 + return rank diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/evaluate.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/evaluate.py new file mode 100644 index 000000000..080b2444b --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/evaluate.py @@ -0,0 +1,97 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from functools import partial +import os + +import numpy as np +import torch +from torch.cuda.amp import autocast + +from moflow.config import CONFIGS +from moflow.data import transform +from moflow.data.data_loader import NumpyTupleDataset + +from moflow.model.model import MoFlow +from moflow.utils import check_validity, convert_predictions_to_mols, predictions_to_smiles, check_novelty +from moflow.runtime.arguments import PARSER +from moflow.runtime.common import get_newest_checkpoint, load_state +from moflow.runtime.distributed_utils import get_device +from moflow.runtime.generate import infer +from moflow.runtime.logger import MetricsLogger, setup_logging + + +if __name__ == '__main__': + from rdkit import RDLogger + RDLogger.DisableLog('rdApp.*') + + args = PARSER.parse_args() + logger = setup_logging(args) + + snapshot_path = get_newest_checkpoint(args.results_dir) + config = CONFIGS[args.config_name] + model = MoFlow(config) + + device = get_device(args.local_rank) + if snapshot_path is not None: + epoch, ln_var = load_state(snapshot_path, model, device=device) + elif args.allow_untrained: + epoch, ln_var = 0, 0 + else: + raise RuntimeError('Generating molecules from an untrained network! ' + 'If this was intentional, pass --allow_untrained flag.') + model.to(device) + model.eval() + + if args.steps == -1: + args.steps = 1 + + acc_logger = MetricsLogger(logger) + valid_idx = transform.get_val_ids(config, args.data_dir) + dataset = NumpyTupleDataset.load( + os.path.join(args.data_dir, config.dataset_config.dataset_file), + transform=partial(transform.transform_fn, config=config), + ) + train_idx = [t for t in range(len(dataset)) if t not in valid_idx] + n_train = len(train_idx) + train_dataset = torch.utils.data.Subset(dataset, train_idx) + train_x = torch.Tensor(np.array([a[0] for a in train_dataset])) + train_adj = torch.Tensor(np.array([a[1] for a in train_dataset])) + + train_smiles = set(predictions_to_smiles(train_adj, train_x, config)) + + + with autocast(enabled=args.amp): + for i in range(args.steps): + results = infer( + model, config, ln_var=ln_var, temp=args.temperature, batch_size=args.batch_size, + device=device) + + mols_batch = convert_predictions_to_mols(*results, correct_validity=args.correct_validity) + validity_info = check_validity(mols_batch) + novel_r, abs_novel_r = check_novelty(validity_info['valid_smiles'], train_smiles, len(mols_batch)) + _, nuv = check_novelty(list(set(validity_info['valid_smiles'])), train_smiles, len(mols_batch)) + metrics = { + 'validity': validity_info['valid_ratio'], + 'novelty': novel_r, + 'uniqueness': validity_info['unique_ratio'], + 'abs_novelty': abs_novel_r, + 'abs_uniqueness': validity_info['abs_unique_ratio'], + 'nuv': nuv, + } + + acc_logger.update(metrics) + + acc_logger.summarize(step=tuple()) diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/generate.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/generate.py new file mode 100644 index 000000000..91b5446e2 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/generate.py @@ -0,0 +1,97 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from typing import Optional, Tuple + +import numpy as np +from torch.cuda.amp import autocast +import torch + +from moflow.config import CONFIGS, Config + +from moflow.model.model import MoFlow +from moflow.utils import convert_predictions_to_mols, postprocess_predictions +from moflow.runtime.arguments import PARSER +from moflow.runtime.common import get_newest_checkpoint, load_state +from moflow.runtime.distributed_utils import get_device +from moflow.runtime.logger import PerformanceLogger, setup_logging + + +def infer(model: MoFlow, config: Config, device: torch.device, *, + ln_var: float = 0, temp: float = 0.6, mu: Optional[torch.Tensor] = None, + batch_size: int = 20) -> Tuple[np.ndarray, np.ndarray]: + + if mu is None: + mu = torch.zeros(config.z_dim, dtype=torch.float32, device=device) + + sigma = temp * np.sqrt(np.exp(ln_var)) + with torch.no_grad(): + z = torch.normal(mu.reshape(-1, config.z_dim).repeat((batch_size, 1)), sigma) + adj, x = model.reverse(z) + x, adj = postprocess_predictions(x, adj, config=config) + + return adj, x + + +if __name__ == '__main__': + from rdkit import RDLogger + RDLogger.DisableLog('rdApp.*') + + args = PARSER.parse_args() + logger = setup_logging(args) + perf_logger = PerformanceLogger(logger, args.batch_size, args.warmup_steps, mode='generate') + if args.predictions_path: + from rdkit.Chem import SmilesWriter + smiles_writer = SmilesWriter(args.predictions_path) + + snapshot_path = get_newest_checkpoint(args.results_dir) + config = CONFIGS[args.config_name] + model = MoFlow(config) + + device = get_device(args.local_rank) + if snapshot_path is not None: + epoch, ln_var = load_state(snapshot_path, model, device=device) + elif args.allow_untrained: + epoch, ln_var = 0, 0 + else: + raise RuntimeError('Generating molecules from an untrained network! ' + 'If this was intentional, pass --allow_untrained flag.') + model.to(device=device, memory_format=torch.channels_last) + model.eval() + if args.jit: + model.atom_model = torch.jit.script(model.atom_model) + model.bond_model = torch.jit.script(model.bond_model) + + + if args.steps == -1: + args.steps = 1 + + with autocast(enabled=args.amp): + for i in range(args.steps): + perf_logger.update() + results = infer( + model, config, ln_var=ln_var, temp=args.temperature, batch_size=args.batch_size, + device=device) + + if (i + 1) % args.log_interval == 0: + perf_logger.summarize(step=(0, i, i)) + if args.predictions_path: + mols_batch = convert_predictions_to_mols(*results, correct_validity=args.correct_validity) + for mol in mols_batch: + smiles_writer.write(mol) + + perf_logger.summarize(step=tuple()) + if args.predictions_path: + smiles_writer.close() diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/logger.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/logger.py new file mode 100644 index 000000000..0918b1036 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/logger.py @@ -0,0 +1,123 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from abc import ABC, abstractmethod +import logging +import time + +import dllogger +from dllogger import JSONStreamBackend, StdOutBackend, Verbosity +import numpy as np + + +LOGGING_LEVELS = dict(enumerate([logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG])) + + +def get_dllogger(args): + backends = [] + if args.local_rank == 0: + backends.append(StdOutBackend(Verbosity.VERBOSE)) + if args.log_path is not None: + backends.append(JSONStreamBackend(Verbosity.VERBOSE, args.log_path, append=True)) + dllogger.init(backends=backends) + return dllogger + + +def setup_logging(args): + logging.basicConfig( + format='%(asctime)s %(levelname)s:\t%(message)s', datefmt='%H:%M:%S', level=LOGGING_LEVELS[args.verbosity], force=True + ) + return get_dllogger(args) + + +class BaseLogger(ABC): + @abstractmethod + def update(self, **kwargs) -> None: + pass + + @abstractmethod + def process_stats(self) -> dict: + return {} + + @abstractmethod + def reset(self) -> None: + pass + + def summarize(self, step: tuple) -> None: + stats = self.process_stats() + if len(stats) == 0: + logging.warn('Empty stats for logging, skipping') + return + self.logger.log(step=step, data=stats) + self.logger.flush() + + +class PerformanceLogger(BaseLogger): + def __init__(self, logger, batch_size: int, warmup_steps: int = 100, mode: str = 'train'): + self.logger = logger + self.batch_size = batch_size + self.warmup_steps = warmup_steps + self._step = 0 + self._timestamps = [] + self.mode = mode + + def update(self, **kwargs) -> None: + self._step += 1 + if self._step >= self.warmup_steps: + self._timestamps.append(time.time()) + + def reset(self) -> None: + self._step = 0 + self._timestamps = [] + + def process_stats(self) -> dict: + if len(self._timestamps) < 2: + logging.warn('Cannot process performance stats - less than 2 measurements collected') + return {} + + timestamps = np.asarray(self._timestamps) + deltas = np.diff(timestamps) + throughput = (self.batch_size / deltas).mean() + stats = { + f'throughput_{self.mode}': throughput, + f'latency_{self.mode}_mean': deltas.mean(), + f'total_time_{self.mode}': timestamps[-1] - timestamps[0], + } + for level in [90, 95, 99]: + stats.update({f'latency_{self.mode}_{level}': np.percentile(deltas, level)}) + + return stats + + +class MetricsLogger(BaseLogger): + def __init__(self, logger, mode: str = 'train'): + self.logger = logger + self.mode = mode + self._metrics_dict = {} + + def update(self, metrics: dict, **kwargs) -> None: + for metrics_name, metric_val in metrics.items(): + if metrics_name not in self._metrics_dict: + self._metrics_dict[metrics_name] = [] + self._metrics_dict[metrics_name].append(float(metric_val)) + + def reset(self) -> None: + self._metrics_dict = {} + + def process_stats(self) -> dict: + stats = {} + for metric_name, metric_val in self._metrics_dict.items(): + stats[metric_name] = np.mean(metric_val) + return stats diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/train.py b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/train.py new file mode 100644 index 000000000..cd19c06bc --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/runtime/train.py @@ -0,0 +1,298 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import argparse +import functools +import json +import logging +import os +import signal +from typing import Dict + +from apex.contrib.clip_grad import clip_grad_norm_ +from apex.optimizers import FusedAdam as Adam +import torch +from torch.cuda.amp import autocast, GradScaler +from torch.utils.data.distributed import DistributedSampler + +from moflow.config import CONFIGS, Config +from moflow.data.data_loader import NumpyTupleDataset +from moflow.data import transform +from moflow.model.model import MoFlow, MoFlowLoss +from moflow.model.utils import initialize +from moflow.runtime.logger import MetricsLogger, PerformanceLogger, setup_logging +from moflow.runtime.arguments import PARSER +from moflow.runtime.common import get_newest_checkpoint, load_state, save_state +from moflow.runtime.distributed_utils import ( + get_device, get_rank, get_world_size, init_distributed, reduce_tensor +) +from moflow.runtime.generate import infer +from moflow.utils import check_validity, convert_predictions_to_mols + + +torch._C._jit_set_autocast_mode(True) + + +def run_validation(model: MoFlow, config: Config, ln_var: float, args: argparse.Namespace, + is_distributed: bool, world_size: int, device: torch.device) -> Dict[str, float]: + model.eval() + if is_distributed: + model_callable = model.module + else: + model_callable = model + result = infer(model_callable, config, device=device, ln_var=ln_var, batch_size=args.val_batch_size, + temp=args.temperature) + mols = convert_predictions_to_mols(*result, correct_validity=args.correct_validity) + validity_info = check_validity(mols) + valid_ratio = torch.tensor(validity_info['valid_ratio'], dtype=torch.float32, device=device) + unique_ratio = torch.tensor(validity_info['unique_ratio'], dtype=torch.float32, device=device) + valid_value = reduce_tensor(valid_ratio, world_size).detach().cpu().numpy() + unique_value = reduce_tensor(unique_ratio, world_size).detach().cpu().numpy() + model.train() + return {'valid': valid_value, 'unique': unique_value} + + +def train(args: argparse.Namespace) -> None: + os.makedirs(args.results_dir, exist_ok=True) + + # Device configuration + device = get_device(args.local_rank) + torch.cuda.set_stream(torch.cuda.Stream()) + is_distributed = init_distributed() + world_size = get_world_size() + local_rank = get_rank() + + logger = setup_logging(args) + if local_rank == 0: + perf_logger = PerformanceLogger(logger, args.batch_size * world_size, args.warmup_steps) + acc_logger = MetricsLogger(logger) + + if local_rank == 0: + logging.info('Input args:') + logging.info(json.dumps(vars(args), indent=4, separators=(',', ':'))) + + # Model configuration + assert args.config_name in CONFIGS + config = CONFIGS[args.config_name] + data_file = config.dataset_config.dataset_file + transform_fn = functools.partial(transform.transform_fn, config=config) + valid_idx = transform.get_val_ids(config, args.data_dir) + + if local_rank == 0: + logging.info('Config:') + logging.info(str(config)) + model = MoFlow(config) + model.to(device) + loss_module = MoFlowLoss(config) + loss_module.to(device) + + # Datasets: + dataset = NumpyTupleDataset.load( + os.path.join(args.data_dir, data_file), + transform=transform_fn, + ) + if len(valid_idx) == 0: + raise ValueError('Empty validation set!') + train_idx = [t for t in range(len(dataset)) if t not in valid_idx] + train = torch.utils.data.Subset(dataset, train_idx) + test = torch.utils.data.Subset(dataset, valid_idx) + + if world_size > 1: + sampler = DistributedSampler(train, seed=args.seed, drop_last=False) + else: + sampler = None + train_dataloader = torch.utils.data.DataLoader( + train, + batch_size=args.batch_size, + shuffle=sampler is None, + sampler=sampler, + num_workers=args.num_workers, + drop_last=True, + ) + + if local_rank == 0: + logging.info(f'Using {world_size} GPUs') + logging.info(f'Num training samples: {len(train)}') + logging.info(f'Minibatch-size: {args.batch_size}') + logging.info(f'Num Iter/Epoch: {len(train_dataloader)}') + logging.info(f'Num epoch: {args.epochs}') + + if is_distributed: + train_dataloader.sampler.set_epoch(-1) + x, adj, *_ = next(iter(train_dataloader)) + x = x.to(device) + adj = adj.to(device) + with autocast(enabled=args.amp): + initialize(model, (adj, x)) + + model.to(memory_format=torch.channels_last) + adj.to(memory_format=torch.channels_last) + + if args.jit: + model.bond_model = torch.jit.script(model.bond_model) + model.atom_model = torch.jit.script(model.atom_model) + + # make one pass in both directions to make sure that model works + with torch.no_grad(): + _ = model(adj, x) + _ = model.reverse(torch.randn(args.batch_size, config.z_dim, device=device)) + + if is_distributed: + model = torch.nn.parallel.DistributedDataParallel( + model, + device_ids=[local_rank], + output_device=local_rank, + ) + loss_module = torch.nn.parallel.DistributedDataParallel( + loss_module, + device_ids=[local_rank], + output_device=local_rank, + ) + model_callable = model.module + loss_callable = loss_module.module + else: + model_callable = model + loss_callable = loss_module + + # Loss and optimizer + optimizer = Adam((*model.parameters(), *loss_module.parameters()), lr=args.learning_rate, betas=(args.beta1, args.beta2)) + scaler = GradScaler() + + if args.save_epochs == -1: + args.save_epochs = args.epochs + if args.eval_epochs == -1: + args.eval_epochs = args.epochs + if args.steps == -1: + args.steps = args.epochs * len(train_dataloader) + + snapshot_path = get_newest_checkpoint(args.results_dir) + if snapshot_path is not None: + snapshot_epoch, ln_var = load_state(snapshot_path, model_callable, optimizer=optimizer, device=device) + loss_callable.ln_var = torch.nn.Parameter(torch.tensor(ln_var)) + first_epoch = snapshot_epoch + 1 + step = first_epoch * len(train_dataloader) + else: + first_epoch = 0 + step = 0 + + if first_epoch >= args.epochs: + logging.info(f'Model was already trained for {first_epoch} epochs') + exit(0) + + for epoch in range(first_epoch, args.epochs): + if local_rank == 0: + acc_logger.reset() + if is_distributed: + train_dataloader.sampler.set_epoch(epoch) + for i, batch in enumerate(train_dataloader): + if local_rank == 0: + perf_logger.update() + step += 1 + optimizer.zero_grad() + x = batch[0].to(device) + adj = batch[1].to(device=device,memory_format=torch.channels_last) + + # Forward, backward and optimize + with_cuda_graph = ( + args.cuda_graph + and step >= args.warmup_steps + and x.size(0) == args.batch_size + ) + with autocast(enabled=args.amp, cache_enabled=not with_cuda_graph): + output = model(adj, x, with_cuda_graph=with_cuda_graph) + nll_x, nll_adj = loss_module(*output) + loss = nll_x + nll_adj + + if args.amp: + scaler.scale(loss).backward() + scaler.unscale_(optimizer) + clip_grad_norm_(model.parameters(), args.clip) + scaler.step(optimizer) + scaler.update() + else: + loss.backward() + clip_grad_norm_(model.parameters(), args.clip) + optimizer.step() + + # Print log info + if (i + 1) % args.log_interval == 0: + nll_x_value = reduce_tensor(nll_x, world_size).item() + nll_adj_value = reduce_tensor(nll_adj, world_size).item() + loss_value = nll_x_value + nll_adj_value + + if local_rank == 0: + acc_logger.update({ + 'loglik': loss_value, + 'nll_x': nll_x_value, + 'nll_adj': nll_adj_value + }) + + acc_logger.summarize(step=(epoch, i, i)) + perf_logger.summarize(step=(epoch, i, i)) + + if step >= args.steps: + break + + if (epoch + 1) % args.eval_epochs == 0: + with autocast(enabled=args.amp): + metrics = run_validation(model, config, loss_callable.ln_var.item(), args, is_distributed, world_size, device) + if local_rank == 0: + acc_logger.update(metrics) + + # The same report for each epoch + if local_rank == 0: + acc_logger.summarize(step=(epoch,)) + perf_logger.summarize(step=(epoch,)) + + # Save the model checkpoints + if (epoch + 1) % args.save_epochs == 0: + if local_rank == 0 or not is_distributed: + save_state(args.results_dir, model_callable, optimizer, loss_callable.ln_var.item(), epoch, keep=5) + + if step >= args.steps: + break + + if local_rank == 0: + acc_logger.summarize(step=tuple()) + perf_logger.summarize(step=tuple()) + + +if __name__ == '__main__': + from rdkit import RDLogger + RDLogger.DisableLog('rdApp.*') + + args = PARSER.parse_args() + train(args) diff --git a/PyTorch/DrugDiscovery/MoFlow/moflow/utils.py b/PyTorch/DrugDiscovery/MoFlow/moflow/utils.py new file mode 100644 index 000000000..d197934f4 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/moflow/utils.py @@ -0,0 +1,211 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import re +from typing import Dict, List, Optional, Tuple, Union + +import numpy as np +from rdkit import Chem +import torch + +from moflow.config import Config, ATOM_VALENCY, CODE_TO_BOND, DUMMY_CODE + + +def postprocess_predictions(x: Union[torch.Tensor, np.ndarray], adj: Union[torch.Tensor, np.ndarray], config: Config) -> Tuple[np.ndarray, np.ndarray]: + assert x.ndim == 3 and adj.ndim == 4, 'expected batched predictions' + n = config.dataset_config.max_num_atoms + adj = adj[:, :, :n, :n] + x = x[:, :n] + + atoms = torch.argmax(x, dim=2) + atoms = _to_numpy_array(atoms) + + adj = torch.argmax(adj, dim=1) + adj = _to_numpy_array(adj) + + decoded = np.zeros_like(atoms) + for code, atomic_num in config.dataset_config.code_to_atomic.items(): + decoded[atoms == code] = atomic_num + + return decoded, adj + + +def convert_predictions_to_mols(adj: np.ndarray, x: np.ndarray, correct_validity: bool = False) -> List[Chem.Mol]: + molecules = [construct_mol(x_elem, adj_elem) for x_elem, adj_elem in zip(x, adj)] + + if correct_validity: + molecules = [correct_mol(mol) for mol in molecules] + return molecules + + +def construct_mol(atoms: np.ndarray, adj: np.ndarray) -> Chem.Mol: + from rdkit import RDLogger + RDLogger.DisableLog('rdApp.*') + atoms_exist = (atoms != 0) + atoms = atoms[atoms_exist] + adj = adj[atoms_exist][:, atoms_exist] + + mol = Chem.RWMol() + + for atom in atoms: + mol.AddAtom(Chem.Atom(int(atom))) + + for start, end in zip(*np.where(adj != DUMMY_CODE)): + if start > end: + mol.AddBond(int(start), int(end), CODE_TO_BOND[int(adj[start, end])]) + # add formal charge to atom: e.g. [O+], [N+] [S+] + # not support [O-], [N-] [S-] [NH+] etc. + flag, atomid_valence = check_valency(mol) + if flag: + continue + else: + assert len(atomid_valence) == 2 + idx = atomid_valence[0] + v = atomid_valence[1] + an = mol.GetAtomWithIdx(idx).GetAtomicNum() + if an in (7, 8, 16) and (v - ATOM_VALENCY[an]) == 1: + mol.GetAtomWithIdx(idx).SetFormalCharge(1) + return mol + + +def valid_mol(x: Optional[Chem.Mol]) -> Optional[Chem.Mol]: + if x is None: + # RDKit wasn't able to create the mol + return None + smi = Chem.MolToSmiles(x, isomericSmiles=True) + if len(smi) == 0 or '.' in smi: + # Mol is empty or fragmented + return None + reloaded = Chem.MolFromSmiles(smi) + # if smiles is invalid - it will be None, otherwise mol is valid + return reloaded + + +def check_valency(mol: Chem.Mol) -> Tuple[bool, List[int]]: + """Checks that no atoms in the mol have exceeded their possible + valency. Returns True if no valency issues, False otherwise + plus information about problematic atom. + """ + try: + Chem.SanitizeMol(mol, sanitizeOps=Chem.SanitizeFlags.SANITIZE_PROPERTIES) + return True, None + except ValueError as e: + e = str(e) + p = e.find('#') + e_sub = e[p:] + atomid_valence = list(map(int, re.findall(r'\d+', e_sub))) + return False, atomid_valence + + +def correct_mol(mol: Chem.Mol) -> Chem.Mol: + flag, atomid_valence = check_valency(mol) + while not flag: + assert len(atomid_valence) == 2 + idx = atomid_valence[0] + v = atomid_valence[1] + queue = [] + for b in mol.GetAtomWithIdx(idx).GetBonds(): + queue.append( + (b.GetIdx(), int(b.GetBondType()), b.GetBeginAtomIdx(), b.GetEndAtomIdx()) + ) + queue.sort(key=lambda tup: tup[1], reverse=True) + if len(queue) > 0: + start = queue[0][2] + end = queue[0][3] + t = queue[0][1] - 1 + mol.RemoveBond(start, end) + if t >= 1: + mol.AddBond(start, end, CODE_TO_BOND[t]) + flag, atomid_valence = check_valency(mol) + + # if mol is fragmented, select the largest fragment + mols = Chem.GetMolFrags(mol, asMols=True) + mol = max(mols, key=lambda m: m.GetNumAtoms()) + + return mol + + +def predictions_to_smiles(adj: torch.Tensor, x: torch.Tensor, config: Config) -> List[str]: + x, adj = postprocess_predictions(x, adj, config=config) + valid = [Chem.MolToSmiles(construct_mol(x_elem, adj_elem), isomericSmiles=True) + for x_elem, adj_elem in zip(x, adj)] + return valid + + +def check_validity(molecules: List[Chem.Mol]) -> dict: + valid = [valid_mol(mol) for mol in molecules] + valid = [mol for mol in valid if mol is not None] + + n_mols = len(molecules) + valid_ratio = len(valid) / n_mols + valid_smiles = [Chem.MolToSmiles(mol, isomericSmiles=False) for mol in valid] + unique_smiles = list(set(valid_smiles)) + unique_ratio = 0. + if len(valid) > 0: + unique_ratio = len(unique_smiles) / len(valid) + valid_mols = [Chem.MolFromSmiles(s) for s in valid_smiles] + abs_unique_ratio = len(unique_smiles) / n_mols + + results = dict() + results['valid_mols'] = valid_mols + results['valid_smiles'] = valid_smiles + results['valid_ratio'] = valid_ratio * 100 + results['unique_ratio'] = unique_ratio * 100 + results['abs_unique_ratio'] = abs_unique_ratio * 100 + + return results + + +def check_novelty(gen_smiles: List[str], train_smiles: List[str], n_generated_mols: int): + if len(gen_smiles) == 0: + novel_ratio = 0. + abs_novel_ratio = 0. + else: + duplicates = [1 for mol in gen_smiles if mol in train_smiles] + novel = len(gen_smiles) - sum(duplicates) + novel_ratio = novel * 100. / len(gen_smiles) + abs_novel_ratio = novel * 100. / n_generated_mols + return novel_ratio, abs_novel_ratio + + +def _to_numpy_array(a): + if isinstance(a, torch.Tensor): + a = a.cpu().detach().numpy() + elif isinstance(a, np.ndarray): + pass + else: + raise TypeError("a ({}) is not a torch.Tensor".format(type(a))) + return a diff --git a/PyTorch/DrugDiscovery/MoFlow/scripts/benchmark_inference.sh b/PyTorch/DrugDiscovery/MoFlow/scripts/benchmark_inference.sh new file mode 100755 index 000000000..f53d039fc --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/scripts/benchmark_inference.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +bs=${1:-512} +prec=${2:-amp} +flags="${@:3}" + + +cmd="python \ + /workspace/moflow_pyt/moflow/runtime/generate.py \ + --batch_size ${bs} \ + --steps 200 \ + --warmup_steps 10 \ + --allow_untrained \ + --predictions_path '' \ + --jit \ + ${flags} \ + " + +if [ $prec == "amp" ]; then + cmd="${cmd} --amp" +fi + +set -x +bash -c "${cmd}" diff --git a/PyTorch/DrugDiscovery/MoFlow/scripts/benchmark_training.sh b/PyTorch/DrugDiscovery/MoFlow/scripts/benchmark_training.sh new file mode 100755 index 000000000..e65e7099f --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/scripts/benchmark_training.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +gpus=${1:-1} +bs=${2:-512} +prec=${3:-amp} +flags="${@:4}" + + +if [[ "${gpus}" == "1" ]]; then + cmd="python" +else + cmd="torchrun --nproc_per_node=${gpus}" +fi + +cmd="${cmd} \ + /workspace/moflow_pyt/moflow/runtime/train.py \ + --batch_size ${bs} \ + --steps 200 \ + --eval_epochs -1 \ + --save_epochs -1 \ + --cuda_graph \ + ${flags} \ + " + +if [ $prec == "amp" ]; then + cmd="${cmd} --amp" +fi + +set -x +bash -c "${cmd}" diff --git a/PyTorch/DrugDiscovery/MoFlow/scripts/data_preprocess.py b/PyTorch/DrugDiscovery/MoFlow/scripts/data_preprocess.py new file mode 100644 index 000000000..1cbf0a3e6 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/scripts/data_preprocess.py @@ -0,0 +1,80 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +import os +import pandas as pd +import argparse +import time + +from moflow.config import CONFIGS +from moflow.data.data_frame_parser import DataFrameParser +from moflow.data.encoding import MolEncoder + + +def parse_args(): + parser = argparse.ArgumentParser(description='') + parser.add_argument('--data_name', type=str, + choices=list(CONFIGS), + help='dataset to be downloaded') + parser.add_argument('--data_dir', type=str, default='/data') + args = parser.parse_args() + return args + +def main(args): + start_time = time.time() + args = parse_args() + print('args', vars(args)) + + assert args.data_name in CONFIGS + dataset_config = CONFIGS[args.data_name].dataset_config + + preprocessor = MolEncoder(out_size=dataset_config.max_num_atoms) + + input_path = os.path.join(args.data_dir, dataset_config.csv_file) + output_path = os.path.join(args.data_dir, dataset_config.dataset_file) + + print(f'Preprocessing {args.data_name} data:') + df = pd.read_csv(input_path, index_col=0) + parser = DataFrameParser(preprocessor, labels=dataset_config.labels, smiles_col=dataset_config.smiles_col) + dataset = parser.parse(df) + + dataset.save(output_path) + print('Total time:', time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time))) + + +if __name__ == '__main__': + args = parse_args() + main(args) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/auto_arima_electricity.yaml b/PyTorch/DrugDiscovery/MoFlow/scripts/predict.sh old mode 100644 new mode 100755 similarity index 62% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/auto_arima_electricity.yaml rename to PyTorch/DrugDiscovery/MoFlow/scripts/predict.sh index d82464068..d8cfda06b --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/auto_arima_electricity.yaml +++ b/PyTorch/DrugDiscovery/MoFlow/scripts/predict.sh @@ -1,10 +1,12 @@ +#!/bin/bash + # Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +14,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -dataset: - config: - stride: 400 + +bs=${1:-512} +prec=${2:-amp} +flags="${@:3}" + + +cmd="python \ + /workspace/moflow_pyt/moflow/runtime/generate.py \ + --batch_size ${bs} \ + --jit \ + --correct_validity \ + ${flags} \ + " + +if [ $prec == "amp" ]; then + cmd="${cmd} --amp" +fi + +set -x +bash -c "${cmd}" diff --git a/PyTorch/DrugDiscovery/MoFlow/scripts/prepare_datasets.sh b/PyTorch/DrugDiscovery/MoFlow/scripts/prepare_datasets.sh new file mode 100755 index 000000000..33c095a0d --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/scripts/prepare_datasets.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +REPO_URL='https://raw.githubusercontent.com/calvin-zcx/moflow' +GIT_HASH='3026b2e9bb8de027f3887deb96ccdd876ba51664' +DATA_DIR="/data" + +wget -O "${DATA_DIR}/zinc250k.csv" "${REPO_URL}/${GIT_HASH}/data/zinc250k.csv" +wget -O "${DATA_DIR}/valid_idx_zinc250k.json" "${REPO_URL}/${GIT_HASH}/data/valid_idx_zinc.json" + +python ${PWD}/scripts/data_preprocess.py --data_name "zinc250k" --data_dir ${DATA_DIR} diff --git a/PyTorch/DrugDiscovery/MoFlow/scripts/train.sh b/PyTorch/DrugDiscovery/MoFlow/scripts/train.sh new file mode 100755 index 000000000..06ede7c96 --- /dev/null +++ b/PyTorch/DrugDiscovery/MoFlow/scripts/train.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Copyright 2020 Chengxi Zang +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +gpus=${1:-1} +prec=${2:-amp} +flags="${@:3}" + + +if [[ "${gpus}" == "1" ]]; then + cmd="python" +else + cmd="torchrun --nproc_per_node=${gpus}" +fi + +cmd="${cmd} \ + /workspace/moflow_pyt/moflow/runtime/train.py \ + --cuda_graph \ + ${flags} \ + " + +eval_cmd="python \ + /workspace/moflow_pyt/moflow/runtime/evaluate.py \ + --steps 1000 \ + --jit \ + ${flags} \ + " + +if [ $prec == "amp" ]; then + cmd="${cmd} --amp" + eval_cmd="${eval_cmd} --amp" +fi + +if [[ $gpus == 1 ]]; then + cmd="${cmd} --learning_rate 0.0001" +fi + +set -x +bash -c "${cmd} && ${eval_cmd}" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/cuml_auto_arima.yaml b/PyTorch/DrugDiscovery/MoFlow/setup.py similarity index 63% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/cuml_auto_arima.yaml rename to PyTorch/DrugDiscovery/MoFlow/setup.py index 01cfc79bd..18b690e3d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/cuml_auto_arima.yaml +++ b/PyTorch/DrugDiscovery/MoFlow/setup.py @@ -4,7 +4,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,8 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -_target_: models.stat_models.CUMLAutoARIMA -defaults: - - _self_ - - /trainer@_global_/trainer: stattrainer +from setuptools import setup + +setup( + name='moflow_pyt', + packages=[ + 'moflow', + 'moflow.data', + 'moflow.model', + 'moflow.runtime' + ], + version='0.0.1', + description='MoFlow: an invertible flow model for generating molecular graphs', +) diff --git a/PyTorch/Forecasting/TFT/Dockerfile b/PyTorch/Forecasting/TFT/Dockerfile old mode 100644 new mode 100755 index 6f94e4726..7b057ad95 --- a/PyTorch/Forecasting/TFT/Dockerfile +++ b/PyTorch/Forecasting/TFT/Dockerfile @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:21.12-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.11-py3 + FROM ${FROM_IMAGE_NAME} # Set workdir and python path diff --git a/PyTorch/Forecasting/TFT/Dockerfile-triton b/PyTorch/Forecasting/TFT/Dockerfile-triton index 2d338397f..f4bc92fe2 100644 --- a/PyTorch/Forecasting/TFT/Dockerfile-triton +++ b/PyTorch/Forecasting/TFT/Dockerfile-triton @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:21.12-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.11-py3 FROM ${FROM_IMAGE_NAME} # Ensure apt-get won't prompt for selecting options diff --git a/PyTorch/Forecasting/TFT/README.md b/PyTorch/Forecasting/TFT/README.md index 6dda2327c..8284f9804 100644 --- a/PyTorch/Forecasting/TFT/README.md +++ b/PyTorch/Forecasting/TFT/README.md @@ -123,9 +123,6 @@ For information about: Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. -* APEX tools for mixed precision training, refer to the [NVIDIA Apex: Tools for Easy Mixed-Precision Training in - PyTorch](https://devblogs.nvidia.com/apex-pytorch-easy-mixed-precision-training/) - . #### Enabling mixed precision @@ -169,7 +166,7 @@ The following section lists the requirements that you need to meet in order to s This repository contains Dockerfile, which extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: - [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -- [PyTorch 21.12 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) +- [PyTorch 22.11 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) - Supported GPUs: - [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) - [NVIDIA Turing architecture](https://www.nvidia.com/en-us/design-visualization/technologies/turing-architecture/) @@ -371,7 +368,7 @@ The [NVIDIA Triton Inference Server](https://github.com/triton-inference-server/ ### Benchmarking -The following section shows how to run benchmarks measuring the model performance in training and inference modes. +The following section shows how to run benchmarks measuring the model performance in training and inference modes. Note that the first 3 steps of each epoch are not used in the throughput or latency calculation. This is due to the fact that the nvFuser performs the optimizations on the 3rd step of the first epoch causing a multi-second pause. #### Training performance benchmark @@ -390,24 +387,24 @@ We conducted an extensive hyperparameter search along with stability tests. The ##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA A100 (8x A100 80GB) GPUs. +Our results were obtained by running the `train.sh` training script in the [PyTorch 22.11 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA A100 (8x A100 80GB) GPUs. | Dataset | GPUs | Batch size / GPU | Accuracy - TF32 | Accuracy - mixed precision | Time to train - TF32 | Time to train - mixed precision | Time to train speedup (TF32 to mixed precision) |-------------|---|------|-----------------------|-----------------------|-------|-------|------- -| Electricity | 8 | 1024 | 0.027 / 0.057 / 0.029 | 0.028 / 0.057 / 0.029 | 216s | 176s | 1.227x -| Traffic | 8 | 1024 | 0.043 / 0.108 / 0.079 | 0.042 / 0.107 / 0.078 | 151s | 126s | 1.198x +| Electricity | 8 | 1024 | 0.026 / 0.056 / 0.029 | 0.028 / 0.058 / 0.029 | 200s | 176s | 1.136x +| Traffic | 8 | 1024 | 0.044 / 0.108 / 0.078 | 0.044 / 0.109 / 0.079 | 140s | 129s | 1.085x ##### Training accuracy: NVIDIA DGX-1 (8x V100 16GB) -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 with (8x V100 16GB) GPUs. +Our results were obtained by running the `train.sh` training script in the [PyTorch 22.11 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 with (8x V100 16GB) GPUs. | Dataset | GPUs | Batch size / GPU | Accuracy - FP32 | Accuracy - mixed precision | Time to train - FP32 | Time to train - mixed precision | Time to train speedup (FP32 to mixed precision) |-------------|---|------|-----------------------|-----------------------|-------|-------|----------- -| Electricity | 8 | 1024 | 0.028 / 0.057 / 0.029 | 0.027 / 0.057 / 0.029 | 381s | 261s | 1.460x -| Traffic | 8 | 1024 | 0.042 / 0.106 / 0.076 | 0.040 / 0.103 / 0.074 | 256s | 176s | 1.455x +| Electricity | 8 | 1024 | 0.028 / 0.057 / 0.028 | 0.027 / 0.059 / 0.030 | 371s | 269s | 1.379x +| Traffic | 8 | 1024 | 0.042 / 0.110 / 0.080 | 0.043 / 0.109 / 0.080 | 251s | 191s | 1.314x @@ -417,22 +414,22 @@ In order to get a greater picture of the model’s accuracy, we performed a hype | Dataset | #GPU | Hidden size | #Heads | Local BS | LR | Gradient clipping | Dropout | Mean q-risk | Std q-risk | Min q-risk | Max q-risk |-------------|------|-------------|--------|----------|------|-------------------|---------|-------------|------------| -----------|------ -| Electricity | 8 | 128 | 4 | 1024 | 1e-3 | 0.0 | 0.1 | 0.1131 | 0.0025 | 0.1080 | 0.1200 -| Traffic | 8 | 128 | 4 | 1024 | 1e-3 | 0.0 | 0.3 | 0.2180 | 0.0049 | 0.2069 | 0.2336 +| Electricity | 8 | 128 | 4 | 1024 | 1e-3 | 0.0 | 0.1 | 0.1129 | 0.0025 | 0.1074 | 0.1244 +| Traffic | 8 | 128 | 4 | 1024 | 1e-3 | 0.0 | 0.3 | 0.2262 | 0.0027 | 0.2207 | 0.2331 #### Training performance results ##### Training performance: NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA A100 (8x A100 80GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. +Our results were obtained by running the `train.sh` training script in the [PyTorch 22.11 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA A100 (8x A100 80GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. | Dataset | GPUs | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 - mixed precision) | Weak scaling - TF32 | Weak scaling - mixed precision |-------------|---|------|--------|--------|-------|-------|----- -| Electricity | 1 | 1024 | 10173 | 13703 | 1.35x | 1 | 1 -| Electricity | 8 | 1024 | 80596 | 107761 | 1.34x | 7.92x | 7.86x -| Traffic | 1 | 1024 | 10197 | 13779 | 1.35x | 1 | 1 -| Traffic | 8 | 1024 | 80692 | 107979 | 1.34x | 7.91x | 7.84x +| Electricity | 1 | 1024 | 12435 | 17608 | 1.42x | 1 | 1 +| Electricity | 8 | 1024 | 94389 | 130769 | 1.39x | 7.59x | 7.42x +| Traffic | 1 | 1024 | 12509 | 17591 | 1.40x | 1 | 1 +| Traffic | 8 | 1024 | 94476 | 130992 | 1.39x | 7.55x | 7.45x To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). @@ -442,14 +439,14 @@ The performance metrics used were items per second. ##### Training performance: NVIDIA DGX-1 (8x V100 16GB) -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 with (8x V100 16GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. +Our results were obtained by running the `train.sh` training script in the [PyTorch 22.11 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 with (8x V100 16GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. | Dataset | GPUs | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 - mixed precision) | Weak scaling - FP32 | Weak scaling - mixed precision |-------------|---|------|-------|-------|-------|------|---- -| Electricity | 1 | 1024 | 5580 | 9148 | 1.64x | 1 | 1 -| Electricity | 8 | 1024 | 43351 | 69855 | 1.61x | 7.77x | 7.64x -| Traffic | 1 | 1024 | 5593 | 9194 | 1.64x | 1 | 1 -| Traffic | 8 | 1024 | 43426 | 69983 | 1.61x | 7.76x | 7.61x +| Electricity | 1 | 1024 | 5932 | 10163 | 1.71x | 1 | 1 +| Electricity | 8 | 1024 | 45566 | 75660 | 1.66x | 7.68x | 7.44x +| Traffic | 1 | 1024 | 5971 | 10166 | 1.70x | 1 | 1 +| Traffic | 8 | 1024 | 45925 | 75640 | 1.64x | 7.69x | 7.44x @@ -463,39 +460,44 @@ The performance metrics used were items per second. ##### Inference Performance: NVIDIA DGX A100 -Our results were obtained by running the `inference.py` script in the [PyTorch 21.12 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX A100. Throughput is measured in items per second and latency is measured in milliseconds. +Our results were obtained by running the `inference.py` script in the [PyTorch 22.11 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX A100. Throughput is measured in items per second and latency is measured in milliseconds. To benchmark the inference performance on a specific batch size and dataset, run the `inference.py` script. | Dataset | GPUs | Batch size / GPU | Throughput - mixed precision (item/s) | Average Latency (ms) | Latency p90 (ms) | Latency p95 (ms) | Latency p99 (ms) |-------------|--------|-----|---------------------------------|-----------------|-------------|-------------|------------ -| Electricity | 1 | 1 | 144.37 | 6.93 | 7.00 | 7.04 | 7.25 -| Electricity | 1 | 2 | 277.53 | 7.21 | 7.25 | 7.27 | 7.48 -| Electricity | 1 | 4 | 564.37 | 7.09 | 7.13 | 7.15 | 7.64 -| Electricity | 1 | 8 | 1399.25 | 5.72 | 5.71 | 5.77 | 7.51 -| Traffic | 1 | 1 | 145.26 | 6.88 | 6.91 | 6.95 | 7.60 -| Traffic | 1 | 2 | 277.97 | 7.19 | 7.28 | 7.30 | 7.46 -| Traffic | 1 | 4 | 563.05 | 7.10 | 7.14 | 7.16 | 7.42 -| Traffic | 1 | 8 | 1411.62 | 5.67 | 5.69 | 5.79 | 6.21 +| Electricity | 1 | 1 | 272.43 | 3.67 | 3.70 | 3.87 | 4.18 +| Electricity | 1 | 2 | 518.13 | 3.86 | 3.88 | 3.93 | 4.19 +| Electricity | 1 | 4 | 1039.31 | 3.85 | 3.89 | 3.97 | 4.15 +| Electricity | 1 | 8 | 2039.54 | 3.92 | 3.93 | 3.95 | 4.32 +| Traffic | 1 | 1 | 269.59 | 3.71 | 3.74 | 3.79 | 4.30 +| Traffic | 1 | 2 | 518.73 | 3.86 | 3.78 | 3.91 | 4.66 +| Traffic | 1 | 4 | 1021.49 | 3.92 | 3.94 | 3.95 | 4.25 +| Traffic | 1 | 8 | 2005.54 | 3.99 | 4.01 | 4.03 | 4.39 ##### Inference Performance: NVIDIA DGX-1 V100 -Our results were obtained by running the `inference.py` script in the [PyTorch 21.12 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 V100. Throughput is measured in items per second and latency is measured in milliseconds. +Our results were obtained by running the `inference.py` script in the [PyTorch 22.11 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 V100. Throughput is measured in items per second and latency is measured in milliseconds. To benchmark the inference performance on a specific batch size and dataset, run the `inference.py` script. | Dataset | GPUs | Batch size / GPU | Throughput - mixed precision (item/s) | Average Latency (ms) | Latency p90 (ms) | Latency p95 (ms) | Latency p99 (ms) |-------------|--------|-----|---------------------------------|-----------------|-------------|-------------|------------ -| Electricity | 1 | 1 | 95.65 | 10.45 | 11.30 | 11.95 | 12.13 -| Electricity | 1 | 2 | 193.15 | 10.35 | 10.80 | 11.46 | 12.16 -| Electricity | 1 | 4 | 381.09 | 10.49 | 10.75 | 12.29 | 12.41 -| Electricity | 1 | 8 | 805.49 | 9.93 | 10.41 | 10.48 | 10.91 -| Traffic | 1 | 1 | 96.72 | 10.34 | 10.53 | 11.99 | 12.13 -| Traffic | 1 | 2 | 192.93 | 10.37 | 10.80 | 11.97 | 12.12 -| Traffic | 1 | 4 | 379.00 | 10.55 | 10.88 | 11.09 | 11.96 -| Traffic | 1 | 8 | 859.69 | 9.30 | 10.58 | 10.65 | 11.28 +| Electricity | 1 | 1 | 171.68 | 5.82 | 5.99 | 6.17 | 7.00 +| Electricity | 1 | 2 | 318.92 | 6.27 | 6.43 | 6.60 | 7.51 +| Electricity | 1 | 4 | 684.79 | 5.84 | 6.02 | 6.08 | 6.47 +| Electricity | 1 | 8 | 1275.54 | 6.27 | 7.31 | 7.36 | 7.51 +| Traffic | 1 | 1 | 183.39 | 5.45 | 5.64 | 5.86 | 6.73 +| Traffic | 1 | 2 | 340.73 | 5.87 | 6.07 | 6.77 | 7.25 +| Traffic | 1 | 4 | 647.33 | 6.18 | 6.35 | 7.99 | 8.07 +| Traffic | 1 | 8 | 1364.39 | 5.86 | 6.07 | 6.40 | 7.31 ## Release notes The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to https://developer.nvidia.com/deep-learning-performance-training-inference. ### Changelog +March 2023 +- 23.01 Container Update +- Switch from NVIDIA Apex AMP and NVIDIA Apex FusedLayerNorm to Native PyTorch AMP and Native PyTorch LayerNorm +- Acceleration using NvFuser + February 2022 - 21.12 Container Update - Triton Inference Performance Numbers diff --git a/PyTorch/Forecasting/TFT/configuration.py b/PyTorch/Forecasting/TFT/configuration.py index b2e3ceb56..09b97f7ef 100644 --- a/PyTorch/Forecasting/TFT/configuration.py +++ b/PyTorch/Forecasting/TFT/configuration.py @@ -124,5 +124,5 @@ def __init__(self): CONFIGS = {'electricity': ElectricityConfig, - 'traffic': TrafficConfig, + 'traffic': TrafficConfig, } diff --git a/PyTorch/Forecasting/TFT/criterions.py b/PyTorch/Forecasting/TFT/criterions.py index 2f469f779..12de5be76 100644 --- a/PyTorch/Forecasting/TFT/criterions.py +++ b/PyTorch/Forecasting/TFT/criterions.py @@ -15,6 +15,7 @@ import torch import torch.nn as nn import torch.nn.functional as F +import numpy as np class QuantileLoss(nn.Module): def __init__(self, config): @@ -26,3 +27,11 @@ def forward(self, predictions, targets): ql = (1-self.q)*F.relu(diff) + self.q*F.relu(-diff) losses = ql.view(-1, ql.shape[-1]).mean(0) return losses + +def qrisk(pred, tgt, quantiles): + diff = pred - tgt + ql = (1-quantiles)*np.clip(diff,0, float('inf')) + quantiles*np.clip(-diff,0, float('inf')) + losses = ql.reshape(-1, ql.shape[-1]) + normalizer = np.abs(tgt).mean() + risk = 2 * losses / normalizer + return risk.mean(0) diff --git a/PyTorch/Forecasting/TFT/data_utils.py b/PyTorch/Forecasting/TFT/data_utils.py index b851f1854..ce6c4f6ed 100644 --- a/PyTorch/Forecasting/TFT/data_utils.py +++ b/PyTorch/Forecasting/TFT/data_utils.py @@ -41,7 +41,8 @@ from bisect import bisect import torch -from torch.utils.data import Dataset,IterableDataset,DataLoader +from torch.utils.data import Dataset, IterableDataset, DataLoader, DistributedSampler, RandomSampler +from torch.utils.data.dataloader import default_collate class DataTypes(enum.IntEnum): """Defines numerical types of each column.""" @@ -401,6 +402,51 @@ def sample_data(dataset, num_samples): else: return torch.utils.data.Subset(dataset, np.random.choice(np.arange(len(dataset)), size=num_samples, replace=False)) +def load_dataset(args, config, collate_fn=default_collate): + from utils import print_once + train_split = TFTBinaryDataset(os.path.join(args.data_path, 'train.bin'), config) + train_split = sample_data(train_split, args.sample_data[0]) + if args.distributed_world_size > 1: + data_sampler = DistributedSampler(train_split, args.distributed_world_size, args.distributed_rank, seed=args.seed + args.distributed_rank, drop_last=True) + else: + data_sampler = RandomSampler(train_split) + train_loader = DataLoader(train_split, + batch_size=args.batch_size, + num_workers=4, + sampler=data_sampler, + collate_fn=collate_fn, + pin_memory=True) + + valid_split = TFTBinaryDataset(os.path.join(args.data_path, 'valid.bin'), config) + valid_split = sample_data(valid_split, args.sample_data[1]) + if args.distributed_world_size > 1: + data_sampler = DistributedSampler(valid_split, args.distributed_world_size, args.distributed_rank, shuffle=False, drop_last=False) + else: + data_sampler = None + valid_loader = DataLoader(valid_split, + batch_size=args.batch_size, + sampler=data_sampler, + num_workers=4, + collate_fn=collate_fn, + pin_memory=True) + + test_split = TFTBinaryDataset(os.path.join(args.data_path, 'test.bin'), config) + if args.distributed_world_size > 1: + data_sampler = DistributedSampler(test_split, args.distributed_world_size, args.distributed_rank, shuffle=False, drop_last=False) + else: + data_sampler = None + test_loader = DataLoader(test_split, + batch_size=args.batch_size, + sampler=data_sampler, + num_workers=4, + collate_fn=collate_fn, + pin_memory=True) + + print_once(f'Train split length: {len(train_split)}') + print_once(f'Valid split length: {len(valid_split)}') + print_once(f'Test split length: {len(test_split)}') + + return train_loader, valid_loader, test_loader def standarize_electricity(path): """Code taken from https://github.com/google-research/google-research/blob/master/tft/script_download_data.py""" @@ -574,4 +620,3 @@ def read_matrix(filename): flat_df.to_csv(os.path.join(path, 'standarized.csv')) - diff --git a/PyTorch/Forecasting/TFT/inference.py b/PyTorch/Forecasting/TFT/inference.py index f1d3ab97f..7f60f5588 100644 --- a/PyTorch/Forecasting/TFT/inference.py +++ b/PyTorch/Forecasting/TFT/inference.py @@ -26,12 +26,12 @@ from configuration import ElectricityConfig from data_utils import TFTDataset from utils import PerformanceMeter -from criterions import QuantileLoss +from criterions import qrisk import dllogger from log_helper import setup_logger +from torch.cuda import amp def _unscale_per_id(config, values, ids, scalers): - values = values.cpu().numpy() num_horizons = config.example_length - config.encoder_length + 1 flat_values = pd.DataFrame( values, @@ -51,11 +51,9 @@ def _unscale_per_id(config, values, ids, scalers): flat_values = pd.concat(df_list, axis=0) flat_values = flat_values[[col for col in flat_values if not 'id' in col]] - flat_tensor = torch.from_numpy(flat_values.values) - return flat_tensor + return flat_values.values def _unscale(config, values, scaler): - values = values.cpu().numpy() num_horizons = config.example_length - config.encoder_length + 1 flat_values = pd.DataFrame( values, @@ -68,46 +66,46 @@ def _unscale(config, values, scaler): flat_values[col] = _t_col flat_values = flat_values[[col for col in flat_values if not 'id' in col]] - flat_tensor = torch.from_numpy(flat_values.values) - return flat_tensor + return flat_values.values def predict(args, config, model, data_loader, scalers, cat_encodings, extend_targets=False): model.eval() predictions = [] targets = [] ids = [] - perf_meter = PerformanceMeter() + perf_meter = PerformanceMeter(benchmark_mode=not args.disable_benchmark) n_workers = args.distributed_world_size if hasattr(args, 'distributed_world_size') else 1 - - for step, batch in enumerate(data_loader): - perf_meter.reset_current_lap() - with torch.no_grad(): - batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in batch.items()} - ids.append(batch['id'][:,0,:]) - targets.append(batch['target']) - predictions.append(model(batch).float()) - - perf_meter.update(args.batch_size * n_workers, - exclude_from_total=step in [0, len(data_loader)-1]) - - targets = torch.cat(targets, dim=0) + + with torch.jit.fuser("fuser2"): + for step, batch in enumerate(data_loader): + perf_meter.reset_current_lap() + with torch.no_grad(): + batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in batch.items()} + ids.append(batch['id'][:,0,:]) + targets.append(batch['target']) + predictions.append(model(batch).float()) + + perf_meter.update(args.batch_size * n_workers, + exclude_from_total=step in [0, 1, 2, len(data_loader)-1]) + + targets = torch.cat(targets, dim=0).cpu().numpy() if not extend_targets: targets = targets[:,config.encoder_length:,:] - predictions = torch.cat(predictions, dim=0) + predictions = torch.cat(predictions, dim=0).cpu().numpy() if config.scale_per_id: ids = torch.cat(ids, dim=0).cpu().numpy() - unscaled_predictions = torch.stack( + unscaled_predictions = np.stack( [_unscale_per_id(config, predictions[:,:,i], ids, scalers) for i in range(len(config.quantiles))], - dim=-1) - unscaled_targets = _unscale_per_id(config, targets[:,:,0], ids, scalers).unsqueeze(-1) + axis=-1) + unscaled_targets = np.expand_dims(_unscale_per_id(config, targets[:,:,0], ids, scalers), axis=-1) else: ids = None - unscaled_predictions = torch.stack( + unscaled_predictions = np.stack( [_unscale(config, predictions[:,:,i], scalers['']) for i in range(len(config.quantiles))], - dim=-1) - unscaled_targets = _unscale(config, targets[:,:,0], scalers['']).unsqueeze(-1) + axis=-1) + unscaled_targets = np.expand_dims(_unscale(config, targets[:,:,0], scalers['']), axis=-1) return unscaled_predictions, unscaled_targets, ids, perf_meter @@ -173,9 +171,11 @@ def inference(args, config, model, data_loader, scalers, cat_encodings): os.makedirs(os.path.join(args.results, 'predictions', str(key)), exist_ok=True) df.to_csv(os.path.join(args.results, 'predictions', str(key), q+'.csv')) - losses = QuantileLoss(config)(unscaled_predictions, unscaled_targets) - normalizer = unscaled_targets.abs().mean() - q_risk = 2 * losses / normalizer + #losses = QuantileLoss(config)(torch.from_numpy(unscaled_predictions).contiguous(), + # torch.from_numpy(unscaled_targets).contiguous()).numpy() + #normalizer = np.mean(np.abs(unscaled_targets)) + #q_risk = 2 * losses / normalizer + risk = qrisk(unscaled_predictions, unscaled_targets, np.array(config.quantiles)) perf_dict = { 'throughput': perf_meter.avg, @@ -186,7 +186,7 @@ def inference(args, config, model, data_loader, scalers, cat_encodings): 'total_infernece_time': perf_meter.total_time, } - return q_risk, perf_dict + return risk, perf_dict def main(args): @@ -215,7 +215,7 @@ def main(args): quantiles = {'test_p10': quantiles[0].item(), 'test_p50': quantiles[1].item(), 'test_p90': quantiles[2].item(), 'sum':sum(quantiles).item()} finish_log = {**quantiles, **perf_dict} dllogger.log(step=(), data=finish_log, verbosity=1) - print('Test q-risk: P10 {} | P50 {} | P90 {}'.format(*quantiles)) + print('Test q-risk: P10 {test_p10} | P50 {test_p50} | P90 {test_p90}'.format(**quantiles)) print('Latency:\n\tAverage {:.3f}s\n\tp90 {:.3f}s\n\tp95 {:.3f}s\n\tp99 {:.3f}s'.format( perf_dict['latency_avg'], perf_dict['latency_p90'], perf_dict['latency_p95'], perf_dict['latency_p99'])) @@ -235,5 +235,6 @@ def main(args): parser.add_argument('--save_predictions', action='http://github.com/store_true') parser.add_argument('--results', type=str, default='/results') parser.add_argument('--log_file', type=str, default='dllogger.json') + parser.add_argument("--disable_benchmark", action='http://github.com/store_true', help='Disable benchmarking mode') ARGS = parser.parse_args() main(ARGS) diff --git a/PyTorch/Forecasting/TFT/modeling.py b/PyTorch/Forecasting/TFT/modeling.py old mode 100644 new mode 100755 index a0300ea99..d5c214d5c --- a/PyTorch/Forecasting/TFT/modeling.py +++ b/PyTorch/Forecasting/TFT/modeling.py @@ -17,12 +17,11 @@ import torch.nn.functional as F from torch import Tensor +from torch.nn.parameter import UninitializedParameter from typing import Dict, Tuple, Optional, List -if os.environ.get("TFT_SCRIPTING", False): - from torch.nn import LayerNorm -else: - from apex.normalization.fused_layer_norm import FusedLayerNorm as LayerNorm +MAKE_CONVERT_COMPATIBLE = os.environ.get("TFT_SCRIPTING", None) is not None +from torch.nn import LayerNorm class MaybeLayerNorm(nn.Module): def __init__(self, output_size, hidden_size, eps): @@ -46,21 +45,20 @@ def forward(self, x: Tensor) -> Tensor: x = F.glu(x) return x - class GRN(nn.Module): def __init__(self, input_size, - hidden_size, + hidden_size, output_size=None, context_hidden_size=None, - dropout=0): + dropout=0.0,): super().__init__() - - self.layer_norm = MaybeLayerNorm(output_size, hidden_size, eps=1e-3) self.lin_a = nn.Linear(input_size, hidden_size) if context_hidden_size is not None: self.lin_c = nn.Linear(context_hidden_size, hidden_size, bias=False) + else: + self.lin_c = nn.Identity() self.lin_i = nn.Linear(hidden_size, hidden_size) self.glu = GLU(hidden_size, output_size if output_size else hidden_size) self.dropout = nn.Dropout(dropout) @@ -74,13 +72,28 @@ def forward(self, a: Tensor, c: Optional[Tensor] = None): x = self.lin_i(x) x = self.dropout(x) x = self.glu(x) - y = a if not self.out_proj else self.out_proj(a) + y = a if self.out_proj is None else self.out_proj(a) x = x + y - x = self.layer_norm(x) - return x + return self.layer_norm(x) + + +# @torch.jit.script #Currently broken with autocast +def fused_pointwise_linear_v1(x, a, b): + out = torch.mul(x.unsqueeze(-1), a) + out = out + b + return out + +@torch.jit.script +def fused_pointwise_linear_v2(x, a, b): + out = x.unsqueeze(3) * a + out = out + b + return out + class TFTEmbedding(nn.Module): - def __init__(self, config): + def __init__(self, config, initialize_cont_params=True): + # initialize_cont_params=False prevents form initializing parameters inside this class + # so they can be lazily initialized in LazyEmbedding module super().__init__() self.s_cat_inp_lens = config.static_categorical_inp_lens self.t_cat_k_inp_lens = config.temporal_known_categorical_inp_lens @@ -108,23 +121,43 @@ def __init__(self, config): self.t_cat_o_embed = nn.ModuleList([ nn.Embedding(n, self.hidden_size) for n in self.t_cat_o_inp_lens]) if self.t_cat_o_inp_lens else None - self.s_cont_embedding_vectors = nn.Parameter(torch.Tensor(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None - self.t_cont_k_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None - self.t_cont_o_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None - self.t_tgt_embedding_vectors = nn.Parameter(torch.Tensor(self.t_tgt_size, self.hidden_size)) + if initialize_cont_params: + self.s_cont_embedding_vectors = nn.Parameter(torch.Tensor(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None + self.t_cont_k_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None + self.t_cont_o_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None + self.t_tgt_embedding_vectors = nn.Parameter(torch.Tensor(self.t_tgt_size, self.hidden_size)) - self.s_cont_embedding_bias = nn.Parameter(torch.zeros(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None - self.t_cont_k_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None - self.t_cont_o_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None - self.t_tgt_embedding_bias = nn.Parameter(torch.zeros(self.t_tgt_size, self.hidden_size)) + self.s_cont_embedding_bias = nn.Parameter(torch.zeros(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None + self.t_cont_k_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None + self.t_cont_o_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None + self.t_tgt_embedding_bias = nn.Parameter(torch.zeros(self.t_tgt_size, self.hidden_size)) + self.reset_parameters() + + + def reset_parameters(self): if self.s_cont_embedding_vectors is not None: torch.nn.init.xavier_normal_(self.s_cont_embedding_vectors) + torch.nn.init.zeros_(self.s_cont_embedding_bias) if self.t_cont_k_embedding_vectors is not None: torch.nn.init.xavier_normal_(self.t_cont_k_embedding_vectors) + torch.nn.init.zeros_(self.t_cont_k_embedding_bias) if self.t_cont_o_embedding_vectors is not None: torch.nn.init.xavier_normal_(self.t_cont_o_embedding_vectors) - torch.nn.init.xavier_normal_(self.t_tgt_embedding_vectors) + torch.nn.init.zeros_(self.t_cont_o_embedding_bias) + if self.t_tgt_embedding_vectors is not None: + torch.nn.init.xavier_normal_(self.t_tgt_embedding_vectors) + torch.nn.init.zeros_(self.t_tgt_embedding_bias) + if self.s_cat_embed is not None: + for module in self.s_cat_embed: + module.reset_parameters() + if self.t_cat_k_embed is not None: + for module in self.t_cat_k_embed: + module.reset_parameters() + if self.t_cat_o_embed is not None: + for module in self.t_cat_o_embed: + module.reset_parameters() + def _apply_embedding(self, cat: Optional[Tensor], @@ -138,8 +171,11 @@ def _apply_embedding(self, #the line below is equivalent to following einsums #e_cont = torch.einsum('btf,fh->bthf', cont, cont_emb) #e_cont = torch.einsum('bf,fh->bhf', cont, cont_emb) - e_cont = torch.mul(cont.unsqueeze(-1), cont_emb) - e_cont = e_cont + cont_bias + if MAKE_CONVERT_COMPATIBLE: + e_cont = torch.mul(cont.unsqueeze(-1), cont_emb) + e_cont = e_cont + cont_bias + else: + e_cont = fused_pointwise_linear_v1(cont, cont_emb, cont_bias) else: e_cont = None @@ -185,11 +221,68 @@ def forward(self, x: Dict[str, Tensor]): # Temporal observed targets # t_observed_tgt = torch.einsum('btf,fh->btfh', t_tgt_obs, self.t_tgt_embedding_vectors) - t_observed_tgt = torch.matmul(t_tgt_obs.unsqueeze(3).unsqueeze(4), self.t_tgt_embedding_vectors.unsqueeze(1)).squeeze(3) - t_observed_tgt = t_observed_tgt + self.t_tgt_embedding_bias + if MAKE_CONVERT_COMPATIBLE: + t_observed_tgt = torch.matmul(t_tgt_obs.unsqueeze(3).unsqueeze(4), self.t_tgt_embedding_vectors.unsqueeze(1)).squeeze(3) + t_observed_tgt = t_observed_tgt + self.t_tgt_embedding_bias + else: + t_observed_tgt = fused_pointwise_linear_v2(t_tgt_obs, self.t_tgt_embedding_vectors, self.t_tgt_embedding_bias) return s_inp, t_known_inp, t_observed_inp, t_observed_tgt +class LazyEmbedding(nn.modules.lazy.LazyModuleMixin, TFTEmbedding): + cls_to_become = TFTEmbedding + + def __init__(self, config): + super().__init__(config, initialize_cont_params=False) + + if config.static_continuous_inp_size: + self.s_cont_embedding_vectors = UninitializedParameter() + self.s_cont_embedding_bias = UninitializedParameter() + else: + self.s_cont_embedding_vectors = None + self.s_cont_embedding_bias = None + + if config.temporal_known_continuous_inp_size: + self.t_cont_k_embedding_vectors = UninitializedParameter() + self.t_cont_k_embedding_bias = UninitializedParameter() + else: + self.t_cont_k_embedding_vectors = None + self.t_cont_k_embedding_bias = None + + if config.temporal_observed_continuous_inp_size: + self.t_cont_o_embedding_vectors = UninitializedParameter() + self.t_cont_o_embedding_bias = UninitializedParameter() + else: + self.t_cont_o_embedding_vectors = None + self.t_cont_o_embedding_bias = None + + self.t_tgt_embedding_vectors = UninitializedParameter() + self.t_tgt_embedding_bias = UninitializedParameter() + + def initialize_parameters(self, x): + if self.has_uninitialized_params(): + s_cont_inp = x.get('s_cont', None) + t_cont_k_inp = x.get('k_cont', None) + t_cont_o_inp = x.get('o_cont', None) + t_tgt_obs = x['target'] # Has to be present + + if s_cont_inp is not None: + self.s_cont_embedding_vectors.materialize((s_cont_inp.shape[-1], self.hidden_size)) + self.s_cont_embedding_bias.materialize((s_cont_inp.shape[-1], self.hidden_size)) + + if t_cont_k_inp is not None: + self.t_cont_k_embedding_vectors.materialize((t_cont_k_inp.shape[-1], self.hidden_size)) + self.t_cont_k_embedding_bias.materialize((t_cont_k_inp.shape[-1], self.hidden_size)) + + if t_cont_o_inp is not None: + self.t_cont_o_embedding_vectors.materialize((t_cont_o_inp.shape[-1], self.hidden_size)) + self.t_cont_o_embedding_bias.materialize((t_cont_o_inp.shape[-1], self.hidden_size)) + + self.t_tgt_embedding_vectors.materialize((t_tgt_obs.shape[-1], self.hidden_size)) + self.t_tgt_embedding_bias.materialize((t_tgt_obs.shape[-1], self.hidden_size)) + + self.reset_parameters() + class VariableSelectionNetwork(nn.Module): def __init__(self, config, num_inputs): super().__init__() @@ -197,7 +290,7 @@ def __init__(self, config, num_inputs): self.var_grns = nn.ModuleList([GRN(config.hidden_size, config.hidden_size, dropout=config.dropout) for _ in range(num_inputs)]) def forward(self, x: Tensor, context: Optional[Tensor] = None): - Xi = x.reshape(*x.shape[:-2], -1) + Xi = torch.flatten(x, start_dim=-2) grn_outputs = self.joint_grn(Xi, c=context) sparse_weights = F.softmax(grn_outputs, dim=-1) transformed_embed_list = [m(x[...,i,:]) for i, m in enumerate(self.var_grns)] @@ -223,7 +316,7 @@ def forward(self, x: Tensor) -> Tuple[Tensor, Tensor, Tensor, Tensor]: # enrichment context # state_c context # state_h context - cs, ce, ch, cc = tuple(m(variable_ctx) for m in self.context_grns) + cs, ce, ch, cc = [m(variable_ctx) for m in self.context_grns] return cs, ce, ch, cc @@ -241,7 +334,7 @@ def __init__(self, config): self.scale = self.d_head**-0.5 self.register_buffer("_mask", torch.triu(torch.full((config.example_length, config.example_length), float('-inf')), 1).unsqueeze(0)) - def forward(self, x: Tensor, mask_future_timesteps: bool = True) -> Tuple[Tensor, Tensor]: + def forward(self, x: Tensor) -> Tuple[Tensor, Tensor]: bs, t, h_size = x.shape qkv = self.qkv_linears(x) q, k, v = qkv.split((self.n_head * self.d_head, self.n_head * self.d_head, self.d_head), dim=-1) @@ -253,8 +346,7 @@ def forward(self, x: Tensor, mask_future_timesteps: bool = True) -> Tuple[Tensor attn_score = torch.matmul(q.permute((0, 2, 1, 3)), k.permute((0, 2, 3, 1))) attn_score.mul_(self.scale) - if mask_future_timesteps: - attn_score = attn_score + self._mask + attn_score = attn_score + self._mask attn_prob = F.softmax(attn_score, dim=3) attn_prob = self.attn_dropout(attn_prob) @@ -265,26 +357,14 @@ def forward(self, x: Tensor, mask_future_timesteps: bool = True) -> Tuple[Tensor out = self.out_proj(m_attn_vec) out = self.out_dropout(out) - return out, attn_vec + return out, attn_prob - - -class TemporalFusionTransformer(nn.Module): - """ - Implementation of https://arxiv.org/abs/1912.09363 - """ +class TFTBack(nn.Module): def __init__(self, config): super().__init__() - if hasattr(config, 'model'): - config = config.model - - self.encoder_length = config.encoder_length #this determines from how distant past we want to use data from - - self.embedding = TFTEmbedding(config) - self.static_encoder = StaticCovariateEncoder(config) - - self.history_vsn = VariableSelectionNetwork(config, config.num_historic_vars) + self.encoder_length = config.encoder_length + self.history_vsn = VariableSelectionNetwork(config, config.num_historic_vars) self.history_encoder = nn.LSTM(config.hidden_size, config.hidden_size, batch_first=True) self.future_vsn = VariableSelectionNetwork(config, config.num_future_vars) self.future_encoder = nn.LSTM(config.hidden_size, config.hidden_size, batch_first=True) @@ -309,28 +389,13 @@ def __init__(self, config): self.decoder_ln = LayerNorm(config.hidden_size, eps=1e-3) self.quantile_proj = nn.Linear(config.hidden_size, len(config.quantiles)) - - def forward(self, x: Dict[str, Tensor]) -> Tensor: - s_inp, t_known_inp, t_observed_inp, t_observed_tgt = self.embedding(x) - - # Static context - cs, ce, ch, cc = self.static_encoder(s_inp) - ch, cc = ch.unsqueeze(0), cc.unsqueeze(0) #lstm initial states - - # Temporal input - _historical_inputs = [t_known_inp[:,:self.encoder_length,:], t_observed_tgt[:,:self.encoder_length,:]] - if t_observed_inp is not None: - _historical_inputs.insert(0,t_observed_inp[:,:self.encoder_length,:]) - - historical_inputs = torch.cat(_historical_inputs, dim=-2) - future_inputs = t_known_inp[:, self.encoder_length:] - - # Encoders + + def forward(self, historical_inputs, cs, ch, cc, ce, future_inputs): historical_features, _ = self.history_vsn(historical_inputs, cs) history, state = self.history_encoder(historical_features, (ch, cc)) future_features, _ = self.future_vsn(future_inputs, cs) future, _ = self.future_encoder(future_features, state) - torch.cuda.synchronize() # this call gives perf boost for unknown reasons + torch.cuda.synchronize() # skip connection input_embedding = torch.cat([historical_features, future_features], dim=1) @@ -343,7 +408,7 @@ def forward(self, x: Dict[str, Tensor]) -> Tensor: enriched = self.enrichment_grn(temporal_features, c=ce) # Temporal self attention - x, _ = self.attention(enriched, mask_future_timesteps=True) + x, _ = self.attention(enriched) # Don't compute hictorical quantiles x = x[:, self.encoder_length:, :] @@ -365,3 +430,39 @@ def forward(self, x: Dict[str, Tensor]) -> Tensor: out = self.quantile_proj(x) return out + + +class TemporalFusionTransformer(nn.Module): + """ + Implementation of https://arxiv.org/abs/1912.09363 + """ + def __init__(self, config): + super().__init__() + + if hasattr(config, 'model'): + config = config.model + + self.encoder_length = config.encoder_length #this determines from how distant past we want to use data from + + self.embedding = LazyEmbedding(config) + self.static_encoder = StaticCovariateEncoder(config) + if MAKE_CONVERT_COMPATIBLE: + self.TFTpart2 = TFTBack(config) + else: + self.TFTpart2 = torch.jit.script(TFTBack(config)) + + def forward(self, x: Dict[str, Tensor]) -> Tensor: + s_inp, t_known_inp, t_observed_inp, t_observed_tgt = self.embedding(x) + + # Static context + cs, ce, ch, cc = self.static_encoder(s_inp) + ch, cc = ch.unsqueeze(0), cc.unsqueeze(0) #lstm initial states + + # Temporal input + _historical_inputs = [t_known_inp[:,:self.encoder_length,:], t_observed_tgt[:,:self.encoder_length,:]] + if t_observed_inp is not None: + _historical_inputs.insert(0,t_observed_inp[:,:self.encoder_length,:]) + + historical_inputs = torch.cat(_historical_inputs, dim=-2) + future_inputs = t_known_inp[:, self.encoder_length:] + return self.TFTpart2(historical_inputs, cs, ch, cc, ce, future_inputs) \ No newline at end of file diff --git a/PyTorch/Forecasting/TFT/tft_torchhub.py b/PyTorch/Forecasting/TFT/tft_torchhub.py new file mode 100644 index 000000000..88888ed2d --- /dev/null +++ b/PyTorch/Forecasting/TFT/tft_torchhub.py @@ -0,0 +1,95 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys +import urllib.request +from zipfile import ZipFile +import torch +from torch.utils.data import DataLoader +NGC_CHECKPOINT_URLS = {} +NGC_CHECKPOINT_URLS["electricity"] = "https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-electricity/versions/22.11.0_amp/zip" +NGC_CHECKPOINT_URLS["traffic"] = "https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-traffic/versions/22.11.0_amp/zip" +def _download_checkpoint(checkpoint, force_reload): + model_dir = os.path.join(torch.hub._get_torch_home(), 'checkpoints') + if not os.path.exists(model_dir): + os.makedirs(model_dir) + ckpt_file = os.path.join(model_dir, os.path.basename(checkpoint)) + if not os.path.exists(ckpt_file) or force_reload: + sys.stderr.write('Downloading checkpoint from {}\n'.format(checkpoint)) + urllib.request.urlretrieve(checkpoint, ckpt_file) + with ZipFile(ckpt_file, "r") as zf: + zf.extractall(path=model_dir) + return os.path.join(model_dir, "checkpoint.pt") + +def nvidia_tft(pretrained=True, **kwargs): + from .modeling import TemporalFusionTransformer + """Constructs a TFT model. + For detailed information on model input and output, training recipies, inference and performance + visit: github.com/NVIDIA/DeepLearningExamples and/or ngc.nvidia.com + Args (type[, default value]): + pretrained (bool, True): If True, returns a pretrained model. + dataset (str, 'electricity'): loads selected model type electricity or traffic. Defaults to electricity + """ + ds_type = kwargs.get("dataset", "electricity") + ckpt = _download_checkpoint(NGC_CHECKPOINT_URLS[ds_type], True) + state_dict = torch.load(ckpt) + config = state_dict['config'] + + model = TemporalFusionTransformer(config) + if pretrained: + model.load_state_dict(state_dict['model']) + model.eval() + return model + +def nvidia_tft_data_utils(**kwargs): + + from .data_utils import TFTDataset + from .configuration import ElectricityConfig + class Processing: + @staticmethod + def download_data(path): + if not os.path.exists(os.path.join(path, "raw")): + os.makedirs(os.path.join(path, "raw"), exist_ok=True) + dataset_url = "https://archive.ics.uci.edu/ml/machine-learning-databases/00321/LD2011_2014.txt.zip" + ckpt_file = os.path.join(path, "raw/electricity.zip") + if not os.path.exists(ckpt_file): + sys.stderr.write('Downloading checkpoint from {}\n'.format(dataset_url)) + urllib.request.urlretrieve(dataset_url, ckpt_file) + with ZipFile(ckpt_file, "r") as zf: + zf.extractall(path=os.path.join(path, "raw/electricity/")) + + @staticmethod + def preprocess(path): + config = ElectricityConfig() + if not os.path.exists(os.path.join(path, "processed")): + os.makedirs(os.path.join(path, "processed"), exist_ok=True) + from data_utils import standarize_electricity as standarize + from data_utils import preprocess + standarize(os.path.join(path, "raw/electricity")) + preprocess(os.path.join(path, "raw/electricity/standarized.csv"), os.path.join(path, "processed/electricity_bin/"), config) + + + @staticmethod + def get_batch(path): + config = ElectricityConfig() + test_split = TFTDataset(os.path.join(path, "processed/electricity_bin/", "test.csv"), config) + data_loader = DataLoader(test_split, batch_size=16, num_workers=0) + for i, batch in enumerate(data_loader): + if i == 40: + break + return batch + + return Processing() + diff --git a/PyTorch/Forecasting/TFT/train.py b/PyTorch/Forecasting/TFT/train.py old mode 100644 new mode 100755 index 37396f80b..cfdba7102 --- a/PyTorch/Forecasting/TFT/train.py +++ b/PyTorch/Forecasting/TFT/train.py @@ -23,10 +23,9 @@ import torch.nn.functional as F import torch.distributed as dist from torch.utils.data import DataLoader, DistributedSampler, RandomSampler -from apex import amp from apex.optimizers import FusedAdam -#from torch.nn.parallel import DistributedDataParallel as DDP -from apex.parallel import DistributedDataParallel as DDP +from torch.nn.parallel import DistributedDataParallel as DDP +from torch.cuda import amp import numpy as np @@ -34,48 +33,14 @@ from modeling import TemporalFusionTransformer from configuration import CONFIGS -from data_utils import TFTBinaryDataset, sample_data +from data_utils import load_dataset from log_helper import setup_logger from criterions import QuantileLoss from inference import predict -from utils import PerformanceMeter +from utils import PerformanceMeter, print_once import gpu_affinity from ema import ModelEma -def load_dataset(args, config): - train_split = TFTBinaryDataset(os.path.join(args.data_path, 'train.bin'), config) - train_split = sample_data(train_split, args.sample_data[0]) - if args.distributed_world_size > 1: - data_sampler = DistributedSampler(train_split, args.distributed_world_size, args.distributed_rank, seed=args.seed + args.distributed_rank, drop_last=True) - else: - data_sampler = RandomSampler(train_split) - train_loader = DataLoader(train_split, batch_size=args.batch_size, num_workers=4, sampler=data_sampler, pin_memory=True) - - valid_split = TFTBinaryDataset(os.path.join(args.data_path, 'valid.bin'), config) - valid_split = sample_data(valid_split, args.sample_data[1]) - if args.distributed_world_size > 1: - data_sampler = DistributedSampler(valid_split, args.distributed_world_size, args.distributed_rank, shuffle=False, drop_last=False) - else: - data_sampler = None - valid_loader = DataLoader(valid_split, batch_size=args.batch_size, sampler=data_sampler, num_workers=4, pin_memory=True) - - test_split = TFTBinaryDataset(os.path.join(args.data_path, 'test.bin'), config) - if args.distributed_world_size > 1: - data_sampler = DistributedSampler(test_split, args.distributed_world_size, args.distributed_rank, shuffle=False, drop_last=False) - else: - data_sampler = None - test_loader = DataLoader(test_split, batch_size=args.batch_size, sampler=data_sampler, num_workers=4, pin_memory=True) - - print_once(f'Train split length: {len(train_split)}') - print_once(f'Valid split length: {len(valid_split)}') - print_once(f'Test split length: {len(test_split)}') - - return train_loader, valid_loader, test_loader - -def print_once(*args, **kwargs): - if not dist.is_initialized() or dist.get_rank() == 0: - print(*args, **kwargs) - def main(args): ### INIT DISTRIBUTED @@ -113,23 +78,28 @@ def main(args): dllogger.log(step='HPARAMS', data={**vars(args), **vars(config)}, verbosity=1) + train_loader, valid_loader, test_loader = load_dataset(args, config) + model = TemporalFusionTransformer(config).cuda() if args.ema_decay: model_ema = ModelEma(model, decay=args.ema_decay) - print_once('Model params: {}'.format(sum(p.numel() for p in model.parameters()))) + # Run dummy iteration to initialize lazy modules + dummy_batch = next(iter(train_loader)) + dummy_batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in dummy_batch.items()} + model(dummy_batch) + criterion = QuantileLoss(config).cuda() optimizer = FusedAdam(model.parameters(), lr=args.lr) - if args.use_amp: - model, optimizer = amp.initialize(model, optimizer, opt_level="O2", loss_scale="dynamic") if args.distributed_world_size > 1: - #model = DDP(model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True) - model = DDP(model) + model = DDP(model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True) - train_loader, valid_loader, test_loader = load_dataset(args, config) + print_once('Model params: {}'.format(sum(p.numel() for p in model.parameters()))) global_step = 0 - perf_meter = PerformanceMeter() + perf_meter = PerformanceMeter(benchmark_mode=not args.disable_benchmark) + if args.use_amp: + scaler = amp.GradScaler(init_scale=32768.0) for epoch in range(args.epochs): start = time.time() @@ -139,20 +109,28 @@ def main(args): for local_step, batch in enumerate(train_loader): perf_meter.reset_current_lap() batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in batch.items()} - predictions = model(batch) - targets = batch['target'][:,config.encoder_length:,:] - p_losses = criterion(predictions, targets) - loss = p_losses.sum() - + with torch.jit.fuser("fuser2"), amp.autocast(enabled=args.use_amp): + predictions = model(batch) + targets = batch['target'][:,config.encoder_length:,:] + p_losses = criterion(predictions, targets) + loss = p_losses.sum() + if global_step == 0 and args.ema_decay: + model_ema(batch) if args.use_amp: - with amp.scale_loss(loss, optimizer) as scaled_loss: - scaled_loss.backward() + scaler.scale(loss).backward() + else: loss.backward() if not args.grad_accumulation or (global_step+1) % args.grad_accumulation == 0: + if args.use_amp: + scaler.unscale_(optimizer) if args.clip_grad: torch.nn.utils.clip_grad_norm_(model.parameters(), args.clip_grad) - optimizer.step() + if args.use_amp: + scaler.step(optimizer) + scaler.update() + else: + optimizer.step() optimizer.zero_grad() if args.ema_decay: model_ema.update(model) @@ -164,7 +142,7 @@ def main(args): torch.cuda.synchronize() ips = perf_meter.update(args.batch_size * args.distributed_world_size, - exclude_from_total=local_step in [0, len(train_loader)-1]) + exclude_from_total=local_step in [0, 1, 2, len(train_loader)-1]) log_dict = {'P10':p_losses[0].item(), 'P50':p_losses[1].item(), 'P90':p_losses[2].item(), 'loss': loss.item(), 'items/s':ips} dllogger.log(step=global_step, data=log_dict, verbosity=1) @@ -188,6 +166,10 @@ def main(args): cat_encodings = pickle.load(open(os.path.join(args.data_path,'cat_encodings.bin'), 'rb')) unscaled_predictions, unscaled_targets, _, _ = predict(args, config, model, test_loader, tgt_scalers, cat_encodings) + + unscaled_predictions = torch.from_numpy(unscaled_predictions).contiguous() + unscaled_targets = torch.from_numpy(unscaled_targets).contiguous() + losses = QuantileLoss(config)(unscaled_predictions, unscaled_targets) normalizer = unscaled_targets.abs().mean() quantiles = 2 * losses / normalizer @@ -209,9 +191,10 @@ def validate(args, config, model, criterion, dataloader, global_step): model.eval() losses = [] + torch.cuda.synchronize() validation_start = time.time() for batch in dataloader: - with torch.no_grad(): + with torch.jit.fuser("fuser2"), amp.autocast(enabled=args.use_amp), torch.no_grad(): batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in batch.items()} predictions = model(batch) targets = batch['target'][:,config.encoder_length:,:] @@ -219,6 +202,7 @@ def validate(args, config, model, criterion, dataloader, global_step): bs = next(t for t in batch.values() if t is not None).shape[0] losses.append((p_losses, bs)) + torch.cuda.synchronize() validation_end = time.time() p_losses = sum([l[0]*l[1] for l in losses])/sum([l[1] for l in losses]) #takes into accunt that the last batch is not full @@ -280,6 +264,7 @@ def validate(args, config, model, criterion, dataloader, global_step): 'disabled'], help='type of CPU affinity') parser.add_argument("--ema_decay", type=float, default=0.0, help='Use exponential moving average') + parser.add_argument("--disable_benchmark", action='http://github.com/store_true', help='Disable benchmarking mode') ARGS = parser.parse_args() diff --git a/PyTorch/Forecasting/TFT/triton/README.md b/PyTorch/Forecasting/TFT/triton/README.md index c548a9401..862c252ef 100644 --- a/PyTorch/Forecasting/TFT/triton/README.md +++ b/PyTorch/Forecasting/TFT/triton/README.md @@ -146,6 +146,9 @@ NVIDIA DGX A100 (1x A100 80GB): bash ./triton/runner/start_NVIDIA-DGX-A100-\(1x- NVIDIA T4: bash ./triton/runner/start_NVIDIA-T4.sh ``` +If one encounters an error like `the provided PTX was compiled with an unsupported toolchain`, follow the steps in +[Step by step deployment process](#step-by-step-deployment-process). + ## Performance The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to @@ -2077,7 +2080,7 @@ Please use the data download from the [Main QSG](https://github.com/NVIDIA/DeepL #### Prepare Checkpoint Please place a `checkpoint.pt` from TFT trained on electricity in `runner_workspace/checkpoints/electricity_bin/`. Note that the `electricity_bin` subdirectory may not be created yet. In addition one can download a zip archive of a trained checkpoint -[here](https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip) +[here](https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-electricity/versions/22.11.0_amp/zip) #### Setup Container Build and run a container that extends the NGC PyTorch container with the Triton Inference Server client libraries and dependencies. @@ -2242,7 +2245,7 @@ mkdir -p ${SHARED_DIR}/input_data python triton/prepare_input_data.py \ --input-data-dir ${SHARED_DIR}/input_data/ \ --dataset ${DATASETS_DIR}/${DATASET} \ - --checkpoint ${CHECKPOINT_DIR}/ \ + --checkpoint ${CHECKPOINT_DIR}/ ``` diff --git a/PyTorch/Forecasting/TFT/triton/deployment_toolkit/bermuda/pyt.py b/PyTorch/Forecasting/TFT/triton/deployment_toolkit/bermuda/pyt.py index 2d3e3a67c..0578f3d49 100644 --- a/PyTorch/Forecasting/TFT/triton/deployment_toolkit/bermuda/pyt.py +++ b/PyTorch/Forecasting/TFT/triton/deployment_toolkit/bermuda/pyt.py @@ -161,6 +161,8 @@ def load(self, model_path: Union[str, Path], **kwargs) -> Model: def _trace(self, model: Model, dataloader_fn) -> Model: device = get_model_device(model.handle) dummy_input = get_sample_input(dataloader_fn(), device) + # Run dummy forward to initialize lazy modules + model.handle(*dummy_input) traced_model = torch.jit.trace_module(model.handle, {"forward": dummy_input}) return Model(traced_model, precision=model.precision, inputs=model.inputs, outputs=model.outputs) @@ -213,6 +215,7 @@ def save(self, model: Model, model_path: Union[str, Path], dataloader_fn) -> Mod device = get_model_device(model.handle) dummy_input = get_sample_input(dataloader_fn(), device) + model.handle(*dummy_input) with torch.no_grad(): torch.onnx.export( model.handle, diff --git a/PyTorch/Forecasting/TFT/triton/requirements.txt b/PyTorch/Forecasting/TFT/triton/requirements.txt index a0af48ed3..30cbed0fa 100644 --- a/PyTorch/Forecasting/TFT/triton/requirements.txt +++ b/PyTorch/Forecasting/TFT/triton/requirements.txt @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -model_navigator[pyt] @ git+https://github.com/triton-inference-server/model_navigator.git@v0.2.5#egg=model_navigator +model_navigator[pyt] @ git+https://github.com/triton-inference-server/model_navigator.git@v0.2.7#egg=model_navigator natsort>=7.0.0 networkx==2.5 numpy @@ -21,3 +21,4 @@ pycuda>=2019.1.2 PyYAML>=5.2 tabulate>=0.8.7 tqdm>=4.44.1 +triton-model-analyzer==1.22.0 diff --git a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-A30.yaml b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-A30.yaml index b76b17bb8..372b640e5 100644 --- a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-A30.yaml +++ b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-A30.yaml @@ -1,8 +1,8 @@ checkpoints: - name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-electricity/versions/22.11.0_amp/zip - name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-traffic/versions/22.11.0_amp/zip configurations: - accelerator: none batch_size: @@ -112,7 +112,7 @@ configurations: triton_gpu_engine_count: 2 triton_max_queue_delay: 1 triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' +container_version: '22.11' datasets: - name: electricity_bin - name: traffic_bin diff --git a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml index b76b17bb8..372b640e5 100644 --- a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml +++ b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml @@ -1,8 +1,8 @@ checkpoints: - name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-electricity/versions/22.11.0_amp/zip - name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-traffic/versions/22.11.0_amp/zip configurations: - accelerator: none batch_size: @@ -112,7 +112,7 @@ configurations: triton_gpu_engine_count: 2 triton_max_queue_delay: 1 triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' +container_version: '22.11' datasets: - name: electricity_bin - name: traffic_bin diff --git a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml index b76b17bb8..372b640e5 100644 --- a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml +++ b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml @@ -1,8 +1,8 @@ checkpoints: - name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-electricity/versions/22.11.0_amp/zip - name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-traffic/versions/22.11.0_amp/zip configurations: - accelerator: none batch_size: @@ -112,7 +112,7 @@ configurations: triton_gpu_engine_count: 2 triton_max_queue_delay: 1 triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' +container_version: '22.11' datasets: - name: electricity_bin - name: traffic_bin diff --git a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-T4.yaml b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-T4.yaml index b76b17bb8..372b640e5 100644 --- a/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-T4.yaml +++ b/PyTorch/Forecasting/TFT/triton/runner/config_NVIDIA-T4.yaml @@ -1,8 +1,8 @@ checkpoints: - name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-electricity/versions/22.11.0_amp/zip - name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip + url: https://api.ngc.nvidia.com/v2/models/nvidia/dle/tft_base_pyt_ckpt_ds-traffic/versions/22.11.0_amp/zip configurations: - accelerator: none batch_size: @@ -112,7 +112,7 @@ configurations: triton_gpu_engine_count: 2 triton_max_queue_delay: 1 triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' +container_version: '22.11' datasets: - name: electricity_bin - name: traffic_bin diff --git a/PyTorch/Forecasting/TFT/triton/scripts/docker/triton_inference_server.sh b/PyTorch/Forecasting/TFT/triton/scripts/docker/triton_inference_server.sh index 242434d3a..481e6c9c2 100644 --- a/PyTorch/Forecasting/TFT/triton/scripts/docker/triton_inference_server.sh +++ b/PyTorch/Forecasting/TFT/triton/scripts/docker/triton_inference_server.sh @@ -41,7 +41,7 @@ docker run --rm -d \ --ulimit memlock=-1 \ --ulimit stack=67108864 \ --ipc=host \ - nvcr.io/nvidia/tritonserver:21.12-py3 tritonserver \ + nvcr.io/nvidia/tritonserver:22.11-py3 tritonserver \ --model-store=${MODEL_REPOSITORY_PATH} \ --strict-model-config=false \ --exit-on-error=true \ diff --git a/PyTorch/Forecasting/TFT/utils.py b/PyTorch/Forecasting/TFT/utils.py index fc993bd63..b85d361c1 100644 --- a/PyTorch/Forecasting/TFT/utils.py +++ b/PyTorch/Forecasting/TFT/utils.py @@ -13,12 +13,17 @@ # limitations under the License. import time +import torch.distributed as dist +import torch class PerformanceMeter(): - def __init__(self): + def __init__(self, benchmark_mode=True): + self.benchmark_mode = benchmark_mode self.reset() def reset(self): + if self.benchmark_mode: + torch.cuda.synchronize() self.avg = 0 self.count = 0 self.total_time = 0 @@ -26,6 +31,8 @@ def reset(self): self.intervals = [] def update(self, n, exclude_from_total=False): + if self.benchmark_mode: + torch.cuda.synchronize() delta = time.time() - self.last_update_time self.intervals.append(delta) if not exclude_from_total: @@ -37,6 +44,8 @@ def update(self, n, exclude_from_total=False): return n/delta def reset_current_lap(self): + if self.benchmark_mode: + torch.cuda.synchronize() self.last_update_time = time.time() def p(self, i): @@ -44,3 +53,7 @@ def p(self, i): idx = int(len(self.intervals) * i / 100) return sorted(self.intervals)[idx] +def print_once(*args, **kwargs): + if not dist.is_initialized() or dist.get_rank() == 0: + print(*args, **kwargs) + diff --git a/PyTorch/LanguageModeling/BART/Dockerfile b/PyTorch/LanguageModeling/BART/Dockerfile index c09b2e2ad..f49237538 100755 --- a/PyTorch/LanguageModeling/BART/Dockerfile +++ b/PyTorch/LanguageModeling/BART/Dockerfile @@ -14,55 +14,25 @@ # limitations under the License. # ============================================================================== -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:21.02-py3 - -###### -# Tokenizers is only available pre-built on x86 -# -FROM ${FROM_IMAGE_NAME} AS tokenizers_amd64 -WORKDIR /wheelhouse -RUN pip download tokenizers==0.8.0 - -FROM quay.io/pypa/manylinux2014_aarch64 as tokenizers_arm64 -ARG PYVER=38 -RUN yum install -y openssl-devel -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2020-05-14 -y -ENV PATH="/root/.cargo/bin:$PATH" -ENV PYBIN=/opt/python/cp${PYVER}-cp${PYVER}/bin -ENV PYTHON_SYS_EXECUTABLE="$PYBIN/python" -RUN git clone -b python-v0.8.0 https://github.com/huggingface/tokenizers.git /opt/tokenizers -WORKDIR /opt/tokenizers/bindings/python -RUN "${PYBIN}/pip" install setuptools-rust \ - && "${PYBIN}/python" setup.py bdist_wheel \ - && rm -rf build/* \ - && for whl in dist/*.whl; do \ - auditwheel repair "$whl" -w dist/; \ - done \ - && rm dist/*-linux_* \ - && mkdir -p /wheelhouse \ - && mv dist/*.whl /wheelhouse - -ARG TARGETARCH -FROM tokenizers_${TARGETARCH} AS tokenizers -# -##### - - +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.08-py3 FROM ${FROM_IMAGE_NAME} -RUN apt-get update && apt-get install -y pbzip2 -RUN --mount=from=tokenizers,source=/wheelhouse,target=/tmp/wheelhouse \ - pip install --no-cache-dir /tmp/wheelhouse/tokenizers*.whl -RUN pip install --no-cache-dir dataclasses gitpython rouge-score pynvml==8.0.4 \ - git+https://github.com/NVIDIA/dllogger pytorch-lightning==1.1.5 gdown sacrebleu - -RUN pip install tqdm --upgrade +RUN apt-get update +COPY requirements.txt . +RUN pip install --upgrade --no-cache-dir pip \ + && pip install --no-cache-dir -r requirements.txt WORKDIR /workspace -RUN git clone https://github.com/artmatsak/cnn-dailymail.git +RUN git clone https://github.com/abisee/cnn-dailymail.git RUN git clone https://github.com/gcunhase/AMICorpusXML.git +# Re-build apex +RUN git clone https://github.com/nv-joseli/apex.git +RUN cd apex && \ + git checkout bf16lamb && \ + NVCC_APPEND_FLAGS='--threads 1' pip install -v --disable-pip-version-check --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" . + WORKDIR /workspace/bart COPY . . diff --git a/PyTorch/LanguageModeling/BART/README.md b/PyTorch/LanguageModeling/BART/README.md index 044f2907a..16e2761c3 100755 --- a/PyTorch/LanguageModeling/BART/README.md +++ b/PyTorch/LanguageModeling/BART/README.md @@ -1,4 +1,4 @@ -# BART 1.0 For PyTorch +# BART For PyTorch This repository provides a script and recipe to train the BART model to achieve state-of-the-art accuracy and is tested and maintained by NVIDIA. @@ -30,16 +30,15 @@ This repository provides a script and recipe to train the BART model to achieve * [Inference performance benchmark](#inference-performance-benchmark) * [Results](#results) * [Training accuracy results](#training-accuracy-results) - * [Training accuracy: NVIDIA DGX A100 (8x A100 80GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-80gb) - * [Training accuracy: NVIDIA DGX-1 V100 (8x V100 32GB)](#training-accuracy-nvidia-dgx-1-v100-8x-v100-32gb) + * [Pre-training accuracy: NVIDIA DGX A100 (320x A100 80GB)](#pre-training-accuracy-nvidia-dgx-a100-320x-a100-80gb) + * [Fine-tuning accuracy: NVIDIA DGX A100 (8x A100 80GB)](#fine-tuning-accuracy-nvidia-dgx-a100-8x-a100-80gb) * [Training stability test](#training-stability-test) * [Training performance results](#training-performance-results) - * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-dgx-a100-8x-a100-80gb) - * [Training performance: NVIDIA DGX-1 V100 (8x V100 32GB)](#training-performance-nvidia-dgx-1-v100-8x-v100-32gb) + * [Pre-training performance: Single-node on NVIDIA DGX A100 (8x A100 80GB)](#pre-training-performance-single-node-on-nvidia-dgx-a100-8x-a100-80gb) + * [Pre-training performance: Multi-node on NVIDIA DGX A100 (8x A100 80GB)](#pre-training-performance-multi-node-on-nvidia-dgx-a100-8x-a100-80gb) + * [Fine-tuning performance: NVIDIA DGX A100 (8x A100 80GB)](#fine-tuning-performance-nvidia-dgx-a100-8x-a100-80gb) * [Inference performance results](#inference-performance-results) * [Inference performance: NVIDIA DGX A100 (1x A100 80GB)](#inference-performance-nvidia-dgx-a100-1x-a100-80gb) - * [Inference performance: NVIDIA DGX-1 V100 (1x V100 32GB)](#inference-performance-nvidia-dgx-1-v100-1x-v100-16gb) - * [Inference performance: NVIDIA T4](#inference-performance-nvidia-t4) - [Release notes](#release-notes) * [Changelog](#changelog) * [Known issues](#known-issues) @@ -76,16 +75,33 @@ Inference is done by default with beam search 4 for CNN-DM dataset and 6 for XSu The following features are supported by this model: -| **Feature** | **BERT** | +| **Feature** | **BART** | |:---------:|:----------:| -|APEX AMP|Yes| -|APEX DDP|Yes| +| PyTorch AMP | Yes | +| PyTorch DDP | Yes | +| LAMB | Yes | +| Multi-node | Yes | +| LDDL | Yes | +| Pre-LN | Yes | #### Features [APEX](https://github.com/NVIDIA/apex) is a PyTorch extension with NVIDIA-maintained utilities to streamline mixed precision and distributed training, whereas [AMP](https://nvidia.github.io/apex/amp.html) is an abbreviation used for automatic mixed precision training. [DDP](https://nvidia.github.io/apex/parallel.html) stands for DistributedDataParallel and is used for multi-GPU training. + +[LAMB](https://arxiv.org/pdf/1904.00962.pdf) stands for Layerwise Adaptive Moments based optimizer, is a large batch optimization technique that helps accelerate training of deep neural networks using large minibatches. It allows using a global batch size of 65536 and 32768 on sequence lengths 128 and 512 respectively, compared to a batch size of 256 for [Adam](https://arxiv.org/pdf/1412.6980.pdf). The optimized implementation accumulates 1024 gradient batches in phase 1 and 4096 steps in phase 2 before updating weights once. This results in a 15% training speedup. On multi-node systems, LAMB allows scaling up to 1024 GPUs resulting in training speedups of up to 72x in comparison to Adam. Adam has limitations on the learning rate that can be used since it is applied globally on all parameters whereas LAMB follows a layerwise learning rate strategy. + +NVLAMB adds the necessary tweaks to [LAMB version 1](https://arxiv.org/abs/1904.00962v1), to ensure correct convergence. The algorithm is as follows: + + ![NVLAMB](images/nvlamb.png) + +In this PyTorch BART example, we used global batch size of 64000 and 30720 on sequence lengths 128 and 512 respectively, compared to a batch size of 8000 and sequence lengths 512 on [RoBERTa](https://arxiv.org/pdf/1907.11692.pdf) which Facebook used for BART. We only trained with 44% total number of tokens compared to Facebook's BART. It can get 2.7x training speedup and achieve similar accuracy. + +[LDDL](../lddl) is a library that enables scalable data preprocessing and loading. LDDL is used by this PyTorch BART example. + +[Pre-LN](https://arxiv.org/pdf/2002.04745.pdf) is an transformer architecture, which layer normalization is put inside the residual blocks. In our experiments, For Pre-LN transformer, the loss decays faster and it makes training more stable without gradient exploding or vanishing . + ### Mixed precision training Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in Volta, and following with both the Turing and Ampere architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures. Using [mixed precision training](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) previously required two steps: @@ -99,17 +115,15 @@ For information about: #### Enabling mixed precision -In this repository, mixed precision training is enabled by PyTorch Lightning with NVIDIA’s APEX library. The APEX library has an automatic mixed precision module that allows mixed precision to be enabled with minimal code changes. +In this repository, mixed precision is enabled in PyTorch by using the Automatic Mixed Precision (AMP) +autocast [torch.cuda.amp.autocast](https://pytorch.org/docs/stable/amp.html#autocasting) which casts variables +to half-precision upon retrieval, while storing variables in single-precision format. +Furthermore, to preserve small gradient magnitudes in backpropagation, +a [gradient scaling](https://pytorch.org/docs/stable/amp.html#gradient-scaling) +step must be included. -Automatic mixed precision can be enabled with the following code changes: - -``` -if args.fp16: - train_params["precision"] = 16 - train_params["amp_level"] = args.amp_level -``` - -Where `` is the optimization level. In the summarization, `O1` is set as the optimization level. Mixed precision training can be turned on by passing the `fp16` argument to the `finetune.py`. All shell scripts have a positional argument available to enable mixed precision training. +For an in-depth walk through on AMP, check out sample usage +[here](https://pytorch.org/docs/stable/amp.html). #### TF32 @@ -146,10 +160,8 @@ The following section lists the requirements that you need to meet in order to s This repository contains Dockerfile which extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: - [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -- [PyTorch 21.02-py3+](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) NGC container +- [PyTorch 22.08-py3+](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) NGC container - Supported GPUs: -- [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) -- [NVIDIA Turing architecture](https://www.nvidia.com/en-us/design-visualization/technologies/turing-architecture/) - [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) For more information about how to get started with NGC containers, see the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: @@ -193,43 +205,73 @@ Use the following script to download and preprocess CNN DM data as well as XSum bash scripts/get_data.sh ``` +Use the script to download Wikipedia, Common Crawl, and OpenWebTextCorpus for pre-training dataset +```bash +bash scripts/get_pretraining_data.sh +``` +The pretraining dataset is 200GB+ and takes 24+ hours to download. + +For downloading less dataset, you can change the date period of Common Crawl archive to take less time. For example: +```bash +download_common_crawl \ + --outdir $data_folder/common_crawl \ + --warc-files-start-date 2016-09-01 \ + --warc-files-end-date 2016-10-31 \ + --start-date 2016-09-01 \ + --end-date 2016-10-31 +``` + +Use the script to preprocess the pre-training dataset into LDDL Parquet shards +```bash +bash scripts/preprocess_pretrain_data.sh +``` + By default, the path to the data folder is set to /workspace/bart/data for ease of use in all the scripts. -5. Start summarizing. +5. Start pre-training + +BART is designed to pre-train language representations. The following scripts are to replicate pre-training on Wikipedia, Common Crawl, and OpenWebTextCorpus from the LAMB paper. These scripts are general and can be used for pre-training language representations on any corpus of choice. +From within the container, you can use the following script to run pre-training using LAMB. + +```bash +bash scripts/run_pretraining.sh +``` + +6. Start summarizing. Pretrained BART representations can be fine tuned for a state-of-the-art summarization system. From within the container, you can use the following script to run summarization on CNN DM dataset. ```bash -bash scripts/run_summarization.sh +bash scripts/run_summarization.sh ``` This repository contains a number of predefined configurations to run the CNN+DM fine tuning on NVIDIA DGX-1 V100 or NVIDIA DGX A100 nodes in `scripts/params/cnn_dm_params.sh`. For example, to use the default DGX A100 8 gpu config, run: ```bash -bash scripts/run_summarization.sh $(source scripts/params/cnn_dm_params.sh && dgxa100_8gpu_fp16) +bash scripts/run_summarization.sh $(source scripts/params/cnn_dm_params.sh && dgxa100_8gpu_bf16) ``` Similarly, configurations for XSum dataset are available in `scripts/params/xsum_params.sh`. -6. Start inference/predictions. +7. Start inference/predictions. You can run the following script to run inference summarization using a fine-tuned checkpoint: ```bash -bash scripts/run_eval_summarization.sh +bash scripts/run_eval_summarization.sh ``` This repository contains multiple predefined configurations in `scripts/params/cnn_dm_params.sh` and `scripts/params/xsum_params.sh`. For example, to run inference on CNN-DM with a checkpoint run: ```bash -bash scripts/run_eval_summarization.sh $(source scripts/params/cnn_dm_params.sh && dgxa100_8gpu_fp16_eval) +bash scripts/run_eval_summarization.sh $(source scripts/params/cnn_dm_params.sh && dgxa100_8gpu_bf16_eval) ``` Now that you have your model trained and evaluated, you can choose to compare your training results with our [Training accuracy results](#training-accuracy-results). You can also choose to benchmark yours performance to [Training performance benchmark](#training-performance-results), or [Inference performance benchmark](#inference-performance-results). Following the steps in these sections will ensure that you achieve the same accuracy and performance results as stated in the [Results](#results) section. -7. Run Custom Inference with the fine-tuned checkpoint +8. Run Custom Inference with the fine-tuned checkpoint We can write a simple few lines of code to run custom inference with the fine-tuned checkpoint. ```python @@ -238,7 +280,8 @@ from bart.tokenization.tokenization_bart import BartTokenizer from bart.configuration.configuration_bart import BartConfig import json config = BartConfig(**json.load(open('configs/config.json', "r"))) -config.fp16 = False +config.dtype = None +config.pre_ln = True model_path = 'results/_epoch1_step2000.ckpt' # The fine-tuned checkpoint path model = BartForConditionalGeneration.from_pretrained(model_path, config=config) tokenizer = BartTokenizer.from_pretrained('facebook/bart-large-cnn') @@ -262,6 +305,7 @@ The following sections provide greater details of the dataset, running training ### Scripts and sample code In the root directory, the most important files are: +* `pretrain.py` - Serves as entry point for pre-training * `finetune.py` - Serves as entry point for fine-tuning * `run_eval.py` - Serves as entry point for inference * `Dockerfile` - Container with the basic set of dependencies to run BART @@ -270,6 +314,8 @@ The `scripts/` folder encapsulates all the one-click scripts required for runnin * `run_summarization.sh` - Runs summarization finetuning followed by inference using the `finetune.py` and `run_eval.py` files. * `run_summarization_eval.sh` - Runs inference on fine tuned checkpoint using the `run_eval.py` file. * `get_data.sh` - Preprocesses CNN-DM dataset as well as downloads and preprocesses XSum dataset. +* `get_pretraining_data.sh` - Downloads pre-train dataset. +* `preprocess_pretrain_data.sh` - Preprocesses pre-train dataset. Other folders included in the root directory are: * `data/` - Necessary folder to download datasets required for fine tuning of BART. @@ -277,27 +323,47 @@ Other folders included in the root directory are: * `utils/` - Necessary utility files for BART model. ### Parameters -Aside from the options to set hyperparameters, the relevant options to control the behaviour of the `run_pretraining.py` script are: +Aside from the options to set hyperparameters, the relevant options to control the behaviour of the `pretrain.py` script are: + +``` +--config_path: The configuration file corresponding to BART Model +--warmup_steps: Number of WARMUP_STEPS +--max_steps: Number of MAX_STEPS +--data_dir: Location to DATA_DIR +--learning_rate: Learning Rate +--n_val: Number of validation examples to test for early stopping +--train_batch_size: Train batch size +--gradient_accumulation_steps: Number of accumulation steps +--max_source_length: Maximum source length +--max_target_length: Maximum target length +--val_max_target_length: Maximum length of validation tokens +--eval_max_gen_length: Maximum length while generating validation tokens +--weight_decay: weight decay +--dropout: drop out +--lamb: Whether to use LAMB optimizer +--pre_ln: Whether to use Pre-LN architecture +--allreduce_post_accumulation_half_precision: Whether to do fp16/bf16 allreduce post accumulation +``` + +Aside from the options to set hyperparameters, the relevant options to control the behaviour of the `finetune.py` script are: ``` --config_path: The configuration file corresponding to BART Model --warmup_steps: Number of WARMUP_STEPS --max_steps: Number of MAX_STEPS --data_dir: Location to DATA_DIR ---gpus: Number of GPUs --learning_rate: Learning Rate --n_val: Number of validation examples to test for early stopping --train_batch_size: Train batch size --gradient_accumulation_steps: Number of accumulation steps ---val_check_interval: Periodicity of checking validation score --max_source_length: Maximum source length --max_target_length: Maximum target length --val_max_target_length: Maximum length of validation tokens --eval_max_gen_length: Maximum length while generating validation tokens --weight_decay: weight decay --dropout: drop out ---early_stopping_patience: number of validation trials of no improvement before which to trigger early stopping ---amp_level: amp mode of optimization level to use if training with mixed precision +--pre_ln: Whether to use Pre-LN architecture +--allreduce_post_accumulation_half_precision: Whether to do fp16/bf16 allreduce post accumulation ``` ### Command-line options @@ -305,13 +371,19 @@ Aside from the options to set hyperparameters, the relevant options to control t To see the full list of available options and their descriptions, use the `-h` or `--help` command-line option with the Python file, for example: ```bash +python pretrain.py --help python finetune.py --help python run_eval.py --help ``` ### Getting the data +For pre-training BART, we use the concatenation of Wikipedia, Common Crawl, and OpenWebTextCorpus. + +Common Crawl is an archieve of news articles from small and major publishers world wide, which is provided from commoncrawl.org. + +OpenWebTextCorpus is an open source effort to reproduce OpenAI’s WebText dataset. The distribution was created by Aaron Gokaslan and Vanya Cohen of Brown University. -We have tested fine tuning the BART model on summarization benchmarks such as CNN-DM and XSum. +For fine-tuning BART, we have tested fine tuning the BART model on summarization benchmarks such as CNN-DM and XSum. CNN-DM is a concatenation of CNN Stories as well as Daily Mail Stories. CNN consists of approximately 90k documents whereas Daily Mail consists of 197k documents. @@ -323,7 +395,7 @@ XSum, on the other hand, is also a single-document summarization task dataset bu #### Dataset guidelines -The repository contains a script to preprocess and download data. It can be run as: +The repository contains scripts to preprocess and download data. It can be run as: ```bash bash scripts/get_data.sh @@ -333,15 +405,67 @@ The script downloads CNN and DM raw data from [here](https://cs.nyu.edu/~kcho/DM The script also downloads the XSum dataset from the [HuggingFace storage](https://s3.amazonaws.com/datasets.huggingface.co/summarization/xsum.tar.gz). +```bash +bash scripts/get_pretraining_data.sh +``` +The script uses the LDDL downloader to download Wikipedia, Common Crawl, and OpenWebTextCorpus dataset. The Common Crawl is downloaded by [news-please](https://github.com/fhamborg/news-please). And OpenWebTextCorpus is downloaded from [here](https://skylion007.github.io/OpenWebTextCorpus/) + +For downloading less dataset, you can change the date period of Common Crawl archive in the script to take less time. For example: +```bash +download_common_crawl \ + --outdir $data_folder/common_crawl \ + --warc-files-start-date 2016-09-01 \ + --warc-files-end-date 2016-10-31 \ + --start-date 2016-09-01 \ + --end-date 2016-10-31 +``` + +```bash +bash scripts/preprocess_pretrain_data.sh +``` +The script uses the LDDL preprocessor and load balancer to preprocess the pre-training dataset into Parquet shards which are then streamed during the pre-training by the LDDL data loader. + The script by default stores the data into the `/workspace/bart/data` folder. ### Training process +The training process consists of two steps: pre-training and fine-tuning. + +#### Pre-training +Pre-training BART is done using `scripts/run_pretraining.sh` script that, in turn, uses the `pretrain.py` file to perform training. + +For example, it can be invoked by calling: + +```bash +bash scripts/run_pretraining.sh +``` + +Where: +* train_batch_size_phase* - per-GPU batch size used for training in the respective phase +* learning_rate_phase* - Learning rate in the respective phase +* precision - fp16/bf16/fp32/tf32 precision for training +* use_preln - Whether to use Pre-LN architecture +* num_gpus - number of GPUs to run training with +* warmup_steps_phase* - Number of warmup steps for learning rate scheduler in the respective phase +* train_steps_phase* - Number of training steps in the respective phase +* save_checkpoint_steps - Number of steps for saving checkpoint +* num_accumulation_phase* - Number of accumulation steps for an effective larger training batch size in the respective phase +* config_path - path to configuration file of BART Model + + + +By default, the training script stores results to `results/bart_pyt_pretraining` and runs with: + +```bash +bash scripts/run_pretraining.sh 200 32 5e-3 4e-3 bf16 true 8 2166 200 95040 7560 100 40 120 configs/config.json +``` + +#### Fine-tuning Training BART for summarization is done using `scripts/run_summarization.sh` script that, in turn, uses the `finetune.py` file to perform training. For example, it can be invoked by calling: ```bash -Bash scripts/run_summarization.sh +bash scripts/run_summarization.sh ``` Where: @@ -359,15 +483,14 @@ Where: * EVAL_BEAMS - Number of beams to run during inference * EVAL_BS - Batch size for inference during validation * PRED_BS - Batch size for inference on test data -* VAL_CHECK_INTERVAL - Fraction of an epoch after which runs validation if <1. Or number of training samples after which to run validation if >1. -* PATIENCE - Number of validation checks of no improvement after which to stop training +* PRELN - Whether to use Pre-LN architecture By default, the training script stores results to `results/bart_pyt_${DATESTAMP}` and runs with: ```bash -bash scripts/run_summarization.sh data/cnn_dm/ configs/config.json 8 1e-4 24 1 fp16 20000 500 1024 142 4 128 64 0.3 +bash scripts/run_summarization.sh data/cnn_dm/ data/nvidia_pretrained/bart_large/ configs/config.json 8 1.25e-4 40 1 bf16 2000 50 1024 142 4 128 true ``` These parameters train CNN-DM with reasonable rouge scores on a LUNA with 80GB A100 cards. Other tested configurations are available under `scripts/params/cnn_dm_params.sh` for CNN-DM and `scripts/params/xsum_params.sh` for XSum datasets. @@ -378,7 +501,7 @@ Evaluating BART for summarization is done using `scripts/run_eval_summarization. For example, it can be invoked by calling: ```bash -bash scripts/run_eval_summarization.sh +bash scripts/run_eval_summarization.sh ``` Where: @@ -391,6 +514,7 @@ Where: * `MAX_TARGET_LEN` - Maximum target length of summaries * `DATA_DIR` - path to data directory with train/test/val files. * `CONFIG_PATH` - path to configuration file of BART Model +* `PRELN` - Whether to use Pre-LN architecture By default, the training script stores results to `results/bart_pyt_inference_${DATESTAMP}` and runs with: @@ -427,57 +551,63 @@ The resulting `NUM_GPU` and PRECISION vs Throughput is stored in `results/bart_p The following sections provide details on how we achieved our performance and accuracy in training and inference. #### Training accuracy results -##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) +##### Pre-training accuracy: NVIDIA DGX A100 (320x A100 80GB) +Our results were obtained by running the `run_pretraining.sh` training script in the PyTorch 22.08-py3 NGC container on 40 nodes NVIDIA DGX A100 (320x A100 80GB) GPUs. +| Nodes | Sequence Length | Batch size/GPU (BF16) | Accumulation Steps | Final loss - BF16 | Time to train (hrs) - BF16 | +|-------|-------|---------------------------------------|------------------------------------|----------------------------------|-----------------------------------| +| 40 | 128 | 200 | 1 | 0.5095 | 17.38 | +| 40 | 512 | 32 | 3 | 0.6085 | 3.28 | +##### Fine-tuning accuracy: NVIDIA DGX A100 (8x A100 80GB) -Our results for XSUM dataset were obtained by running the `run_summarization.sh` training script in the PyTorch 21.02-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Accuracy column lists rogue1, rogue2 and rogueLSum scores. +Our results for XSUM dataset were obtained by running the `run_summarization.sh` training script in the PyTorch 22.08-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Rogue1, rogue2 and rogueLSum scores list as accuracy. -| GPUs | Batch size (TF32, mixed precision) | Accuracy - TF32 | Accuracy - mixed precision | Time to train (hrs) - TF32 | Time to train (hrs) - mixed precision | Time to train (hrs) speedup (TF32 to mixed precision) | -|------|------------------|-----------------|----------------------------|----------------------|---------------------------------|-------------------------------------------------| -| 1 | 24, 40 | 44.41, 21.02, 35.66 | 44.87, 21.49, 36.17 | 3.10 | 2.43 | 1.27 | -| 8 | 192, 320 | 45.34, 21.93, 36.61 | 45.31, 21.83, 36.60 | 0.58 | 0.45 | 1.27 | +| GPUs | Batch size (TF32, BF16) | R1 - TF32 | R2 - TF32 | RL - TF32 | R1 - BF16 | R2 - BF16 | RL - BF16 | Time to train (hrs) - TF32 | Time to train (hrs) - BF16 | Time to train (hrs) speedup (TF32 to BF16) | +|------|------------------|-----|-----|-----|-----|-----|-----|----------------------|---------------------------------|-------------------------------------------------| +| 1 | 24, 40 | 45.22 | 22.03 | 36.95 | 44.91 | 21.85 | 36.78 | 2.41 | 1.69 | 1.43 | +| 8 | 192, 320 | 45.04 | 21.92 | 36.82 | 45.01 | 21.86 | 36.81 | 0.64 | 0.39 | 1.64 | In addition,results for CNN-DM dataset are: -| GPUs | Batch size (TF32, mixed precision) | Accuracy - TF32 | Accuracy - mixed precision | Time to train (hrs) - TF32 | Time to train (hrs) - mixed precision | Time to train (hrs) speedup (TF32 to mixed precision) | -|------|------------------|-----------------|----------------------------|----------------------|---------------------------------|-------------------------------------------------| -| 1 | 24, 40 | 44.37, 21.36, 41.17 | 44.43, 21.43, 41.22 | 4.88 | 3.61 | 1.35 | -| 8 | 192, 320 | 44.49, 21.48, 41.28 | 44.19, 21.26, 40.97 | 0.73 | 0.56 | 1.30 | - -##### Training accuracy: NVIDIA DGX-1 V100 (8x V100 32GB) - -Our results were obtained by running the `run_summarization.sh` training script in the PyTorch 21.02-py3 NGC container on NVIDIA DGX-2 with (16x V100 32GB) GPUs. Accuracy column lists rogue1, rogue2 and rogueLSum scores. - -| GPUs | Batch size (FP32, mixed precision) | Accuracy - FP32 | Accuracy - mixed precision | Time to train (hrs) - FP32 | Time to train (hrs) - mixed precision | Time to train (hrs) speedup (FP32 to mixed precision) | -|------|------------------|-----------------|----------------------------|----------------------|---------------------------------|-------------------------------------------------| -| 1 | 8, 14 | 44.16, 20.66, 35.24 | 44.86, 21.41, 36.02 | 17.23 | 6.12 | 2.82 | -| 8 | 64, 112 | 45.42, 21.91, 36.62 | 45.58, 22.01, 36.79 | 2.56 | 1.09 | 2.36 | - - -In addition,results for CNN-DM dataset are: +| GPUs | Batch size (TF32, BF16) | R1 - TF32 | R2 - TF32 | RL - TF32 | R1 - BF16 | R2 - BF16 | RL - BF16 | Time to train (hrs) - TF32 | Time to train (hrs) - BF16 | Time to train (hrs) speedup (TF32 to BF16) | +|------|------------------|-----|-----|-----|-----|-----|-----|----------------------|---------------------------------|-------------------------------------------------| +| 1 | 24, 40 | 43.76 | 20.79 | 40.51 | 43.58 | 20.63 | 40.32 | 3.87 | 2.42 | 1.60 | +| 8 | 192, 320 | 43.77 | 20.77 | 40.53 | 43.76 | 20.73 | 40.50 | 0.73 | 0.45 | 1.62 | -| GPUs | Batch size (FP32, mixed precision) | Accuracy - FP32 | Accuracy - mixed precision | Time to train (hrs) - FP32 | Time to train (hrs) - mixed precision | Time to train (hrs) speedup (FP32 to mixed precision) | -|------|------------------|-----------------|----------------------------|----------------------|---------------------------------|-------------------------------------------------| -| 1 | 8, 14 | 44.49, 21.48, 41.26 | 44.55, 21.47, 41.32 | 26.17 | 9.74 | 2.69 | -| 8 | 64, 112 | 44.34, 21.42, 41.12 | 44.27, 21.30, 41.06 | 3.58 | 1.45 | 2.46 | +##### Fine-tuning stability test - -##### Training stability test - -Our results for XSUM dataset were obtained by running the `run_summarization.sh` training script in the PyTorch 21.02-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Accuracy column lists rogue1 scores across 5 different training runs with different seeds on DGX A100. +Our results for XSUM dataset were obtained by running the `run_summarization.sh` training script in the PyTorch 22.08-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Accuracy column lists rogue1 scores across 5 different training runs with different seeds on DGX A100. | **FP16, 8x GPUs** | **seed 1** | **seed 2** | **seed 3** | **seed 4** | **seed 5** | **mean** | **std** | |:-----------:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:| -|rogue1 | 45.34 | 45.34 | 45.21 | 45.33 | 45.34 | 45.31 | 0.055 | +|rogue1 | 45.08 | 44.98 | 45.10 | 44.91 | 44.95 | 45.00 | #### Training performance results -##### Training performance: NVIDIA DGX A100 (8x A100 80GB) - -Our results were obtained by running the `run_summarization.sh` training script in the PyTorch 21.02-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. - -| GPUs | Batch size / GPU (TF32, mixed precision) | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 - mixed precision) | Weak scaling - TF32 | Weak scaling - mixed precision | +##### Pre-training performance: Single-node on NVIDIA DGX A100 (8x A100 80GB) +Our results were obtained by running the `run_pretraining.sh` training script in the PyTorch 22.08-py3 NGC container on single node NVIDIA DGX A100 (8x A100 80GB) GPUs. +| GPUs | Sequence Length | Batch size / GPU (TF32, BF16) | Throughput - TF32 | Throughput - BF16 | Throughput speedup (TF32 - BF16) | Weak scaling - TF32 | Weak scaling - BF16 | +|------|------|------------------|-------------------|------------------------------|---------------------------------------------|---------------------|--------------------------------| +| 1 | 128 | 100, 200 | 202.53 | 326.53 | 1.61 | 1 | 1 | +| 8 | 128 | 100, 200 | 1556.23 | 2572.86 | 1.65 | 7.68 | 7.88 | +| 1 | 512 | 16, 32 | 41.35 | 69.31 | 1.68 | 1 | 1 | +| 8 | 512 | 16, 32 | 317.85 | 549.67 | 1.73 | 7.69 | 7.93 | +##### Pre-training performance: Multi-node on NVIDIA DGX A100 (8x A100 80GB) +Our results were obtained by running the `run_pretraining.sh` training script in the PyTorch 22.08-py3 NGC container on multi node NVIDIA DGX A100 (8x A100 80GB) GPUs. +| Nodes | Sequence Length |Batch size / GPU (TF32, BF16) | Throughput - TF32 | Throughput - BF16 | Throughput speedup (TF32 - BF16) | Weak scaling - TF32 | Weak scaling - BF16 | +|------|------|------------------|-------------------|------------------------------|---------------------------------------------|---------------------|--------------------------------| +| 1 | 128 | 100, 200 | 1556.23 | 2572.86 | 1.65 | 1 | 1 | +| 20 | 128 | 100, 200 | 31067.96 | 52,459.02 | 1.69 | 19.96 | 20.39 | +| 40 | 128 | 100, 200 | 61,538.46 | 97028.51 | 1.58 | 39.54 | 37.71 | +| 1 | 512 | 16, 32 | 317.85 | 549.67 | 1.73 | 1 | 1 | +| 20 | 512 | 16, 32 | 5953.49 | 10520.54 | 1.77 | 18.73 | 19.14 | +| 40 | 512 | 16, 32 | 11,636.36 | 19948.05 | 1.71 | 36.61 | 36.29 | +##### Fine-tuning performance: NVIDIA DGX A100 (8x A100 80GB) + +Our results were obtained by running the `run_summarization.sh` training script in the PyTorch 22.08-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in items per second) were averaged over an entire training epoch. + +| GPUs | Batch size / GPU (TF32, BF16) | Throughput - TF32 | Throughput - BF16 | Throughput speedup (TF32 - BF16) | Weak scaling - TF32 | Weak scaling - BF16 | |------|------------------|-------------------|------------------------------|---------------------------------------------|---------------------|--------------------------------| -| 1 | 24, 40 | 31607 | 42076 | 1.33 | 1.00 | 1.00 | -| 8 | 24, 40 | 163054 | 217514 | 1.33 | 5.16 | 5.17 | +| 1 | 24, 40 | 48.61 | 74.59 | 1.53 | 1.00 | 1.00 | +| 8 | 24, 40 | 243.03 | 390.24 | 1.61 | 3.39 | 4.08 | @@ -486,72 +616,22 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic The performance metrics used are tokens per second computed from iterating through an entire epoch of XSum dataset with source length = 1024 and target length = 60. -##### Training performance: NVIDIA DGX-1 V100 (8x V100 32GB) - -Our results were obtained by running the `run_summarization.sh` training script in the PyTorch 21.02-py3 NGC container on NVIDIA DGX-2 with (16x V100 32GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. - -| GPUs | Batch size / GPU (FP32, mixed precision) | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 - mixed precision) | Weak scaling - FP32 | Weak scaling - mixed precision | -|------|------------------|-------------------|------------------------------|---------------------------------------------|---------------------|--------------------------------| -| 1 | 8, 14 | 7527 | 19356 | 2.57 | 1.00 | 1.00 | -| 8 | 8, 14 | 42024 | 111720 | 2.65 | 5.58 | 5.77 | - - -To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). - -The performance metrics used are tokens per second computed from iterating through an entire epoch of XSum dataset with source length = 1024 and target length = 60. - #### Inference performance results ##### Inference performance: NVIDIA DGX A100 (1x A100 80GB) -Our results were obtained by running the `run_eval_summarization.sh` inferencing benchmarking script in the PyTorch 20.11-py3 NGC container on NVIDIA DGX A100 (1x A100 80GB) GPU. +Our results were obtained by running the `run_eval_summarization.sh` inferencing benchmarking script in the PyTorch 22.08-py3 NGC container on NVIDIA DGX A100 (1x A100 80GB) GPU. -FP16 +BF16 | Batch size | Latency Avg | Latency 90% | Latency 95% | Latency 99% | Throughput | |------------|-------------|:-----------:|:-----------:|:-----------:|------------| -| 1 | 0.43 | 0.53 | 0.57 | 0.67 | 2.34 | -| 4 | 0.64 | 0.75 | 0.81 | 0.95 | 6.28 | -| 8 | 0.86 | 1.01 | 1.09 | 1.20 | 9.35 | -| 16 | 1.29 | 1.56 | 1.65 | 1.76 | 12.44 | -| 32 | 2.38 | 3.06 | 3.23 | 3.33 | 13.42 | -| 64 | 4.70 | 6.06 | 6.25 | 6.35 | 13.55 | -| 128 | 10.10 | 12.22 | 12.32 | 12.96 | 12.61 | - -To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). - -The inference performance metrics used are milliseconds per iteration. They are computed by iterating through the XSum test data with source length = 1024, target length = 60 and beam search = 6. - - -##### Inference performance: NVIDIA DGX-1 V100 (1x V100 32GB) - -Our results were obtained by running the `run_eval_summarization.sh` inferencing benchmarking script in the PyTorch 20.11-py3 NGC container on NVIDIA DGX-2 with (1x V100 32GB) GPU. - -FP16 -| Batch size | Latency Avg | Latency 90% | Latency 95% | Latency 99% | Throughput | -|------------|-------------|:-----------:|:-----------:|:-----------:|------------| -| 1 | 0.67 | 0.84 | 0.89 | 1.04 | 1.49 | -| 4 | 0.96 | 1.14 | 1.24 | 1.43 | 4.16 | -| 8 | 1.33 | 1.59 | 1.72 | 1.90 | 6.01 | -| 16 | 1.99 | 2.39 | 2.57 | 2.69 | 8.04 | -| 32 | 3.41 | 4.31 | 4.53 | 4.63 | 9.36 | -| 64 | 6.66 | 8.61 | 8.75 | 8.92 | 9.55 | - -To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). - -The inference performance metrics used are milliseconds per iteration. They are computed by iterating through the XSum test data with source length = 1024, target length = 60 and beam search = 6. - -##### Inference performance: NVIDIA T4 - -Our results were obtained by running the `run_eval_summarization.sh` inferencing benchmarking script in the PyTorch 21.02-py3 NGC container on NVIDIA T4 with GPU. - -FP16 -| Batch size | Latency Avg | Latency 90% | Latency 95% | Latency 99% | Throughput | -|------------|-------------|:-----------:|:-----------:|:-----------:|------------| -| 1 | 0.42 | 0.52 | 0.56 | 0.66 | 2.40 | -| 4 | 0.72 | 0.89 | 0.96 | 1.09 | 5.58 | -| 8 | 1.13 | 1.60 | 1.73 | 1.96 | 7.08 | -| 16 | 2.25 | 3.19 | 3.38 | 3.58 | 7.11 | -| 32 | 4.44 | 6.53 | 6.96 | 7.21 | 7.19 | +| 1 | 0.28 | 0.35 | 0.38 | 0.46 | 3.54 | +| 4 | 0.44 | 0.52 | 0.56 | 0.71 | 9.16 | +| 8 | 0.63 | 0.75 | 0.83 | 0.98 | 12.79 | +| 16 | 0.98 | 1.2 | 1.29 | 1.47 | 16.3 | +| 32 | 1.8 | 2.27 | 2.47 | 2.63 | 17.73 | +| 64 | 3.78 | 4.85 | 5.21 | 5.4 | 16.83 | +| 128 | 8.29 | 10.53 | 10.69 | 10.93 | 15.36 | To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). @@ -564,6 +644,9 @@ The inference performance metrics used are milliseconds per iteration. They are June, 2021 - Initial release +December, 2022 +- Add features for pre-training + ### Known issues There are no known issues with this model. diff --git a/PyTorch/LanguageModeling/BART/bart/configuration/configuration_bart.py b/PyTorch/LanguageModeling/BART/bart/configuration/configuration_bart.py index 8805bd2dc..25bab4fe6 100755 --- a/PyTorch/LanguageModeling/BART/bart/configuration/configuration_bart.py +++ b/PyTorch/LanguageModeling/BART/bart/configuration/configuration_bart.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The Fairseq Authors and The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -88,8 +89,6 @@ Google "layerdrop arxiv", as its not explainable in one line. decoder_layerdrop: (:obj:`float`, optional, defaults to 0.0): Google "layerdrop arxiv", as its not explainable in one line. - extra_pos_embeddings: (:obj:`int`, optional, defaults to 2): - How many extra learned positional embeddings to use. Should be pad_token_id+1 for bart. num_labels: (:obj:`int`, optional, defaults to 2): for SequenceClassification is_encoder_decoder (:obj:`int`, optional, defaults to True): @@ -109,7 +108,6 @@ class BartConfig(PretrainedConfig): def __init__( self, activation_dropout=0.0, - extra_pos_embeddings=2, # FIXME(@sshleifer): delete? activation_function="gelu", vocab_size=50265, d_model=1024, @@ -194,9 +192,6 @@ def __init__( # Classifier stuff self.classif_dropout = classifier_dropout - # pos embedding offset - self.extra_pos_embeddings = self.pad_token_id + 1 - self.force_bos_token_to_be_generated = force_bos_token_to_be_generated self.attention_bias = attention_bias diff --git a/PyTorch/LanguageModeling/BART/bart/configuration/configuration_t5.py b/PyTorch/LanguageModeling/BART/bart/configuration/configuration_t5.py index 8eb8dc976..654885741 100755 --- a/PyTorch/LanguageModeling/BART/bart/configuration/configuration_t5.py +++ b/PyTorch/LanguageModeling/BART/bart/configuration/configuration_t5.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2010, The T5 Authors and HuggingFace Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/configuration/configuration_utils.py b/PyTorch/LanguageModeling/BART/bart/configuration/configuration_utils.py index 76650135f..5fbf2ada0 100755 --- a/PyTorch/LanguageModeling/BART/bart/configuration/configuration_utils.py +++ b/PyTorch/LanguageModeling/BART/bart/configuration/configuration_utils.py @@ -1,6 +1,6 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team. -# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/PyTorch/LanguageModeling/BART/bart/modeling/bert_attn.py b/PyTorch/LanguageModeling/BART/bart/modeling/bert_attn.py new file mode 100644 index 000000000..410b128b8 --- /dev/null +++ b/PyTorch/LanguageModeling/BART/bart/modeling/bert_attn.py @@ -0,0 +1,78 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +class BertSelfAttention(nn.Module): + + def __init__( + self, + embed_dim, + num_heads, + dropout=0.0, + bias=True, + encoder_decoder_attention=False, # otherwise self_attention + ): + def __init__(self, config): + super(BertSelfAttention, self).__init__() + if config.hidden_size % num_heads != 0: + raise ValueError( + "The hidden size (%d) is not a multiple of the number of attention " + "heads (%d)" % (config.hidden_size, num_heads)) + self.num_heads = num_heads + self.attention_head_size = int(config.hidden_size / num_heads) + self.all_head_size = self.num_heads * self.attention_head_size + + self.query = nn.Linear(config.hidden_size, self.all_head_size) + self.key = nn.Linear(config.hidden_size, self.all_head_size) + self.value = nn.Linear(config.hidden_size, self.all_head_size) + + self.dropout = nn.Dropout(config.attention_probs_dropout_prob) + + def transpose_for_scores(self, x): + new_x_shape = x.size()[:-1] + (self.num_heads, self.attention_head_size) + x = torch.reshape(x, new_x_shape) + return x.permute(0, 2, 1, 3) + + def transpose_key_for_scores(self, x): + new_x_shape = x.size()[:-1] + (self.num_heads, self.attention_head_size) + x = torch.reshape(x, new_x_shape) + return x.permute(0, 2, 3, 1) + + def forward(self, hidden_states, attention_mask): + mixed_query_layer = self.query(hidden_states) + mixed_key_layer = self.key(hidden_states) + mixed_value_layer = self.value(hidden_states) + + query_layer = self.transpose_for_scores(mixed_query_layer) + key_layer = self.transpose_key_for_scores(mixed_key_layer) + value_layer = self.transpose_for_scores(mixed_value_layer) + + # Take the dot product between "query" and "key" to get the raw attention scores. + attention_scores = torch.matmul(query_layer, key_layer) + attention_scores = attention_scores / math.sqrt(self.attention_head_size) + # Apply the attention mask is (precomputed for all layers in BertModel forward() function) + attention_scores = attention_scores + attention_mask + + # Normalize the attention scores to probabilities. + attention_probs = F.softmax(attention_scores, dim=-1) + + # This is actually dropping out entire tokens to attend to, which might + # seem a bit unusual, but is taken from the original Transformer paper. + attention_probs = self.dropout(attention_probs) + + context_layer = torch.matmul(attention_probs, value_layer) + context_layer = context_layer.permute(0, 2, 1, 3).contiguous() + new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,) + context_layer = torch.reshape(context_layer, new_context_layer_shape) + return context_layer diff --git a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_bart.py b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_bart.py index cbffa72fb..51872c311 100755 --- a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_bart.py +++ b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_bart.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The Facebook AI Research Team Authors and The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -291,6 +292,7 @@ def __init__(self, config: BartConfig): self.fc1 = nn.Linear(self.embed_dim, config.encoder_ffn_dim) self.fc2 = nn.Linear(config.encoder_ffn_dim, self.embed_dim) self.final_layer_norm = LayerNorm(self.embed_dim) + self.pre_ln = config.pre_ln def forward( self, @@ -312,24 +314,44 @@ def forward( """ residual = hidden_states - hidden_states, attn_weights, _ = self.self_attn( - hidden_states=hidden_states, - attention_mask=attention_mask, - layer_head_mask=layer_head_mask, - output_attentions=output_attentions, - ) - hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) - dtype = hidden_states.dtype - hidden_states = residual + hidden_states - hidden_states = self.self_attn_layer_norm(hidden_states).to(dtype) + if self.pre_ln: + dtype = hidden_states.dtype + hidden_states = self.self_attn_layer_norm(hidden_states).to(dtype) + hidden_states, attn_weights, _ = self.self_attn( + hidden_states=hidden_states, + attention_mask=attention_mask, + layer_head_mask=layer_head_mask, + output_attentions=output_attentions, + ) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states - residual = hidden_states - hidden_states = self.activation_fn(self.fc1(hidden_states)).to(dtype) - hidden_states = F.dropout(hidden_states, p=self.activation_dropout, training=self.training) - hidden_states = self.fc2(hidden_states) - hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) - hidden_states = residual + hidden_states - hidden_states = self.final_layer_norm(hidden_states).to(dtype) + residual = hidden_states + hidden_states = self.final_layer_norm(hidden_states).to(dtype) + hidden_states = self.activation_fn(self.fc1(hidden_states)).to(dtype) + hidden_states = F.dropout(hidden_states, p=self.activation_dropout, training=self.training) + hidden_states = self.fc2(hidden_states) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states + else: + hidden_states, attn_weights, _ = self.self_attn( + hidden_states=hidden_states, + attention_mask=attention_mask, + layer_head_mask=layer_head_mask, + output_attentions=output_attentions, + ) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + dtype = hidden_states.dtype + hidden_states = residual + hidden_states + hidden_states = self.self_attn_layer_norm(hidden_states).to(dtype) + + residual = hidden_states + hidden_states = self.activation_fn(self.fc1(hidden_states)).to(dtype) + hidden_states = F.dropout(hidden_states, p=self.activation_dropout, training=self.training) + hidden_states = self.fc2(hidden_states) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states + hidden_states = self.final_layer_norm(hidden_states).to(dtype) if torch.isinf(hidden_states).any() or torch.isnan(hidden_states).any(): clamp_value = torch.finfo(hidden_states.dtype).max - 1000 @@ -369,6 +391,7 @@ def __init__(self, config: BartConfig): self.fc1 = nn.Linear(self.embed_dim, config.decoder_ffn_dim) self.fc2 = nn.Linear(config.decoder_ffn_dim, self.embed_dim) self.final_layer_norm = LayerNorm(self.embed_dim) + self.pre_ln = config.pre_ln def forward( self, @@ -405,49 +428,94 @@ def forward( # decoder uni-directional self-attention cached key/values tuple is at positions 1,2 self_attn_past_key_value = past_key_value[:2] if past_key_value is not None else None # add present self-attn cache to positions 1,2 of present_key_value tuple - hidden_states, self_attn_weights, present_key_value = self.self_attn( - hidden_states=hidden_states, - past_key_value=self_attn_past_key_value, - attention_mask=attention_mask, - layer_head_mask=layer_head_mask, - output_attentions=output_attentions, - ) - hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) - dtype = hidden_states.dtype - hidden_states = residual + hidden_states - hidden_states = self.self_attn_layer_norm(hidden_states).to(dtype) - - # Cross-Attention Block - cross_attn_present_key_value = None - cross_attn_weights = None - if encoder_hidden_states is not None: - residual = hidden_states + if self.pre_ln: + dtype = hidden_states.dtype + hidden_states = self.self_attn_layer_norm(hidden_states).to(dtype) + hidden_states, self_attn_weights, present_key_value = self.self_attn( + hidden_states=hidden_states, + past_key_value=self_attn_past_key_value, + attention_mask=attention_mask, + layer_head_mask=layer_head_mask, + output_attentions=output_attentions, + ) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states - # cross_attn cached key/values tuple is at positions 3,4 of present_key_value tuple - cross_attn_past_key_value = past_key_value[-2:] if past_key_value is not None else None - hidden_states, cross_attn_weights, cross_attn_present_key_value = self.encoder_attn( + # Cross-Attention Block + cross_attn_present_key_value = None + cross_attn_weights = None + if encoder_hidden_states is not None: + residual = hidden_states + + # cross_attn cached key/values tuple is at positions 3,4 of present_key_value tuple + cross_attn_past_key_value = past_key_value[-2:] if past_key_value is not None else None + hidden_states = self.encoder_attn_layer_norm(hidden_states).to(dtype) + hidden_states, cross_attn_weights, cross_attn_present_key_value = self.encoder_attn( + hidden_states=hidden_states, + key_value_states=encoder_hidden_states, + attention_mask=encoder_attention_mask, + layer_head_mask=encoder_layer_head_mask, + past_key_value=cross_attn_past_key_value, + output_attentions=output_attentions, + ) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states + + # add cross-attn to positions 3,4 of present_key_value tuple + present_key_value = present_key_value + cross_attn_present_key_value + + # Fully Connected + residual = hidden_states + hidden_states = self.final_layer_norm(hidden_states).to(dtype) + hidden_states = self.activation_fn(self.fc1(hidden_states)).to(dtype) + hidden_states = F.dropout(hidden_states, p=self.activation_dropout, training=self.training) + hidden_states = self.fc2(hidden_states) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states + else: + hidden_states, self_attn_weights, present_key_value = self.self_attn( hidden_states=hidden_states, - key_value_states=encoder_hidden_states, - attention_mask=encoder_attention_mask, - layer_head_mask=encoder_layer_head_mask, - past_key_value=cross_attn_past_key_value, + past_key_value=self_attn_past_key_value, + attention_mask=attention_mask, + layer_head_mask=layer_head_mask, output_attentions=output_attentions, ) hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + dtype = hidden_states.dtype hidden_states = residual + hidden_states - hidden_states = self.encoder_attn_layer_norm(hidden_states).to(dtype) + hidden_states = self.self_attn_layer_norm(hidden_states).to(dtype) + + # Cross-Attention Block + cross_attn_present_key_value = None + cross_attn_weights = None + if encoder_hidden_states is not None: + residual = hidden_states + + # cross_attn cached key/values tuple is at positions 3,4 of present_key_value tuple + cross_attn_past_key_value = past_key_value[-2:] if past_key_value is not None else None + hidden_states, cross_attn_weights, cross_attn_present_key_value = self.encoder_attn( + hidden_states=hidden_states, + key_value_states=encoder_hidden_states, + attention_mask=encoder_attention_mask, + layer_head_mask=encoder_layer_head_mask, + past_key_value=cross_attn_past_key_value, + output_attentions=output_attentions, + ) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states + hidden_states = self.encoder_attn_layer_norm(hidden_states).to(dtype) - # add cross-attn to positions 3,4 of present_key_value tuple - present_key_value = present_key_value + cross_attn_present_key_value + # add cross-attn to positions 3,4 of present_key_value tuple + present_key_value = present_key_value + cross_attn_present_key_value - # Fully Connected - residual = hidden_states - hidden_states = self.activation_fn(self.fc1(hidden_states)).to(dtype) - hidden_states = F.dropout(hidden_states, p=self.activation_dropout, training=self.training) - hidden_states = self.fc2(hidden_states) - hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) - hidden_states = residual + hidden_states - hidden_states = self.final_layer_norm(hidden_states).to(dtype) + # Fully Connected + residual = hidden_states + hidden_states = self.activation_fn(self.fc1(hidden_states)).to(dtype) + hidden_states = F.dropout(hidden_states, p=self.activation_dropout, training=self.training) + hidden_states = self.fc2(hidden_states) + hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) + hidden_states = residual + hidden_states + hidden_states = self.final_layer_norm(hidden_states).to(dtype) outputs = (hidden_states,) @@ -642,7 +710,7 @@ class BartEncoder(BartPretrainedModel): def __init__(self, config: BartConfig, embed_tokens: Optional[nn.Embedding] = None): super().__init__(config) - self.fp16 = config.fp16 + self.cast_dtype = config.dtype self.dropout = config.dropout self.layerdrop = config.encoder_layerdrop @@ -663,6 +731,9 @@ def __init__(self, config: BartConfig, embed_tokens: Optional[nn.Embedding] = No ) self.layers = nn.ModuleList([BartEncoderLayer(config) for _ in range(config.encoder_layers)]) self.layernorm_embedding = LayerNorm(embed_dim) + self.pre_ln = config.pre_ln + if self.pre_ln: + self.last_layernorm = LayerNorm(embed_dim) self.init_weights() @@ -737,12 +808,12 @@ def forward( if attention_mask is not None: # [bsz, seq_len] -> [bsz, 1, tgt_seq_len, src_seq_len] attention_mask = _expand_mask(attention_mask, inputs_embeds.dtype) - if self.fp16: - attention_mask = attention_mask.to(torch.float16) + if self.cast_dtype: + attention_mask = attention_mask.to(self.cast_dtype) - if self.fp16: - hidden_states = hidden_states.to(torch.float16) + if self.cast_dtype: + hidden_states = hidden_states.to(self.cast_dtype) encoder_states = () if output_hidden_states else None all_attentions = () if output_attentions else None @@ -787,6 +858,11 @@ def custom_forward(*inputs): if output_attentions: all_attentions = all_attentions + (layer_outputs[1],) + if self.pre_ln: + hidden_states = self.last_layernorm(hidden_states) + if self.cast_dtype: + hidden_states = hidden_states.to(self.cast_dtype) + if output_hidden_states: encoder_states = encoder_states + (hidden_states,) @@ -807,7 +883,7 @@ class BartDecoder(BartPretrainedModel): def __init__(self, config: BartConfig, embed_tokens: Optional[nn.Embedding] = None): super().__init__(config) - self.fp16 = config.fp16 + self.cast_dtype = config.dtype self.dropout = config.dropout self.layerdrop = config.decoder_layerdrop self.padding_idx = config.pad_token_id @@ -826,6 +902,9 @@ def __init__(self, config: BartConfig, embed_tokens: Optional[nn.Embedding] = No ) self.layers = nn.ModuleList([BartDecoderLayer(config) for _ in range(config.decoder_layers)]) self.layernorm_embedding = LayerNorm(config.d_model) + self.pre_ln = config.pre_ln + if self.pre_ln: + self.last_layernorm = LayerNorm(config.d_model) self.init_weights() @@ -961,12 +1040,12 @@ def forward( hidden_states = F.dropout(hidden_states, p=self.dropout, training=self.training) - if self.fp16: - hidden_states = hidden_states.to(torch.float16) + if self.cast_dtype: + hidden_states = hidden_states.to(self.cast_dtype) if attention_mask is not None: - attention_mask = attention_mask.to(torch.float16) - assert encoder_hidden_states.dtype==torch.float16 - encoder_attention_mask = encoder_attention_mask.to(torch.float16) + attention_mask = attention_mask.to(self.cast_dtype) + assert encoder_hidden_states.dtype==self.cast_dtype + encoder_attention_mask = encoder_attention_mask.to(self.cast_dtype) # decoder layers all_hidden_states = () if output_hidden_states else None @@ -1039,6 +1118,11 @@ def custom_forward(*inputs): if encoder_hidden_states is not None: all_cross_attentions += (layer_outputs[2],) + if self.pre_ln: + hidden_states = self.last_layernorm(hidden_states) + if self.cast_dtype: + hidden_states = hidden_states.to(self.cast_dtype) + # add hidden states from the last decoder layer if output_hidden_states: all_hidden_states += (hidden_states,) diff --git a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_outputs.py b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_outputs.py index ea9ccbc1d..e80d34ac6 100755 --- a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_outputs.py +++ b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_outputs.py @@ -1,3 +1,18 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + from dataclasses import dataclass from typing import List, Optional, Tuple diff --git a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_t5.py b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_t5.py index 203dd5cd1..c9cf45c6f 100755 --- a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_t5.py +++ b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_t5.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 Mesh TensorFlow authors, T5 Authors and HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_utils.py b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_utils.py index 4c85eb3bb..1f9d8b95f 100755 --- a/PyTorch/LanguageModeling/BART/bart/modeling/modeling_utils.py +++ b/PyTorch/LanguageModeling/BART/bart/modeling/modeling_utils.py @@ -1,6 +1,6 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 The Google AI Language Team Authors, Facebook AI Research authors and The HuggingFace Inc. team. -# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_bart.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_bart.py index 3c8f53d91..399413cdd 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_bart.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_bart.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The Facebook AI Research Team Authors and The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_gpt2.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_gpt2.py index dbb722b2c..fcdb1b786 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_gpt2.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_gpt2.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 The Open AI Team Authors and The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_mbart.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_mbart.py index d648baa39..5d3c154f4 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_mbart.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_mbart.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The Facebook AI Research Team Authors and The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_roberta.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_roberta.py index cc2d4f44f..bbc004a6c 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_roberta.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_roberta.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 The Open AI Team Authors and The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils.py index cc3e04dd3..efe79478a 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -312,8 +313,6 @@ def split_on_token(tok, text): elif i == len(split_text) - 1: if sub_text: result += [sub_text] - else: - pass else: if sub_text: result += [sub_text] diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_base.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_base.py index 2084ebe73..8e3e993b8 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_base.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_base.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_fast.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_fast.py index 84b79ad37..8a73230d7 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_fast.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_utils_fast.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlm_roberta.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlm_roberta.py index fe6e38ffc..20c485377 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlm_roberta.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlm_roberta.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 Google AI, Google Brain and Carnegie Mellon University Authors and the HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlnet.py b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlnet.py index 5b2496b9a..5f917b49f 100755 --- a/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlnet.py +++ b/PyTorch/LanguageModeling/BART/bart/tokenization/tokenization_xlnet.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 Google AI, Google Brain and Carnegie Mellon University Authors and the HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/finetune.py b/PyTorch/LanguageModeling/BART/finetune.py index c9db18ea6..dc6541b2f 100755 --- a/PyTorch/LanguageModeling/BART/finetune.py +++ b/PyTorch/LanguageModeling/BART/finetune.py @@ -22,14 +22,14 @@ from pathlib import Path from typing import Dict, List, Tuple import json +import random import numpy as np -import pytorch_lightning as pl import torch from torch import nn from torch.utils.data import DataLoader -from lightning_base import BaseTransformer, add_generic_args, generic_train +from training_base import BaseTransformer, add_generic_args, generic_test, generic_train from bart.tokenization.tokenization_mbart import MBartTokenizer from bart.modeling.modeling_t5 import T5ForConditionalGeneration @@ -37,7 +37,6 @@ from bart.tokenization.tokenization_bart import BartTokenizer from bart.modeling.modeling_bart import BartForConditionalGeneration, shift_tokens_right -from utils.callbacks import Seq2SeqLoggingCallback, get_checkpoint_callback, get_early_stopping_callback, CheckpointEveryNSteps from utils.utils import ( ROUGE_KEYS, LegacySeq2SeqDataset, @@ -54,9 +53,10 @@ save_git_info, save_json, use_task_specific_params, - format_step, + format_step ) -from utils.distributed_utils import get_rank +from utils.gpu_affinity import set_affinity +from utils.distributed_utils import get_rank, get_device_count, get_world_size import dllogger import time @@ -130,6 +130,8 @@ def __init__(self, hparams, **kwargs): self.eval_max_length = self.model.config.max_length self.val_metric = self.default_val_metric if self.hparams.val_metric is None else self.hparams.val_metric + self.config = self.model.config + def freeze_embeds(self): """Freeze token embeddings and positional embeddings for bart, just token embeddings for t5.""" try: @@ -158,7 +160,7 @@ def _step(self, batch: dict) -> Tuple: if isinstance(self.model, T5ForConditionalGeneration): decoder_input_ids = self.model._shift_right(tgt_ids) else: - decoder_input_ids = shift_tokens_right(tgt_ids, pad_token_id, self.model.config.decoder_start_token_id) + decoder_input_ids = shift_tokens_right(tgt_ids, pad_token_id, self.config.decoder_start_token_id) outputs = self(src_ids, attention_mask=src_mask, decoder_input_ids=decoder_input_ids, use_cache=False) lm_logits = outputs[0] @@ -166,7 +168,7 @@ def _step(self, batch: dict) -> Tuple: # Same behavior as modeling_bart.py, besides ignoring pad_token_id ce_loss_fct = torch.nn.CrossEntropyLoss(ignore_index=pad_token_id) - assert lm_logits.shape[-1] == self.model.config.vocab_size + assert lm_logits.shape[-1] == self.config.vocab_size loss = ce_loss_fct(lm_logits.view(-1, lm_logits.shape[-1]), tgt_ids.view(-1)) else: lprobs = torch.nn.functional.log_softmax(lm_logits, dim=-1) @@ -179,7 +181,7 @@ def _step(self, batch: dict) -> Tuple: def pad(self) -> int: return self.tokenizer.pad_token_id - def training_step(self, batch, batch_idx) -> Dict: + def training_step(self, batch) -> Dict: loss_tensors, logits = self._step(batch) logs = {name: loss for name, loss in zip(self.loss_names, loss_tensors)} # tokens per batch @@ -191,14 +193,14 @@ def training_step(self, batch, batch_idx) -> Dict: logs["src_pad_frac"] = batch["input_ids"].eq(self.pad).float().mean() # TODO(SS): make a wandb summary metric for this - self.log("train_loss_ddp_avg", loss_tensors[0], on_step=True, prog_bar=True, logger=True, sync_dist=self.sync_dist) - return {"loss": loss_tensors[0], "log": logs, "progress_bar":{"global_step":self.global_step}} + # self.log("train_loss_ddp_avg", loss_tensors[0], on_step=True, prog_bar=True, logger=True, sync_dist=self.sync_dist) + return {"loss": loss_tensors[0], "log": logs} # Can remove after pytorch lightning fix def training_epoch_end(self, outputs) -> None: return - def validation_step(self, batch, batch_idx) -> Dict: + def validation_step(self, batch) -> Dict: return self._generative_step(batch) def validation_epoch_end(self, outputs, prefix="val") -> Dict: @@ -262,7 +264,7 @@ def _generative_step(self, batch: dict) -> dict: base_metrics.update(gen_time=gen_time, gen_len=summ_len, preds=preds, target=target, **rouge) return base_metrics - def test_step(self, batch, batch_idx): + def test_step(self, batch): return self._generative_step(batch) def test_epoch_end(self, outputs): @@ -303,10 +305,8 @@ def get_dataloader(self, type_path: str, batch_size: int, shuffle: bool = False) dataset, batch_sampler=batch_sampler, collate_fn=dataset.collate_fn, - # shuffle=False, num_workers=self.num_workers, pin_memory=True, - # batch_size=None, ) else: return DataLoader( @@ -395,6 +395,9 @@ def add_model_specific_args(parser, root_dir): parser.add_argument('--layers', type=str, default=None, help="string indicating which layers to distill for SFT, split by '-' (ex. 0-6-11)") parser.add_argument('--do_encoder', action="http://github.com/store_true", default=False, help="if true distills the encoder") parser.add_argument('--do_decoder', action="http://github.com/store_true", default=False, help="if true distills the decoder") + parser.add_argument("--local_rank", type=int, default=os.getenv('LOCAL_RANK', 0), help="local_rank for distributed training on gpus") + parser.add_argument("--gpus", type=int, default=1, help="number of gpus to train on applied per node") + parser.add_argument("--load_model_weights_only", action="http://github.com/store_true", help="Only load model weights, ignoring other ckpt states. useful at the start of phase2 training") return parser @@ -413,6 +416,29 @@ def __init__(self, hparams, **kwargs): def calc_generative_metrics(self, preds, target) -> dict: return calculate_bleu(preds, target) +def set_seed(args): + random.seed(args.seed + get_rank()) + np.random.seed(args.seed + get_rank()) + torch.manual_seed(args.seed + get_rank()) + +def save_final_checkpoint(args, model): + output_filename = os.path.join(args.output_dir, "final_step.ckpt") + + if get_rank() == 0: + model_to_save = model.module if hasattr(model, "module") else model + torch.save(model_to_save.state_dict(), + output_filename) + +def load_checkpoint(args, path, model, optimizer, scaler): + checkpoint = torch.load(path, map_location=args.device) + model.load_state_dict(checkpoint["model"]) + + if not args.load_model_weights_only: + if 'optimizer' in checkpoint: + optimizer.load_state_dict(checkpoint["optimizer"]) + if 'scaler' in checkpoint: + scaler.load_state_dict(checkpoint["scaler"]) + def distill(layers, pick_layers): sft_layers = nn.ModuleList() delete_layers = [] @@ -449,13 +475,54 @@ def main(args, model=None) -> SummarizationModule: print(args) Path(args.output_dir).mkdir(exist_ok=True) + # Initializes the distributed backend which will take care of sychronizing nodes/GPUs + torch.cuda.set_device(args.local_rank) + device = torch.device("cuda", args.local_rank) + torch.distributed.init_process_group(backend="nccl") + args.device = device + + # Set GPU affinity + if args.affinity != 'disabled': + affinity = set_affinity( + get_rank(), + get_device_count(), + args.affinity + ) + logger.warning(f'{get_rank()}: thread affinity: {affinity}') + + # Set seed + set_seed(args) + + # Setup logging + logging.basicConfig( + format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", + datefmt="%m/%d/%Y %H:%M:%S", + level=logging.INFO if get_rank() in [-1, 0] else logging.WARN, + ) + logger.warning( + "Process global rank: %s, device: %s, distributed training: %s, 16-bits training: %s", + get_rank(), + device, + bool(get_rank() != -1), + (args.fp16 or args.bf16), + ) + + checkpoints = list(sorted(glob.glob(os.path.join(args.output_dir, "_step*.ckpt"), recursive=True), + key=lambda x:int(x.split("step")[1].split(".")[0]))) + if model is None: if "summarization" in args.task: ### Define BART model # Config from "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-cnn/config.json%20%20%20%20%20%20%20%20%20%20%20%20%20#%20Vocab%20modified%20to%2050265%20to%20be%20consistent%20with%20facebook/bart-large%20default%20%20%20%20%20%20%20%20%20%20%20%20%20config%20=%20BartConfig(**json.load(open(args.config_path,"r"))) - config.fp16 = args.fp16 + if args.fp16: + config.dtype = torch.float16 + elif args.bf16: + config.dtype = torch.bfloat16 + else: + config.dtype = None + config.pre_ln = args.pre_ln if args.distill: # if distilling, start from finetuned checkpoint if Path(args.data_dir).name == "cnn_dm": @@ -471,100 +538,81 @@ def main(args, model=None) -> SummarizationModule: checkpoint = args.resume_from_checkpoint if args.distill: # set resume from checkpoint to None (state dict is different) args.resume_from_checkpoint = None + model = BartForConditionalGeneration(config=config) else: - checkpoints = list(sorted(glob.glob(os.path.join(args.output_dir, "*.ckpt"), recursive=True))) if len(checkpoints) > 0: #No checkpoints available checkpoint = checkpoints[-1] args.resume_from_checkpoint = checkpoint + model = BartForConditionalGeneration(config=config) else: args.resume_from_checkpoint = None print("No valid checkpoint to resume from. Using ", checkpoint) + model = BartForConditionalGeneration.from_pretrained(checkpoint, config=config) + + else: + model = BartForConditionalGeneration.from_pretrained(checkpoint, config=config) print("Loading BART model checkpoint using ", checkpoint) - model = BartForConditionalGeneration.from_pretrained(checkpoint, config=config) if args.distill == "sft": model = distill_sft(model) tokenizer = BartTokenizer.from_pretrained( 'facebook/bart-large') # Downloads vocab and merges file automatically - model: SummarizationModule = SummarizationModule(args, model=model, config=config, tokenizer=tokenizer) + trainer: SummarizationModule = SummarizationModule(args, model=model, config=config, tokenizer=tokenizer) else: raise ValueError("Translation not supported at this time") model: SummarizationModule = TranslationModule(args) dataset = Path(args.data_dir).name - if ( - args.logger_name == "default" - or args.fast_dev_run - or str(args.output_dir).startswith("/tmp") - or str(args.output_dir).startswith("/var") - ): - logger = True # don't pollute wandb logs unnecessarily - elif args.logger_name == "wandb": - from pytorch_lightning.loggers import WandbLogger - - project = os.environ.get("WANDB_PROJECT", dataset) - logger = WandbLogger(name=model.output_dir.name, project=project) - - elif args.logger_name == "wandb_shared": - from pytorch_lightning.loggers import WandbLogger - - logger = WandbLogger(name=model.output_dir.name, project=f"hf_{dataset}") - - # if args.early_stopping_patience >= 0: - # extra_callbacks = [get_early_stopping_callback(f"val_{model.val_metric}", args.early_stopping_patience)] - # else: - # extra_callbacks = [] - extra_callbacks = [CheckpointEveryNSteps(args.output_dir, args.max_steps-1)] - - lower_is_better = args.val_metric == "loss" - - log_callback = Seq2SeqLoggingCallback() - - trainer: pl.Trainer = generic_train( - model, - args, - logging_callback=log_callback, - checkpoint_callback=get_checkpoint_callback( - args.output_dir, model.val_metric, args.save_top_k, lower_is_better - ), - extra_callbacks=extra_callbacks, - logger=logger, - ) + trainer.model.to(device) + + # Set up optimizer and scheduler + optimizer, scheduler = trainer.configure_optimizers() + optimizer = optimizer[0] + scheduler = scheduler[0]['scheduler'] + scaler = torch.cuda.amp.GradScaler(enabled=args.fp16) + + step = 0 + if args.resume_from_checkpoint: + logger.info("Loading BART model checkpoint using %s", checkpoint) + checkpoint_suffix = checkpoint.split("step")[-1].split(".")[0] + step = int(checkpoint_suffix) + 1 + load_checkpoint(args, checkpoint, trainer.model, optimizer, scaler) + + if args.distill or args.load_model_weights_only: + args.resume_from_checkpoint = None + step = 0 + + # Distributed training (should be after apex fp16 initialization) + if args.local_rank != -1: + trainer.model = torch.nn.parallel.DistributedDataParallel( + trainer.model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True + ) - if get_rank() == 0: - dllogger.init(backends=[dllogger.JSONStreamBackend(verbosity=dllogger.Verbosity.VERBOSE, - filename=args.json_summary), - dllogger.StdOutBackend(verbosity=dllogger.Verbosity.VERBOSE, step_format=format_step)]) - dllogger.metadata("avg_train_time", {"unit": "s"}) - dllogger.metadata("avg_train_throughput", {"unit": "tokens/s"}) - dllogger.log(step=tuple(), data={"avg_train_tokens":log_callback.tokens, "avg_train_time":log_callback.train_time, "total_train_epochs":log_callback.epochs, "avg_train_throughput":log_callback.tokens/log_callback.train_time}) - print("Avg Tokens = %d Avg Train Time = %.2f Total Epochs = %d"%(log_callback.tokens, log_callback.train_time, log_callback.epochs)) - print("Avg steps per sec = %d Avg Throughput (tok/s) = %d"%(log_callback.avg_steps_per_sec, log_callback.tokens/log_callback.train_time)) - dllogger.flush() - - pickle_save(model.hparams, model.output_dir / "hparams.pkl") - if args.do_predict and not args.do_train: + generic_train(args, trainer, optimizer, scheduler, scaler, checkpoints, step) + + pickle_save(trainer.hparams, trainer.output_dir / "hparams.pkl") + save_final_checkpoint(args, trainer.model) + + if args.do_predict: # Testing from a checkpoint - trainer.test(model) - elif args.do_predict and args.do_train: - # test() without a model tests using the best checkpoint automatically - model.hparams.test_checkpoint = "" - checkpoints = list(sorted(glob.glob(os.path.join(args.output_dir, "*.ckpt"), recursive=True))) - if checkpoints: - model.hparams.test_checkpoint = checkpoints[-1] - trainer.resume_from_checkpoint = checkpoints[-1] - trainer.logger.log_hyperparams(model.hparams) - trainer.test() - return model + generic_test(args, trainer) + return trainer if __name__ == "__main__": parser = argparse.ArgumentParser() - parser = pl.Trainer.add_argparse_args(parser) parser = SummarizationModule.add_model_specific_args(parser, os.getcwd()) args = parser.parse_args() + if get_rank() == 0: + dllogger.init(backends=[dllogger.JSONStreamBackend(verbosity=dllogger.Verbosity.VERBOSE, + filename=args.json_summary), + dllogger.StdOutBackend(verbosity=dllogger.Verbosity.VERBOSE, step_format=format_step)]) + main(args) + dllogger.flush() + + torch.distributed.barrier() diff --git a/PyTorch/LanguageModeling/BART/images/nvlamb.png b/PyTorch/LanguageModeling/BART/images/nvlamb.png new file mode 100644 index 000000000..a28f24e31 Binary files /dev/null and b/PyTorch/LanguageModeling/BART/images/nvlamb.png differ diff --git a/PyTorch/LanguageModeling/BART/pretrain.py b/PyTorch/LanguageModeling/BART/pretrain.py new file mode 100644 index 000000000..76bf1d3b2 --- /dev/null +++ b/PyTorch/LanguageModeling/BART/pretrain.py @@ -0,0 +1,423 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +import argparse +import glob +import logging +import os +from tabnanny import check +import time +import datetime +import random +from collections import defaultdict +from pathlib import Path +from typing import Dict, List, Tuple +import json + +import numpy as np +import torch +from torch.utils.data import DataLoader +from torch.utils.tensorboard import SummaryWriter + +from training_base import BaseTransformer, add_generic_args, generic_train +from bart.tokenization.tokenization_mbart import MBartTokenizer + +from bart.configuration.configuration_bart import BartConfig +from bart.tokenization.tokenization_bart import BartTokenizer +from bart.modeling.modeling_bart import BartForConditionalGeneration + +from utils.utils import ( + PretrainingSeq2SeqDataset, + Seq2SeqDataset, + assert_all_frozen, + freeze_params, + get_git_info, + label_smoothed_nll_loss, + lmap, + pickle_save, + save_git_info, + save_json, + use_task_specific_params, + format_step +) +from utils.data_collator import DataCollatorForBART +from utils.gpu_affinity import set_affinity +from utils.distributed_utils import get_rank, get_device_count, get_world_size +import dllogger + +import lddl.torch +from lddl.utils import get_all_parquets_under + +logger = logging.getLogger(__name__) + +class BartForConditionalGenerationWrapper(torch.nn.Module): + def __init__(self, model, args): + super(BartForConditionalGenerationWrapper, self).__init__() + if args.fp16: + model.half() + elif args.bf16: + model.bfloat16() + + model.train() + + self.module = model + + def forward(self, input_ids, attention_mask, decoder_input_ids): + outputs = self.module.forward(input_ids, attention_mask=attention_mask, decoder_input_ids=decoder_input_ids, use_cache=False) + + return outputs + +class PretrainingModule(BaseTransformer): + mode = "pretraining" + loss_names = ["loss"] + + def __init__(self, hparams, **kwargs): + + super().__init__(hparams, num_labels=None, mode=self.mode, **kwargs) + use_task_specific_params(self.model, "pretraining") + save_git_info(self.hparams.output_dir) + self.metrics_save_path = Path(self.output_dir) / "metrics.json" + self.hparams_save_path = Path(self.output_dir) / "hparams.pkl" + pickle_save(self.hparams, self.hparams_save_path) + self.step_count = 0 + self.metrics = defaultdict(list) + + self.dataset_kwargs: dict = dict( + max_source_length=self.hparams.max_source_length, + prefix=self.model.config.prefix or "", + ) + self.n_obs = { + "train": self.hparams.n_train if self.hparams.n_train >= 0 else None + } + + #@todo should you freeze? + if self.hparams.freeze_embeds: + self.freeze_embeds() + if self.hparams.freeze_encoder: + freeze_params(self.model.get_encoder()) + assert_all_frozen(self.model.get_encoder()) + + self.hparams.git_sha = get_git_info()["repo_sha"] + self.num_workers = hparams.num_workers + self.decoder_start_token_id = None # default to config + + if self.model.config.decoder_start_token_id is None and isinstance(self.tokenizer, MBartTokenizer): + self.decoder_start_token_id = self.tokenizer.lang_code_to_id[hparams.tgt_lang] + self.model.config.decoder_start_token_id = self.decoder_start_token_id + + self.collate_fn = DataCollatorForBART( + tokenizer=self.tokenizer, + mlm_probability=self.hparams.mlm_probability, + permute_sentence_ratio=self.hparams.permute_sentence_ratio, + decoder_start_token_id=self.model.config.decoder_start_token_id + ) + + self.dataset_class = ( + PretrainingSeq2SeqDataset + ) + + self.conig = self.model.config + + def freeze_embeds(self): + """Freeze token embeddings and positional embeddings for bart, just token embeddings for t5.""" + try: + freeze_params(self.model.model.shared) + for d in [self.model.model.encoder, self.model.model.decoder]: + freeze_params(d.embed_positions) + freeze_params(d.embed_tokens) + except AttributeError: + freeze_params(self.model.shared) + for d in [self.model.encoder, self.model.decoder]: + freeze_params(d.embed_tokens) + + def forward(self, input_ids, **kwargs): + return self.model(input_ids, **kwargs) + + def ids_to_clean_text(self, generated_ids: List[int]): + gen_text = self.tokenizer.batch_decode( + generated_ids, skip_special_tokens=True, clean_up_tokenization_spaces=True + ) + return lmap(str.strip, gen_text) + + + def _step(self, batch: dict) -> Tuple: + pad_token_id = self.tokenizer.pad_token_id + src_ids, src_mask, decoder_input_ids = batch["input_ids"], batch["attention_mask"], batch["decoder_input_ids"] + tgt_ids = batch["labels"] + + outputs = self(src_ids, attention_mask=src_mask, decoder_input_ids=decoder_input_ids, use_cache=False) + lm_logits = outputs[0] + if self.hparams.label_smoothing == 0: + # Same behavior as modeling_bart.py, besides ignoring pad_token_id + ce_loss_fct = torch.nn.CrossEntropyLoss(ignore_index=pad_token_id) #@should you ignore unmasked tokens? Check! + + assert lm_logits.shape[-1] == self.config.vocab_size + loss = ce_loss_fct(lm_logits.view(-1, lm_logits.shape[-1]), tgt_ids.view(-1)) + else: + lprobs = torch.nn.functional.log_softmax(lm_logits, dim=-1) + loss, nll_loss = label_smoothed_nll_loss( + lprobs, tgt_ids, self.hparams.label_smoothing, ignore_index=pad_token_id + ) + return (loss,), lm_logits + + @property + def pad(self) -> int: + return self.tokenizer.pad_token_id + + def training_step(self, batch) -> Dict: + loss_tensors, logits = self._step(batch) + logs = {name: loss for name, loss in zip(self.loss_names, loss_tensors)} + # tokens per batch + logs["ip_tpb"] = batch["input_ids"].numel() + logs["op_tpb"] = batch["labels"].numel() + logs["tpb"] = batch["input_ids"].ne(self.pad).sum() + batch["labels"].ne(self.pad).sum() + logs["bs"] = batch["input_ids"].shape[0] + logs["src_pad_tok"] = batch["input_ids"].eq(self.pad).sum() + logs["src_pad_frac"] = batch["input_ids"].eq(self.pad).float().mean() + # TODO(SS): make a wandb summary metric for this + + # self.log("train_loss_ddp_avg", loss_tensors[0], on_step=True, prog_bar=True, logger=True, sync_dist=self.sync_dist) + + return {"loss": loss_tensors[0], "log": logs} + + # Can remove after pytorch lightning fix + def training_epoch_end(self, outputs) -> None: + return + + def save_metrics(self, latest_metrics, type_path) -> None: + self.metrics[type_path].append(latest_metrics) + save_json(self.metrics, self.metrics_save_path) + + def get_dataset(self, type_path, src_file, + shuffle_buffer_size=1000, + shuffle_buffer_warmup_factor=16, + max_shards_per_node=1048576) -> Seq2SeqDataset: + + lddl_dataset_kwargs = { + 'transform':lambda x:x, + 'local_rank': get_rank(), + 'shuffle_buffer_size': shuffle_buffer_size, + 'shuffle_buffer_warmup_factor': shuffle_buffer_warmup_factor, + 'base_seed': self.hparams.seed, + 'max_shards_per_node': max_shards_per_node + } + + n_obs = self.n_obs[type_path] + dataset = self.dataset_class( + get_all_parquets_under(src_file), + self.tokenizer, + n_obs=n_obs, + type_path=type_path, + **self.dataset_kwargs, **lddl_dataset_kwargs, + ) + return dataset + + def get_dataloader(self, type_path: str, batch_size: int, shuffle: bool = False) -> DataLoader: + dataset = self.get_dataset(type_path, self.hparams.data_dir) + + dataloader_args = {"collate_fn":self.collate_fn} + + return DataLoader( + dataset, + batch_size=batch_size, + collate_fn=self.collate_fn, + shuffle=False, + num_workers=self.num_workers, + sampler=None, + pin_memory=True + ) + + def train_dataloader(self) -> DataLoader: + dataloader = self.get_dataloader("train", batch_size=self.hparams.train_batch_size, shuffle=True) + return dataloader + + @staticmethod + def add_model_specific_args(parser, root_dir): + BaseTransformer.add_model_specific_args(parser, root_dir) + add_generic_args(parser, root_dir) + parser.add_argument( + "--max_source_length", + default=1024, + type=int, + help="The maximum total input sequence length after tokenization. Sequences longer " + "than this will be truncated, sequences shorter will be padded.", + ) + parser.add_argument("--load_model_weights_only", action="http://github.com/store_true", help="Only load model weights, ignoring other ckpt states. useful at the start of phase2 training") + parser.add_argument("--freeze_encoder", action="http://github.com/store_true") + parser.add_argument("--freeze_embeds", action="http://github.com/store_true") + parser.add_argument("--logger_name", type=str, choices=["default", "wandb", "wandb_shared"], default="default") + parser.add_argument("--n_train", type=int, default=-1, required=False, help="# examples. -1 means use all.") + parser.add_argument("--buffer_size", type=int, default=128, required=False, help="Buffer size for shuffling dataset") + parser.add_argument( + "--task", type=str, default="pretraining", required=False, help="# examples. -1 means use all." + ) + parser.add_argument("--label_smoothing", type=float, default=0.0, required=False) + parser.add_argument("--mlm_probability", type=float, default=0.3, required=False) + parser.add_argument("--permute_sentence_ratio", type=float, default=1.0, required=False) + parser.add_argument("--src_lang", type=str, default="", required=False) + parser.add_argument("--tgt_lang", type=str, default="", required=False) + + parser.add_argument( + "--early_stopping_patience", + type=int, + default=-1, + required=False, + help="-1 means never early stop. early_stopping_patience is measured in validation checks, not epochs. So val_check_interval will effect it.", + ) + parser.add_argument("--local_rank", type=int, default=os.getenv('LOCAL_RANK', 0), help="local_rank for distributed training on gpus") + parser.add_argument('--json-summary', type=str, default="results/dllogger.json", + help='If provided, the json summary will be written to' + 'the specified file.') + return parser + +def set_seed(args): + random.seed(args.seed + get_rank()) + np.random.seed(args.seed + get_rank()) + torch.manual_seed(args.seed + get_rank()) + +def load_checkpoint(args, path, model, optimizer, scaler): + checkpoint = torch.load(path, map_location=args.device) + model.load_state_dict(checkpoint["model"]) + + if not args.load_model_weights_only: + if 'optimizer' in checkpoint: + optimizer.load_state_dict(checkpoint["optimizer"]) + if 'scaler' in checkpoint: + scaler.load_state_dict(checkpoint["scaler"]) + +def main(args, model=None) -> PretrainingModule: + print(args) + Path(args.output_dir).mkdir(parents=True, exist_ok=True) + + # Initializes the distributed backend which will take care of sychronizing nodes/GPUs + torch.cuda.set_device(args.local_rank) + device = torch.device("cuda", args.local_rank) + torch.distributed.init_process_group(backend="nccl") + args.device = device + + # Set GPU affinity + if args.affinity != 'disabled': + affinity = set_affinity( + get_rank(), + get_device_count(), + args.affinity + ) + logger.warning(f'{get_rank()}: thread affinity: {affinity}') + + # Set seed + set_seed(args) + + # Setup logging + logging.basicConfig( + format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", + datefmt="%m/%d/%Y %H:%M:%S", + level=logging.INFO if get_rank() in [-1, 0] else logging.WARN, + ) + logger.warning( + "Process global rank: %s, device: %s, distributed training: %s, 16-bits training: %s", + get_rank(), + device, + bool(get_rank() != -1), + (args.fp16 or args.bf16), + ) + + if model is None: + if "pretraining" in args.task: + ### Define BART model + # Config from "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-cnn/config.json+%20%20%20%20%20%20%20%20%20%20%20%20#%20Vocab%20modified%20to%2050265%20to%20be%20consistent%20with%20facebook/bart-large%20default+%20%20%20%20%20%20%20%20%20%20%20%20config%20=%20BartConfig(**json.load(open(args.config_path,"r"))) + if args.fp16: + config.dtype = torch.float16 + elif args.bf16: + config.dtype = torch.bfloat16 + else: + config.dtype = None + config.pre_ln = args.pre_ln + + model = BartForConditionalGeneration(config=config) + tokenizer = BartTokenizer.from_pretrained( + 'facebook/bart-large') # Downloads vocab and merges file automatically + trainer: PretrainingModule = PretrainingModule(args, model=model, config=config, tokenizer=tokenizer) + else: + raise ValueError("Only pretraining supported!") + + dataset = Path(args.data_dir).name + trainer.model.to(device) + + # Set up optimizer and scheduler + optimizer, scheduler = trainer.configure_optimizers() + optimizer = optimizer[0] + scheduler = scheduler[0]['scheduler'] + scaler = torch.cuda.amp.GradScaler(enabled=args.fp16) + + checkpoints = list(sorted(glob.glob(os.path.join(args.output_dir, "_step*.ckpt"), recursive=True), + key=lambda x:int(x.split("step")[1].split(".")[0]))) + + step = 0 + if args.resume_from_checkpoint: + if ".ckpt" in args.resume_from_checkpoint: + checkpoint = args.resume_from_checkpoint + else: + if len(checkpoints) > 0: #No checkpoints available + checkpoint = checkpoints[-1] + args.resume_from_checkpoint = checkpoint + else: + args.resume_from_checkpoint = None + checkpoint = None + + if checkpoint is None: + logger.info("Pretraining from scratch") + + else: + logger.info("Loading BART model checkpoint using %s", checkpoint) + checkpoint_suffix = checkpoint.split("step")[-1].split(".")[0] + step = int(checkpoint_suffix) + 1 + load_checkpoint(args, checkpoint, trainer.model, optimizer, scaler) + + if args.load_model_weights_only: + args.resume_from_checkpoint = None + step = 0 + + if args.fp16 and args.allreduce_post_accumulation_half_precision: + trainer.model.half() + if args.bf16 and args.allreduce_post_accumulation_half_precision: + trainer.model.bfloat16() + + # Distributed training (should be after apex fp16 initialization) + if args.local_rank != -1: + trainer.model = torch.nn.parallel.DistributedDataParallel( + trainer.model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True + ) + + generic_train(args, trainer, optimizer, scheduler, scaler, checkpoints, step) + + pickle_save(trainer.hparams, trainer.output_dir / "hparams.pkl") + return trainer + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser = PretrainingModule.add_model_specific_args(parser, os.getcwd()) + + args = parser.parse_args() + + if get_rank() == 0: + dllogger.init(backends=[dllogger.JSONStreamBackend(verbosity=dllogger.Verbosity.VERBOSE, + filename=args.json_summary)]) + + main(args) + + dllogger.flush() diff --git a/PyTorch/LanguageModeling/BART/requirements.txt b/PyTorch/LanguageModeling/BART/requirements.txt new file mode 100644 index 000000000..7fb7912a0 --- /dev/null +++ b/PyTorch/LanguageModeling/BART/requirements.txt @@ -0,0 +1,7 @@ +dataclasses +gitpython==3.1.29 +rouge-score==0.1.2 +pynvml==8.0.4 +tqdm==4.64.1 +git+https://github.com/NVIDIA/dllogger +git+https://github.com/NVIDIA/lddl.git \ No newline at end of file diff --git a/PyTorch/LanguageModeling/BART/run_eval.py b/PyTorch/LanguageModeling/BART/run_eval.py index e489631f1..0c6f87cf7 100755 --- a/PyTorch/LanguageModeling/BART/run_eval.py +++ b/PyTorch/LanguageModeling/BART/run_eval.py @@ -91,6 +91,8 @@ def generate_summaries_or_translations( batch_size: int = 8, device: str = DEFAULT_DEVICE, fp16=False, + bf16=False, + pre_ln=False, task="summarization", prefix=None, max_source_length=1024, @@ -117,7 +119,14 @@ def generate_summaries_or_translations( # Config from "https://s3.amazonaws.com/models.huggingface.co/bert/facebook/bart-large-cnn/config.json%20%20%20%20%20#%20Vocab%20modified%20to%2050265%20to%20be%20consistent%20with%20facebook/bart-large%20default%20%20%20%20%20config%20=%20BartConfig(**json.load(open(config_path,"r"))) - config.fp16 = fp16 + if fp16: + config.dtype = torch.float16 + elif bf16: + config.dtype = torch.bfloat16 + else: + config.dtype = None + config.pre_ln = pre_ln + model = BartForConditionalGeneration.from_pretrained(model_path, config=config).to(device) # if distilling, change model @@ -126,6 +135,8 @@ def generate_summaries_or_translations( if fp16: model = model.half() + elif bf16: + model = model.bfloat16() model.eval() tokenizer = BartTokenizer.from_pretrained('facebook/bart-large-cnn') @@ -149,6 +160,7 @@ def generate_summaries_or_translations( results = [] with torch.no_grad(): for batch in tqdm(data_loader): + torch.cuda.synchronize() t0 = time.time() summaries = model.generate( @@ -169,6 +181,7 @@ def generate_summaries_or_translations( if num_return_sequences > 1: preds = chunks(preds, num_return_sequences) # batch size chunks, each of size num_return_seq + torch.cuda.synchronize() eval_time = time.time() - t0 for i, pred in enumerate(preds): store_time = eval_time if i == 0 else None #only store latency for element 0 of every batch @@ -220,6 +233,7 @@ def run_generate(verbose=True): "--num_return_sequences", type=int, default=1, required=False, help="How many sequences to return" ) parser.add_argument("--fp16", action="http://github.com/store_true") + parser.add_argument("--bf16", action="http://github.com/store_true") parser.add_argument("--dump-args", action="http://github.com/store_true", help="print the custom hparams with the results") parser.add_argument( "--info", @@ -259,6 +273,11 @@ def run_generate(verbose=True): parser.add_argument('--layers', type=str, default=None, help="string indicating which teacher layers remain, split by '-' (ex. 0-6-11)") parser.add_argument('--do_encoder', action="http://github.com/store_true", default=False, help="if true encoder distilled") parser.add_argument('--do_decoder', action="http://github.com/store_true", default=False, help="if true decoder distilled") + parser.add_argument("--pre_ln", + default=False, + action='http://github.com/store_true', + help="Whether to use Pre-LN architecture." + ) dist = parser.add_argument_group('distributed setup') dist.add_argument('--local_rank', type=int, @@ -291,10 +310,6 @@ def run_generate(verbose=True): else: dllogger.init(backends=[]) - dllogger.metadata("inference_throughput_mean", {"unit": "tokens/s"}) - for suffix in ["mean", "conf_50", "conf_90", "conf_95", "conf_99", "conf_100"]: - dllogger.metadata(f"inference_latency_{suffix}", {"unit": "s"}) - if parsed_args and verbose: print(f"parsed the following generate kwargs: {parsed_args}") @@ -315,6 +330,8 @@ def run_generate(verbose=True): batch_size=args.bs, device=args.device, fp16=args.fp16, + bf16=args.bf16, + pre_ln=args.pre_ln, task=args.task, prefix=args.prefix, eval_beams=args.eval_beams, diff --git a/PyTorch/LanguageModeling/BART/scripts/get_data.sh b/PyTorch/LanguageModeling/BART/scripts/get_data.sh index 2e5d6924e..9c33933b9 100755 --- a/PyTorch/LanguageModeling/BART/scripts/get_data.sh +++ b/PyTorch/LanguageModeling/BART/scripts/get_data.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + # Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +20,12 @@ data_folder=${1:-"/workspace/bart/data/"} mkdir -p $data_folder # Download and unzip the stories directories into data folder from https://cs.nyu.edu/~kcho/DMQA/ for both CNN and Daily Mail. -cd $data_folder && gdown --id 0BwmD_VLjROrfTHk4NFg2SndKcjQ && tar xf cnn_stories.tgz -gdown --id 0BwmD_VLjROrfM1BxdkxVaTY2bWs && tar xf dailymail_stories.tgz +cd $data_folder && gdown "0BwmD_VLjROrfTHk4NFg2SndKcjQ&confirm=t" && tar xf cnn_stories.tgz +gdown "0BwmD_VLjROrfM1BxdkxVaTY2bWs&confirm=t" && tar xf dailymail_stories.tgz cnn_stories=/workspace/bart/data/cnn/stories dailymail_stories=/workspace/bart/data/dailymail/stories -cd /workspace/cnn-dailymail && python /workspace/cnn-dailymail/make_datafiles.py $cnn_stories $dailymail_stories && mv cnn_dm ${data_folder} +cd /workspace/cnn-dailymail && python /workspace/bart/utils/make_datafiles.py $cnn_stories $dailymail_stories && mv cnn_dm ${data_folder} cd ${data_folder} && wget https://s3.amazonaws.com/datasets.huggingface.co/summarization/xsum.tar.gz && tar -xvf xsum.tar.gz diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/exceptions.py b/PyTorch/LanguageModeling/BART/scripts/get_pretraining_data.sh old mode 100644 new mode 100755 similarity index 53% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/exceptions.py rename to PyTorch/LanguageModeling/BART/scripts/get_pretraining_data.sh index daa8bfb9e..11c649b32 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/exceptions.py +++ b/PyTorch/LanguageModeling/BART/scripts/get_pretraining_data.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + # Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -11,25 +13,22 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -class RunnerException(Exception): - """ - Runner Exception - """ +# ============================================================================== - def __init__(self, message: str): - self._message = message +data_folder=${1:-"/workspace/bart/data/"} - def __str__(self): - return self._message +mkdir -p $data_folder - @property - def message(self): - """Get the exception message. +# Get wikipedia data +download_wikipedia --outdir $data_folder/wiki - Returns - ------- - str - The message associated with this exception, or None if no message. +# Get Common Crawl data +download_common_crawl \ + --outdir $data_folder/common_crawl \ + --warc-files-start-date 2016-09-01 \ + --warc-files-end-date 2019-02-28 \ + --start-date 2016-09-01 \ + --end-date 2019-02-28 - """ - return self._message +# Get OpenWebText data +download_open_webtext --outdir $data_folder/openwebtext diff --git a/PyTorch/LanguageModeling/BART/scripts/params/cnn_dm_params.sh b/PyTorch/LanguageModeling/BART/scripts/params/cnn_dm_params.sh index 69b634647..21097db9a 100755 --- a/PyTorch/LanguageModeling/BART/scripts/params/cnn_dm_params.sh +++ b/PyTorch/LanguageModeling/BART/scripts/params/cnn_dm_params.sh @@ -17,15 +17,16 @@ # CNN-DM Summarization configurations for NVIDIA DGX A100 (8x NVIDIA A100 40GB GPU) -dgxa100_8gpu_fp16 () +dgxa100_8gpu_bf16 () { DATA_DIR=data/cnn_dm/ + CKPT_PATH=data/nvidia_pretrained/bart_large/ CONFIG_PATH="configs/config.json" NUM_GPU=8 LR=1.25e-4 BS=40 ACCUM=1 - PRECISION="fp16" + PRECISION="bf16" TRAIN_STEPS=2000 WARMUP_STEPS=50 MAX_SOURCE_LEN=1024 @@ -33,17 +34,17 @@ dgxa100_8gpu_fp16 () EVAL_BEAMS=4 EVAL_BS=128 PRED_BS=128 - VAL_CHECK_INTERVAL=0.3 + PRELN=true - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL + echo $DATA_DIR $CKPT_PATH $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $PRELN } -dgxa100_8gpu_fp16_eval () +dgxa100_8gpu_bf16_eval () { DATA_DIR=data/cnn_dm/ CONFIG_PATH="configs/config.json" NUM_GPU=8 - PRECISION="fp16" + PRECISION="bf16" MAX_SOURCE_LEN=1024 MAX_TARGET_LEN=142 EVAL_BEAMS=4 @@ -55,6 +56,7 @@ dgxa100_8gpu_fp16_eval () dgxa100_8gpu_tf32 () { DATA_DIR=data/cnn_dm/ + CKPT_PATH=data/nvidia_pretrained/bart_large/ CONFIG_PATH="configs/config.json" NUM_GPU=8 LR=1.25e-4 @@ -68,9 +70,9 @@ dgxa100_8gpu_tf32 () EVAL_BEAMS=4 EVAL_BS=128 PRED_BS=64 - VAL_CHECK_INTERVAL=0.3 + PRELN=true - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL + echo $DATA_DIR $CKPT_PATH $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $PRELN } dgxa100_8gpu_tf32_eval () @@ -86,148 +88,3 @@ dgxa100_8gpu_tf32_eval () echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH } - - -# CNN-DM Summarization configurations for NVIDIA DGX-2H (16x NVIDIA V100 32GB GPU) - -dgx2_16gpu_fp16 () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=16 - LR=1e-4 - BS=14 - ACCUM=1 - PRECISION="fp16" - TRAIN_STEPS=3500 - WARMUP_STEPS=100 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - EVAL_BS=128 - PRED_BS=96 - VAL_CHECK_INTERVAL=0.3 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL -} - -dgx2_16gpu_fp16_eval () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=16 - PRECISION="fp16" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - PRED_BS=96 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} - -dgx2_16gpu_fp32 () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=16 - LR=7e-5 - BS=8 - ACCUM=1 - PRECISION="fp32" - TRAIN_STEPS=6125 - WARMUP_STEPS=150 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - EVAL_BS=96 - PRED_BS=32 - VAL_CHECK_INTERVAL=0.3 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL -} - -dgx2_16gpu_fp32_eval () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=16 - PRECISION="fp32" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - PRED_BS=32 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} - -# CNN-DM Summarization configurations for NVIDIA DGX-1 (8x NVIDIA V100 32GB GPU) - -dgx1_8gpu_fp16 () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=8 - LR=5.5e-5 - BS=14 - ACCUM=1 - PRECISION="fp16" - TRAIN_STEPS=7000 - WARMUP_STEPS=150 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - EVAL_BS=128 - PRED_BS=96 - VAL_CHECK_INTERVAL=0.3 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL -} - -dgx1_8gpu_fp16_eval () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=8 - PRECISION="fp16" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - PRED_BS=96 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} - -dgx1_8gpu_fp32 () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=8 - LR=5.5e-5 - BS=8 - ACCUM=1 - PRECISION="fp32" - TRAIN_STEPS=12250 - WARMUP_STEPS=150 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - EVAL_BS=96 - PRED_BS=32 - VAL_CHECK_INTERVAL=0.3 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL -} - -dgx1_8gpu_fp32_eval () -{ - DATA_DIR=data/cnn_dm/ - CONFIG_PATH="configs/config.json" - NUM_GPU=8 - PRECISION="fp32" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=142 - EVAL_BEAMS=4 - PRED_BS=32 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} diff --git a/PyTorch/LanguageModeling/BART/scripts/params/xsum_params.sh b/PyTorch/LanguageModeling/BART/scripts/params/xsum_params.sh index aa86691b0..21a9964bd 100755 --- a/PyTorch/LanguageModeling/BART/scripts/params/xsum_params.sh +++ b/PyTorch/LanguageModeling/BART/scripts/params/xsum_params.sh @@ -17,15 +17,16 @@ # XSUM dataset summarization configurations for NVIDIA DGX A100 (8x NVIDIA A100 40GB GPU) -dgxa100_8gpu_fp16 () +dgxa100_8gpu_bf16 () { DATA_DIR=data/xsum + CKPT_PATH=data/nvidia_pretrained/bart_large/ CONFIG_PATH=configs/config_xsum.json NUM_GPU=8 LR=1.25e-4 BS=40 ACCUM=1 - PRECISION="fp16" + PRECISION="bf16" TRAIN_STEPS=2000 WARMUP_STEPS=50 MAX_SOURCE_LEN=1024 @@ -33,17 +34,17 @@ dgxa100_8gpu_fp16 () EVAL_BEAMS=6 EVAL_BS=128 PRED_BS=128 - VAL_CHECK_INTERVAL=0.1 + PRELN=true - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL + echo $DATA_DIR $CKPT_PATH $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $PRELN } -dgxa100_8gpu_fp16_eval () +dgxa100_8gpu_bf16_eval () { DATA_DIR=data/xsum CONFIG_PATH=configs/config_xsum.json NUM_GPU=8 - PRECISION="fp16" + PRECISION="bf16" MAX_SOURCE_LEN=1024 MAX_TARGET_LEN=60 EVAL_BEAMS=6 @@ -55,6 +56,7 @@ dgxa100_8gpu_fp16_eval () dgxa100_8gpu_tf32 () { DATA_DIR=data/xsum + CKPT_PATH=data/nvidia_pretrained/bart_large/ CONFIG_PATH=configs/config_xsum.json NUM_GPU=8 LR=1.25e-4 @@ -68,9 +70,9 @@ dgxa100_8gpu_tf32 () EVAL_BEAMS=6 EVAL_BS=128 PRED_BS=64 - VAL_CHECK_INTERVAL=0.1 + PRELN=true - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL + echo $DATA_DIR $CKPT_PATH $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $PRELN } dgxa100_8gpu_tf32_eval () @@ -86,151 +88,3 @@ dgxa100_8gpu_tf32_eval () echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH } - -# XSUM dataset summarization configurations for NVIDIA DGX-2H (16x NVIDIA V100 32GB GPU) - -dgx2_16gpu_fp16 () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=16 - LR=1e-4 - BS=14 - ACCUM=1 - PRECISION="fp16" - TRAIN_STEPS=3500 - WARMUP_STEPS=100 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - EVAL_BS=128 - PRED_BS=96 - VAL_CHECK_INTERVAL=0.3 - PATIENCE=1 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL $PATIENCE -} - -dgx2_16gpu_fp16_eval () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=16 - PRECISION="fp16" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - PRED_BS=96 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} - -dgx2_16gpu_fp32 () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=16 - LR=1.25e-4 - BS=8 - ACCUM=1 - PRECISION="fp32" - TRAIN_STEPS=6125 - WARMUP_STEPS=150 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - EVAL_BS=96 - PRED_BS=32 - VAL_CHECK_INTERVAL=0.3 - PATIENCE=1 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL $PATIENCE -} - -dgx2_16gpu_fp32_eval () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=16 - PRECISION="fp32" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - PRED_BS=32 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} - -# XSUM dataset summarization configurations for NVIDIA DGX-1 (8x NVIDIA V100 32GB GPU) - -dgx1_8gpu_fp16 () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=8 - LR=7e-5 - BS=14 - ACCUM=1 - PRECISION="fp16" - TRAIN_STEPS=7000 - WARMUP_STEPS=200 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - EVAL_BS=128 - PRED_BS=64 - VAL_CHECK_INTERVAL=0.3 - PATIENCE=1 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL $PATIENCE -} - -dgx1_8gpu_fp16_eval () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=8 - PRECISION="fp16" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - PRED_BS=96 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} - -dgx1_8gpu_fp32 () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=8 - LR=7e-5 - BS=8 - ACCUM=1 - PRECISION="fp32" - TRAIN_STEPS=12250 - WARMUP_STEPS=200 - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - EVAL_BS=96 - PRED_BS=32 - VAL_CHECK_INTERVAL=0.3 - PATIENCE=1 - - echo $DATA_DIR $CONFIG_PATH $NUM_GPU $LR $BS $ACCUM $PRECISION $TRAIN_STEPS $WARMUP_STEPS $MAX_SOURCE_LEN $MAX_TARGET_LEN $EVAL_BEAMS $EVAL_BS $PRED_BS $VAL_CHECK_INTERVAL $PATIENCE -} - -dgx1_8gpu_fp32_eval () -{ - DATA_DIR=data/xsum - CONFIG_PATH=configs/config_xsum.json - NUM_GPU=8 - PRECISION="fp32" - MAX_SOURCE_LEN=1024 - MAX_TARGET_LEN=60 - EVAL_BEAMS=6 - PRED_BS=32 - - echo $PRED_BS $NUM_GPU $PRECISION $EVAL_BEAMS $MAX_SOURCE_LEN $MAX_TARGET_LEN $DATA_DIR $CONFIG_PATH -} \ No newline at end of file diff --git a/PyTorch/LanguageModeling/BART/scripts/preprocess_pretrain_data.sh b/PyTorch/LanguageModeling/BART/scripts/preprocess_pretrain_data.sh new file mode 100755 index 000000000..2c3168404 --- /dev/null +++ b/PyTorch/LanguageModeling/BART/scripts/preprocess_pretrain_data.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +wiki_path=${1:-"/workspace/bart/data/wiki"} +common_crawl_path=${2:-"/workspace/bart/data/common_crawl"} +openwebtext_path=${3:-"/workspace/bart/data/openwebtext"} +output_path=${4:-"/workspace/bart/data"} + +mpirun \ + -np 16 \ + --oversubscribe \ + --allow-run-as-root \ + preprocess_bart_pretrain \ + --schedule mpi \ + --target-seq-length 128 \ + --wikipedia $wiki_path/source \ + --common-crawl $common_crawl_path/source \ + --open-webtext $openwebtext_path/source \ + --sink $output_path/pretrain_lddl_128 \ + --num-blocks 1280 + +mpirun -np 16 --oversubscribe --allow-run-as-root \ + balance_dask_output \ + --indir $output_path/pretrain_lddl_128 \ + --num-shards 1280 + +mpirun \ + -np 16 \ + --oversubscribe \ + --allow-run-as-root \ + preprocess_bart_pretrain \ + --schedule mpi \ + --target-seq-length 512 \ + --wikipedia $wiki_path/source \ + --common-crawl $common_crawl_path/source \ + --open-webtext $openwebtext_path/source \ + --sink $output_path/pretrain_lddl_512 \ + --num-blocks 1280 + +mpirun -np 16 --oversubscribe --allow-run-as-root \ + balance_dask_output \ + --indir $output_path/pretrain_lddl_512 \ + --num-shards 1280 diff --git a/PyTorch/LanguageModeling/BART/scripts/run_eval_summarization.sh b/PyTorch/LanguageModeling/BART/scripts/run_eval_summarization.sh index 99b2e7f55..645110954 100755 --- a/PyTorch/LanguageModeling/BART/scripts/run_eval_summarization.sh +++ b/PyTorch/LanguageModeling/BART/scripts/run_eval_summarization.sh @@ -1,14 +1,3 @@ -INIT_CKPT=${1} - -if [ ! -f "$INIT_CKPT" ]; then - echo "$INIT_CKPT does not exist. Cannot run inference without a valid checkpoint" - exit -1 -fi - -PRED_BS=${2:-96} -NUM_GPU=${3:-8} -PRECISION=${4:-fp16} -EVAL_BEAMS=${5:-4} # Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,11 +13,23 @@ EVAL_BEAMS=${5:-4} # limitations under the License. # ============================================================================== +INIT_CKPT=${1} + +if [ ! -f "$INIT_CKPT" ]; then + echo "$INIT_CKPT does not exist. Cannot run inference without a valid checkpoint" + exit -1 +fi + +PRED_BS=${2:-96} +NUM_GPU=${3:-8} +PRECISION=${4:-fp16} +EVAL_BEAMS=${5:-4} MAX_SOURCE_LEN=${6:-1024} MAX_TARGET_LEN=${7:-142} DATA_DIR=${8:-data/cnn_dm} CONFIG_PATH=${9:-"configs/config.json"} +PRELN=${10:-true} printf -v TAG "bart_pyt_inference" DATESTAMP=`date +'%y%m%d%H%M%S'` @@ -38,12 +39,21 @@ mkdir -p $RESULTS_DIR if [ "$PRECISION" = "fp16" ] ; then echo "fp16 activated!" USE_FP16="--fp16" - +elif [ "$PRECISION" = "bf16" ] ; then + echo "bf16 activated!" + USE_FP16="--bf16" else echo "fp32/tf32 activated!" USE_FP16="" fi +if [ "$PRELN" = "true" ] ; then + echo "Use PreLN" + USE_FP16="--pre_ln $USE_FP16" +else + echo "Use PostLN" +fi + python -m torch.distributed.launch --nproc_per_node=$NUM_GPU run_eval.py \ --task summarization \ --bs ${PRED_BS} --max_source_length=${MAX_SOURCE_LEN} --max_target_length=${MAX_TARGET_LEN} \ diff --git a/PyTorch/LanguageModeling/BART/scripts/run_inference_benchmark.sh b/PyTorch/LanguageModeling/BART/scripts/run_inference_benchmark.sh index 64151770f..58c3f60fd 100755 --- a/PyTorch/LanguageModeling/BART/scripts/run_inference_benchmark.sh +++ b/PyTorch/LanguageModeling/BART/scripts/run_inference_benchmark.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + # Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,4 +61,4 @@ for NUM_GPU in 1 4 8; do done -done \ No newline at end of file +done diff --git a/PyTorch/LanguageModeling/BART/scripts/run_pretraining.sh b/PyTorch/LanguageModeling/BART/scripts/run_pretraining.sh new file mode 100644 index 000000000..7d919393c --- /dev/null +++ b/PyTorch/LanguageModeling/BART/scripts/run_pretraining.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +echo "Container nvidia build = " $NVIDIA_BUILD_ID + +train_batch_size_phase1=${1:-200} +train_batch_size_phase2=${2:-32} +learning_rate_phase1=${3:-"5e-3"} +learning_rate_phase2=${4:-"4e-3"} +precision=${5:-"bf16"} +use_preln=${6:-"true"} +num_gpus=${7:-8} +warmup_steps_phase1=${8:-"2166"} +warmup_steps_phase2=${9:-"200"} +train_steps_phase1=${10:-95040} +train_steps_phase2=${11:-7560} +save_checkpoints_steps=${12:-100} +num_accumulation_steps_phase1=${13:-40} +num_accumulation_steps_phase2=${14:-120} +config_path=${15:-"configs/config.json"} + +DATA_DIR=data +export DATA_DIR=$DATA_DIR + +printf -v TAG "bart_pyt_pretraining" +RESULTS_DIR=${RESULTS_DIR:-results/${TAG}} + +printf "Saving checkpoints to %s\n" "$RESULTS_DIR" +export RESULTS_DIR=$RESULTS_DIR + +printf -v SCRIPT_ARGS "%d %d %e %e %s %s %d %d %d %d %d %d %d %d %s" \ + $train_batch_size_phase1 $train_batch_size_phase2 $learning_rate_phase1 \ + $learning_rate_phase2 "$precision" "$use_preln" $num_gpus $warmup_steps_phase1 \ + $warmup_steps_phase2 $train_steps_phase1 $train_steps_phase2 $save_checkpoints_steps \ + $num_accumulation_steps_phase1 $num_accumulation_steps_phase2 "$config_path" + +set -x +# RUN PHASE 1 +bash scripts/run_pretraining_phase1.sh $SCRIPT_ARGS + +# RUN PHASE 2 +bash scripts/run_pretraining_phase2.sh $SCRIPT_ARGS +set +x diff --git a/PyTorch/LanguageModeling/BART/scripts/run_pretraining_phase1.sh b/PyTorch/LanguageModeling/BART/scripts/run_pretraining_phase1.sh new file mode 100644 index 000000000..040af7b1d --- /dev/null +++ b/PyTorch/LanguageModeling/BART/scripts/run_pretraining_phase1.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash + +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +echo "Container nvidia build = " $NVIDIA_BUILD_ID + +train_batch_size_phase1=${1:-200} +train_batch_size_phase2=${2:-32} +learning_rate_phase1=${3:-"5e-3"} +learning_rate_phase2=${4:-"4e-3"} +precision=${5:-"bf16"} +use_preln=${6:-"true"} +num_gpus=${7:-8} +warmup_steps_phase1=${8:-"2166"} +warmup_steps_phase2=${9:-"200"} +train_steps_phase1=${10:-95040} +train_steps_phase2=${11:-7560} +save_checkpoints_steps=${12:-100} +num_accumulation_steps_phase1=${13:-40} +num_accumulation_steps_phase2=${14:-120} +config_path=${15:-"configs/config.json"} + +DATA_DIR=${DATA_DIR:-data} +RESULTS_DIR=${RESULTS_DIR:-results} + +RESULTS_DIR_PHASE1=${RESULTS_DIR}/phase_1 +mkdir -m 777 -p $RESULTS_DIR_PHASE1 + +DATESTAMP=`date +'%y%m%d%H%M%S'` +LOGFILE=$RESULTS_DIR_PHASE1/$DATESTAMP.log +printf "Logs written to %s\n" "$LOGFILE" + +SOURCE_LEN=128 + +if [ "$precision" = "fp16" ] ; then + echo "fp16 activated!" + USE_FP16="--fp16" +elif [ "$precision" = "bf16" ] ; then + echo "bf16 activated!" + USE_FP16="--bf16" +else + echo "fp32/tf32 activated!" + USE_FP16="" +fi + +if [ "$use_preln" = "true" ] ; then + echo "Trained with PreLN" + USE_FP16="--pre_ln $USE_FP16" +else + echo "Trained with PostLN" +fi + +export TOKENIZERS_PARALLELISM=true; +python -m torch.distributed.launch --nproc_per_node=${num_gpus} pretrain.py \ +--data_dir=${DATA_DIR}/pretrain_lddl_${SOURCE_LEN} \ +--config_path=${config_path} \ +--output_dir=${RESULTS_DIR_PHASE1} \ +--num_workers 4 \ +--learning_rate=${learning_rate_phase1} \ +${USE_FP16} \ +--do_train \ +--train_batch_size=${train_batch_size_phase1} --gradient_accumulation_steps=${num_accumulation_steps_phase1} \ +--max_steps=${train_steps_phase1} --warmup_steps=${warmup_steps_phase1} \ +--max_source_length=${SOURCE_LEN} \ +--lr_scheduler polynomial \ +--label_smoothing 0 \ +--weight_decay 0.1 \ +--dropout 0.1 --attention_dropout 0.1 --gradient_clip_val=0.1 \ +--resume_from_checkpoint=True \ +--save_checkpoint_steps=${save_checkpoints_steps} --log_freq=${save_checkpoints_steps} \ +--allreduce_post_accumulation_half_precision \ +--seed $RANDOM --lamb |& tee -a ${LOGFILE} diff --git a/PyTorch/LanguageModeling/BART/scripts/run_pretraining_phase2.sh b/PyTorch/LanguageModeling/BART/scripts/run_pretraining_phase2.sh new file mode 100644 index 000000000..5b9f21224 --- /dev/null +++ b/PyTorch/LanguageModeling/BART/scripts/run_pretraining_phase2.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +echo "Container nvidia build = " $NVIDIA_BUILD_ID + +train_batch_size_phase1=${1:-200} +train_batch_size_phase2=${2:-32} +learning_rate_phase1=${3:-"5e-3"} +learning_rate_phase2=${4:-"4e-3"} +precision=${5:-"bf16"} +use_preln=${6:-"true"} +num_gpus=${7:-8} +warmup_steps_phase1=${8:-"2166"} +warmup_steps_phase2=${9:-"200"} +train_steps_phase1=${10:-95040} +train_steps_phase2=${11:-7560} +save_checkpoints_steps=${12:-100} +num_accumulation_steps_phase1=${13:-40} +num_accumulation_steps_phase2=${14:-120} +config_path=${15:-"configs/config.json"} + +DATA_DIR=${DATA_DIR:-data} +RESULTS_DIR=${RESULTS_DIR:-results} + +RESULTS_DIR_PHASE2=${RESULTS_DIR}/phase_2 +mkdir -m 777 -p $RESULTS_DIR_PHASE2 + +DATESTAMP=`date +'%y%m%d%H%M%S'` +LOGFILE=$RESULTS_DIR_PHASE2/$DATESTAMP.log +printf "Logs written to %s\n" "$LOGFILE" + +SOURCE_LEN=512 + +if [ "$precision" = "fp16" ] ; then + echo "fp16 activated!" + USE_FP16="--fp16" +elif [ "$precision" = "bf16" ] ; then + echo "bf16 activated!" + USE_FP16="--bf16" +else + echo "fp32/tf32 activated!" + USE_FP16="" +fi + +if [ "$use_preln" = "true" ] ; then + echo "Trained with PreLN" + USE_FP16="--pre_ln $USE_FP16" +else + echo "Trained with PostLN" +fi + +PHASE1_CKPT=${PHASE1_CKPT:-"${RESULTS_DIR}/phase_1/_step${train_steps_phase1}.ckpt"} + +export TOKENIZERS_PARALLELISM=true; +python -m torch.distributed.launch --nproc_per_node=${num_gpus} pretrain.py \ +--data_dir=${DATA_DIR}/pretrain_lddl_${SOURCE_LEN} \ +--config_path=${config_path} \ +--output_dir=${RESULTS_DIR_PHASE2} \ +--num_workers 4 \ +--learning_rate=${learning_rate_phase2} \ +${USE_FP16} \ +--do_train \ +--train_batch_size=${train_batch_size_phase2} --gradient_accumulation_steps=${num_accumulation_steps_phase2} \ +--max_steps=${train_steps_phase2} --warmup_steps=${warmup_steps_phase2} \ +--max_source_length=${SOURCE_LEN} \ +--lr_scheduler polynomial \ +--label_smoothing 0 \ +--weight_decay 0.1 \ +--dropout 0.1 --attention_dropout 0.1 --gradient_clip_val=0.1 \ +--resume_from_checkpoint=${PHASE1_CKPT} --load_model_weights_only \ +--save_checkpoint_steps=${save_checkpoints_steps} --log_freq=${save_checkpoints_steps} \ +--allreduce_post_accumulation_half_precision \ +--seed $RANDOM --lamb |& tee -a ${LOGFILE} diff --git a/PyTorch/LanguageModeling/BART/scripts/run_summarization.sh b/PyTorch/LanguageModeling/BART/scripts/run_summarization.sh index 2ee06ab74..a5a346d63 100755 --- a/PyTorch/LanguageModeling/BART/scripts/run_summarization.sh +++ b/PyTorch/LanguageModeling/BART/scripts/run_summarization.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + # Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,30 +16,39 @@ # ============================================================================== DATA_DIR=${1:-data/cnn_dm/} -CONFIG_PATH=${2:-"configs/config.json"} -NUM_GPU=${3:-2} -LR=${4:-1e-4} -BS=${5:-8} -ACCUM=${6:-1} -PREC=${7:-"fp16"} -TRAIN_STEPS=${8:-20000} -WARMUP_STEPS=${9:-500} -MAX_SOURCE_LEN=${10:-1024} -MAX_TARGET_LEN=${11:-142} -EVAL_BEAMS=${12:-4} -EVAL_BS=${13:-128} -PRED_BS=${14:-64} -VAL_CHECK_INTERVAL=${15:-0.3} -PATIENCE=${16:-2} +CKPT_PATH=${2:-data/nvidia_pretrained/bart_large} +CONFIG_PATH=${3:-"configs/config.json"} +NUM_GPU=${4:-8} +LR=${5:-1.25e-4} +BS=${6:-40} +ACCUM=${7:-1} +PREC=${8:-"bf16"} +TRAIN_STEPS=${9:-2000} +WARMUP_STEPS=${10:-50} +MAX_SOURCE_LEN=${11:-1024} +MAX_TARGET_LEN=${12:-142} +EVAL_BEAMS=${13:-4} +EVAL_BS=${14:-128} +PRED_BS=${15:-64} +PRELN=${16:-true} if [ "$PREC" = "fp16" ] ; then echo "fp16 activated!" USE_FP16="--fp16" +elif [ "$PREC" = "bf16" ] ; then + echo "bf16 activated!" + USE_FP16="--bf16" else echo "fp32/tf32 activated!" USE_FP16="" fi +if [ "$PRELN" = "true" ] ; then + echo "Trained with PreLN" + USE_FP16="--pre_ln $USE_FP16" +else + echo "Trained with PostLN" +fi printf -v TAG "bart_pyt" DATESTAMP=`date +'%y%m%d%H%M%S'` @@ -45,7 +56,7 @@ RESULTS_DIR=${RESULTS_DIR:-results/${TAG}_${DATESTAMP}} mkdir -p ${RESULTS_DIR} export TOKENIZERS_PARALLELISM="true" -python finetune.py \ +python -m torch.distributed.launch --nproc_per_node=${NUM_GPU:-8} finetune.py \ --data_dir=${DATA_DIR} \ --config_path=${CONFIG_PATH} \ --output_dir=${RESULTS_DIR} \ @@ -57,7 +68,6 @@ python finetune.py \ --train_batch_size=${BS} --gradient_accumulation_steps=${ACCUM} \ --eval_batch_size=${EVAL_BS} \ --max_steps ${TRAIN_STEPS} --warmup_steps ${WARMUP_STEPS} \ - --min_epochs=0 --val_check_interval ${VAL_CHECK_INTERVAL} \ --max_source_length=${MAX_SOURCE_LEN} --max_target_length=${MAX_TARGET_LEN} \ --val_max_target_length=${MAX_TARGET_LEN} --eval_max_gen_length=${MAX_TARGET_LEN} \ --sortish_sampler \ @@ -65,18 +75,18 @@ python finetune.py \ --label_smoothing 0.1 \ --weight_decay 0.1 \ --dropout 0.1 --attention_dropout 0.1 --gradient_clip_val=0.1 \ - --early_stopping_patience=${PATIENCE} \ - --num_sanity_val_steps=0 --eval_beams 0 --freeze_embeds \ - --amp_level=O1 --seed ${SEED:-42} \ + --eval_beams 0 --freeze_embeds \ + --seed ${SEED:-42} \ + --resume_from_checkpoint=${CKPT_PATH} --load_model_weights_only \ ${@:17} |& tee ${RESULTS_DIR}/joblog.log echo "completed training! Begin test" |& tee -a ${RESULTS_DIR}/joblog.log -INIT_CKPT=$(ls ${RESULTS_DIR}/_epoch*.ckpt | sort -n | tail -1) +INIT_CKPT=$(ls ${RESULTS_DIR}/final_step.ckpt | sort -n | tail -1) -python -m torch.distributed.launch --nproc_per_node=$NUM_GPU run_eval.py \ +python -m torch.distributed.launch --nproc_per_node=${NUM_GPU:-8} run_eval.py \ --task summarization \ --bs ${PRED_BS} --max_source_length=${MAX_SOURCE_LEN} --max_target_length=${MAX_TARGET_LEN} \ --eval_max_gen_length=${MAX_TARGET_LEN} --eval_beams=${EVAL_BEAMS} ${USE_FP16} \ diff --git a/PyTorch/LanguageModeling/BART/scripts/run_training_benchmark.sh b/PyTorch/LanguageModeling/BART/scripts/run_training_benchmark.sh index e0340d837..200485f00 100755 --- a/PyTorch/LanguageModeling/BART/scripts/run_training_benchmark.sh +++ b/PyTorch/LanguageModeling/BART/scripts/run_training_benchmark.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + # Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -68,4 +70,4 @@ for NUM_GPU in 1 4 8; do echo "$NUM_GPU $precision $perf" |& tee ${RESULTS_DIR}/training_benchmark.log done -done \ No newline at end of file +done diff --git a/PyTorch/LanguageModeling/BART/lightning_base.py b/PyTorch/LanguageModeling/BART/training_base.py similarity index 54% rename from PyTorch/LanguageModeling/BART/lightning_base.py rename to PyTorch/LanguageModeling/BART/training_base.py index 1b10a0d2b..fcefd61c6 100755 --- a/PyTorch/LanguageModeling/BART/lightning_base.py +++ b/PyTorch/LanguageModeling/BART/training_base.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,9 +18,7 @@ import os from pathlib import Path from typing import Any, Dict - -import pytorch_lightning as pl -from pytorch_lightning.utilities import rank_zero_info +import time from bart.configuration.configuration_bart import BartConfig from bart.tokenization.tokenization_bart import BartTokenizer @@ -34,11 +32,14 @@ get_polynomial_decay_schedule_with_warmup, ) from utils.gpu_affinity import set_affinity -from utils.distributed_utils import get_rank, get_device_count -from apex.optimizers import FusedAdam, FusedLAMB +from utils.distributed_utils import get_rank, get_device_count, get_world_size +from utils.utils import get_readable_time, Mean +from apex.optimizers import FusedAdam, FusedMixedPrecisionLamb +import dllogger logger = logging.getLogger(__name__) + MODEL_MODES = { "question-answering": BartForQuestionAnswering, "pretraining": PretrainedBartModel, @@ -62,7 +63,7 @@ arg_to_scheduler_metavar = "{" + ", ".join(arg_to_scheduler_choices) + "}" -class BaseTransformer(pl.LightningModule): +class BaseTransformer(): def __init__( self, hparams: argparse.Namespace, @@ -75,12 +76,9 @@ def __init__( ): """Initialize a model, tokenizer and config.""" super().__init__() - # TODO: move to self.save_hyperparameters() - # self.save_hyperparameters() - # can also expand arguments into trainer signature for easier reading - self.save_hyperparameters(hparams) self.step_count = 0 + self.hparams = hparams self.output_dir = Path(self.hparams.output_dir) cache_dir = self.hparams.cache_dir if self.hparams.cache_dir else None if config is None: @@ -117,6 +115,9 @@ def __init__( else: self.model = model + def __call__(self, input_ids, **kwargs): + return self.forward(input_ids, **kwargs) + def load_hf_checkpoint(self, *args, **kwargs): self.model = self.model_type.from_pretrained(*args, **kwargs) @@ -144,9 +145,15 @@ def configure_optimizers(self): }, ] if self.hparams.lamb: - optimizer = FusedLAMB( - optimizer_grouped_parameters, lr=self.hparams.learning_rate, eps=self.hparams.adam_epsilon) - + optimizer_reduced_precision_type = self.config.dtype if self.hparams.allreduce_post_accumulation_half_precision else None + optimizer = FusedMixedPrecisionLamb( + optimizer_grouped_parameters, + lr=self.hparams.learning_rate, + eps=self.hparams.adam_epsilon, + max_grad_norm=self.hparams.gradient_clip_val, + reduced_precision_dtype=optimizer_reduced_precision_type) + elif self.hparams.allreduce_post_accumulation_half_precision: + raise ValueError("--allreduce_post_accumulation_half_precision is only supported on LAMB optimizer") elif self.hparams.adafactor: optimizer = Adafactor( optimizer_grouped_parameters, lr=self.hparams.learning_rate, scale_parameter=False, relative_step=False @@ -178,15 +185,11 @@ def total_steps(self) -> int: dataset_size = len(self.train_loader.dataset) return (dataset_size / effective_batch_size) * self.hparams.max_epochs - def setup(self, mode): - if mode == "fit": - self.train_loader = self.get_dataloader("train", self.hparams.train_batch_size, shuffle=True) - def get_dataloader(self, type_path, batch_size, shuffle=False): raise NotImplementedError("You must implement this for your task") def train_dataloader(self): - return self.train_loader + return self.get_dataloader("train", self.hparams.train_batch_size, shuffle=True) def val_dataloader(self): return self.get_dataloader("dev", self.hparams.eval_batch_size, shuffle=False) @@ -204,7 +207,6 @@ def _feature_file(self, mode): ), ) - @pl.utilities.rank_zero_only def on_save_checkpoint(self, checkpoint: Dict[str, Any]) -> None: save_path = self.output_dir.joinpath("best_tfmr") self.model.config.save_step = self.step_count @@ -220,6 +222,13 @@ def add_model_specific_args(parser, root_dir): type=str, help="Where do you want to store the pre-trained models downloaded from s3", ) + parser.add_argument( + "--resume_from_checkpoint", + type=str, + help="""Path/URL of the checkpoint from which training is resumed. If there is no checkpoint file at + the path, start from scratch. If resuming from mid-epoch checkpoint, training will start from + the beginning of the next epoch.""", + ) parser.add_argument( "--encoder_layerdrop", type=float, @@ -250,7 +259,9 @@ def add_model_specific_args(parser, root_dir): help="Learning rate scheduler", ) parser.add_argument("--weight_decay", default=0.0, type=float, help="Weight decay if we apply some.") + parser.add_argument("--gradient_clip_val", default=0.5, type=float, help="The value at which to clip gradients.") parser.add_argument("--adam_epsilon", default=1e-8, type=float, help="Epsilon for Adam optimizer.") + parser.add_argument("--max_steps", default=10, type=int, help="Stop training after this number of steps.") parser.add_argument("--warmup_steps", default=0, type=int, help="Linear warmup over warmup_steps.") parser.add_argument("--num_workers", default=4, type=int, help="kwarg passed to DataLoader") parser.add_argument("--min_num_train_epochs", dest="min_epochs", default=0, type=int) @@ -265,36 +276,12 @@ def add_model_specific_args(parser, root_dir): 'socket_unique_continuous', 'disabled'], help='type of CPU affinity') - - -class LoggingCallback(pl.Callback): - def on_batch_end(self, trainer, pl_module): - lr_scheduler = trainer.lr_schedulers[0]["scheduler"] - lrs = {f"lr_group_{i}": lr for i, lr in enumerate(lr_scheduler.get_lr())} - pl_module.logger.log_metrics(lrs) - - def on_validation_end(self, trainer: pl.Trainer, pl_module: pl.LightningModule): - rank_zero_info("***** Validation results *****") - metrics = trainer.callback_metrics - # Log results - for key in sorted(metrics): - if key not in ["log", "progress_bar"]: - rank_zero_info("{} = {}\n".format(key, str(metrics[key]))) - - def on_test_end(self, trainer: pl.Trainer, pl_module: pl.LightningModule): - rank_zero_info("***** Test results *****") - metrics = trainer.callback_metrics - # Log and save results to file - output_test_results_file = os.path.join(pl_module.hparams.output_dir, "test_results.txt") - with open(output_test_results_file, "w") as writer: - for key in sorted(metrics): - if key not in ["log", "progress_bar"]: - rank_zero_info("{} = {}\n".format(key, str(metrics[key]))) - writer.write("{} = {}\n".format(key, str(metrics[key]))) - + parser.add_argument('--allreduce_post_accumulation_half_precision', + default=False, + action='http://github.com/store_true', + help="Whether to do fp16/bf16 allreduce post accumulation.") def add_generic_args(parser, root_dir) -> None: - # TODO(SS): allow all pl args? parser = pl.Trainer.add_argparse_args(parser) parser.add_argument( "--output_dir", default=None, @@ -305,7 +292,12 @@ def add_generic_args(parser, root_dir) -> None: parser.add_argument( "--fp16", action="http://github.com/store_true", - help="Whether to use 16-bit (mixed) precision (through NVIDIA apex) instead of 32-bit", + help="Whether to use 16-bit (mixed) precision instead of 32-bit", + ) + parser.add_argument( + "--bf16", + action="http://github.com/store_true", + help="Whether to use BFloat 16 mixed precision instead of 32-bit", ) parser.add_argument("--n_tpu_cores", dest="tpu_cores", type=int) parser.add_argument("--max_grad_norm", dest="gradient_clip_val", default=1.0, type=float, help="Max gradient norm") @@ -326,63 +318,185 @@ def add_generic_args(parser, root_dir) -> None: required=True, help="The input data dir. Should contain the training files for the CoNLL-2003 NER task.", ) - - -def generic_train( - model: BaseTransformer, - args: argparse.Namespace, - logging_callback=None, - checkpoint_callback=None, - extra_callbacks=[], - logger=True, # can pass WandbLogger() here - **extra_train_kwargs -): - pl.seed_everything(args.seed) - - # init model - odir = Path(model.hparams.output_dir) - odir.mkdir(exist_ok=True) - - # add custom checkpoints - if checkpoint_callback is None: - checkpoint_callback = pl.callbacks.ModelCheckpoint( - filepath=args.output_dir, prefix="checkpoint", monitor="val_loss", mode="min", save_top_k=1 - ) - if logging_callback is None: - logging_callback = LoggingCallback() - - train_params = {} - - train_params["limit_val_batches"] = 2 - - # TODO: remove with PyTorch 1.6 since pl uses native amp - if args.fp16: - train_params["precision"] = 16 - train_params["amp_level"] = args.amp_level - - if args.gpus > 1 or args.num_nodes > 1: - train_params["distributed_backend"] = "ddp" - train_params["accelerator"] = "ddp" - - trainer = pl.Trainer.from_argparse_args( - args, - weights_summary=None, - callbacks=[logging_callback] + extra_callbacks, - logger=logger, - checkpoint_callback=checkpoint_callback, - **train_params, + parser.add_argument("--log_freq", type=int, default=100, help="Log every X updates steps.") + parser.add_argument("--save_checkpoint_steps", type=int, default=100, required=False, help="How many checkpoints to save") + parser.add_argument( + "--profile", + action="http://github.com/store_true", + ) + parser.add_argument("--pre_ln", + default=True, + action='http://github.com/store_true', + help="Whether to use Pre-LN architecture." ) - if args.affinity != 'disabled': - affinity = set_affinity( - get_rank(), - get_device_count(), - args.affinity - ) - print(f'{get_rank()}: thread affinity: {affinity}') +def save_checkpoint(args, checkpoints, model, optimizer, scaler, step): + output_filename = os.path.join(args.output_dir, "_step{}.ckpt".format(step)) + if get_rank() == 0: + model_to_save = model + while(hasattr(model_to_save, "module")): + model_to_save = model_to_save.module + torch.save({"model": model_to_save.state_dict(), + "optimizer": optimizer.state_dict(), + "scaler": scaler.state_dict()}, + output_filename) - if args.do_train: - trainer.fit(model) +def train_one_step(args, trainer, optimizer, scheduler, features, local_step, scaler): + if args.fp16: + cast_dtype = torch.float16 + elif args.bf16: + cast_dtype = torch.bfloat16 + else: + cast_dtype = None + with torch.cuda.amp.autocast(dtype=cast_dtype, enabled=(args.fp16 or args.bf16) and not args.allreduce_post_accumulation_half_precision): + result = trainer.training_step(features) + total_loss = result["loss"] + loss = total_loss + if args.accumulate_grad_batches > 1: + total_loss = total_loss / args.accumulate_grad_batches + + if local_step % args.accumulate_grad_batches == 0: + scaler.scale(total_loss).backward() + + if not args.lamb: + scaler.unscale_(optimizer) + torch.nn.utils.clip_grad_norm_(trainer.model.parameters(), args.gradient_clip_val) + + scheduler.step() # Update learning rate schedule + scaler.step(optimizer) + optimizer.zero_grad() + + skip_optimizer_step = scaler._found_inf_per_device(optimizer)[args.device] if scaler.is_enabled() else 0 + result["log"]["skip_optimizer_step"] = int(skip_optimizer_step) + scaler.update() + else: + with trainer.model.no_sync(): + scaler.scale(total_loss).backward() + + return loss, result["log"] - return trainer \ No newline at end of file +def generic_train( + args, + trainer, + optimizer, + scheduler, + scaler, + checkpoints, + step, + **extra_train_kwargs +): + device = args.device + + # Set up dataset + dataloader = trainer.train_dataloader() + + # Set up metrics + metrics = {} + metrics["avg_train_throughput"] = Mean(name="train_perf") + metrics["total_loss"] = Mean(name="total_loss") + + trainer.model.train() + local_step = 0 + train_start, start_step = time.time(), step - 1 + resume_step = step + skipped_optimizer_steps = 0 + + if get_rank() == 0: + dllogger.metadata("avg_train_time", {"unit": "s"}) + dllogger.metadata("avg_train_throughput", {"unit": "seq/s"}) + + while step <= args.max_steps: + for batch in dataloader: + batch = {k: v.to(device) for k, v in batch.items()} + local_step += 1 + torch.cuda.synchronize() + iter_start = time.time() + + total_loss, logs = train_one_step(args, trainer, optimizer, scheduler, batch, local_step, scaler) + torch.cuda.synchronize() + train_perf = logs["bs"] * get_world_size() / (time.time() - iter_start) + + + metrics["total_loss"].update(total_loss) + metrics["avg_train_throughput"].update(train_perf) + if local_step % args.accumulate_grad_batches == 0: + static_optimizer_step = local_step // args.accumulate_grad_batches + skipped_optimizer_steps += logs["skip_optimizer_step"] + opt_step = static_optimizer_step - skipped_optimizer_steps + resume_step + + if args.log_freq > 0 and step != opt_step and ( + step % args.log_freq == 0 or step == args.max_steps): + log_info_dict = {k:v.result() for k, v in metrics.items()} + if get_rank() == 0: + dllogger.log(step=(step,), data=log_info_dict, verbosity=0) + print( + 'Step:{step:6d}, Loss:{total_loss:10.6f}, Perf:{train_perf:4.2f}, Loss Scaler: {loss_scale}, ' + 'Elapsed: {elapsed}, ETA: {eta}'.format( + step=step, + total_loss=total_loss, + train_perf=train_perf, + loss_scale=scaler.get_scale(), + elapsed=get_readable_time(time.time() - train_start), + eta=get_readable_time( + (time.time() - train_start) / (step - start_step) * (args.max_steps - step))), + flush=True + ) + + if step == args.max_steps: + final_metrics = {} + log_info_dict['avg_train_time'] = time.time() - train_start + for key, v in log_info_dict.items(): + val = torch.tensor(v, device=device) + torch.distributed.all_reduce(val, op=torch.distributed.ReduceOp.SUM) + val /= get_world_size() + final_metrics[key] = val.item() + if get_rank() == 0: + dllogger.log(step=(), data=log_info_dict, verbosity=0) + logger.info(' Step:{step:6d}, Loss:{total_loss:10.6f}, Perf:{avg_train_throughput:4.2f}, Train time:{avg_train_time}s'.format( + step=step, **final_metrics)) + + for key, m in metrics.items(): + if key != 'avg_train_throughput': + m.reset() + + if get_rank() == 0: + dllogger.flush() + + if args.save_checkpoint_steps > 0 and step != opt_step and \ + ((step % args.save_checkpoint_steps == 0 and step > 0) or step == args.max_steps): + save_checkpoint(args, checkpoints, trainer.model, optimizer, scaler, step) + logger.info(f" ** Saved model checkpoint for step {step}") + + step = opt_step + if step > args.max_steps: + break + +def generic_test( + args, + trainer +): + device = args.device + + # Set up dataset + dataloader = trainer.test_dataloader() + + metrics = {k: Mean(name=k) for k in trainer.loss_names + trainer.metric_names} + + for batch in dataloader: + batch = {k: v.to(device) for k, v in batch.items()} + + result_metric = trainer.test_step(batch) + for k, v in result_metric: + metrics[k].update(v) + + log_info_dict = {k:v.result() for k, v in metrics.items()} + final_metrics = {} + for key, v in log_info_dict.items(): + val = torch.tensor(v, device=device) + torch.distributed.all_reduce(val, op=torch.distributed.ReduceOp.SUM) + val /= get_world_size() + final_metrics[key] = val.item() + if get_rank() == 0: + dllogger.log(step=(), data=log_info_dict, verbosity=0) + print(final_metrics) diff --git a/PyTorch/LanguageModeling/BART/utils/activations.py b/PyTorch/LanguageModeling/BART/utils/activations.py index ccf685f9e..dad9f1175 100755 --- a/PyTorch/LanguageModeling/BART/utils/activations.py +++ b/PyTorch/LanguageModeling/BART/utils/activations.py @@ -1,3 +1,18 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + import logging import math diff --git a/PyTorch/LanguageModeling/BART/utils/callbacks.py b/PyTorch/LanguageModeling/BART/utils/callbacks.py index 48dfe1666..f73d8a9c5 100755 --- a/PyTorch/LanguageModeling/BART/utils/callbacks.py +++ b/PyTorch/LanguageModeling/BART/utils/callbacks.py @@ -157,7 +157,7 @@ def on_train_end(self, trainer: pl.Trainer, pl_module: pl.LightningModule): self.train_time = ((self.train_time * self.epochs) + all_reduce_time) / (self.epochs + 1) self.avg_steps_per_sec = ((self.avg_steps_per_sec * self.epochs) + all_reduce_avg_steps_per_sec) / (self.epochs + 1.0) -def get_checkpoint_callback(output_dir, metric, save_top_k=1, lower_is_better=False): +def get_checkpoint_callback(output_dir, metric, save_top_k=1): """Saves the best model by validation ROUGE2 score.""" monitor = f"val_{metric}" if metric == "rouge2": @@ -220,6 +220,17 @@ def on_batch_end(self, trainer: pl.Trainer, _): ckpt_path = os.path.join(self.output_dir, filename) trainer.save_checkpoint(ckpt_path) + def on_train_end(self, trainer: pl.Trainer, pl_module: pl.LightningModule): + + epoch = trainer.current_epoch + global_step = trainer.global_step + if self.use_modelcheckpoint_filename: + filename = trainer.checkpoint_callback.filename + else: + filename = f"{self.prefix}_epoch{epoch}_step{global_step}.ckpt" + ckpt_path = os.path.join(self.output_dir, filename) + trainer.save_checkpoint(ckpt_path) + def get_early_stopping_callback(metric, patience): return EarlyStopping( monitor=metric, # does this need avg? diff --git a/PyTorch/LanguageModeling/BART/utils/data_collator.py b/PyTorch/LanguageModeling/BART/utils/data_collator.py index f7173c23d..69968e9f5 100644 --- a/PyTorch/LanguageModeling/BART/utils/data_collator.py +++ b/PyTorch/LanguageModeling/BART/utils/data_collator.py @@ -1,3 +1,4 @@ +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The HuggingFace Team. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -656,7 +657,7 @@ class DataCollatorForBART(DataCollatorForLanguageModeling): Data collator used for language modeling. - collates batches of tensors, honoring their tokenizer's pad_token - - preprocesses batches for masked language modeling + - preprocesses batches for masked language modeling - includes sentence permutation and whole work masking """ permute_sentence_ratio: float = 1.0 @@ -816,7 +817,7 @@ def mask_tokens_span(self, inputs: torch.Tensor, mask_labels: torch.Tensor, atte inputs_left_shift = torch.cat((inputs[:, 1:], torch.zeros(inputs.shape[0],1)), dim=-1) mask_left_shift = torch.not_equal((inputs - inputs_left_shift), 0) mask = torch.cat((torch.full((inputs.shape[0],1),True), mask_left_shift[:, :-1]), dim=-1) | torch.not_equal(inputs, mask_token_id) - + inputs = [torch.masked_select(inputs[i,:], mask[i,:]) for i in range(inputs.shape[0])] if attention_mask is not None: attention_mask = [torch.masked_select(attention_mask[i, :], mask[i,:]) for i in range(attention_mask.shape[0])] diff --git a/PyTorch/LanguageModeling/BART/utils/data_utils.py b/PyTorch/LanguageModeling/BART/utils/data_utils.py index 41c5fcf93..f904ca18f 100755 --- a/PyTorch/LanguageModeling/BART/utils/data_utils.py +++ b/PyTorch/LanguageModeling/BART/utils/data_utils.py @@ -71,30 +71,3 @@ def get_dataset(self, type_path): src_lang="", tgt_lang="" ) return dataset - - - # def train_dataloader(self) -> DataLoader: - # dataloader = self.get_dataloader("train", batch_size=self.hparams.train_batch_size, shuffle=True) - # return dataloader - - # def val_dataloader(self) -> DataLoader: - # return self.get_dataloader("val", batch_size=self.hparams.eval_batch_size) - - # def test_dataloader(self) -> DataLoader: - # return self.get_dataloader("test", batch_size=self.hparams.eval_batch_size) - - # def __iter__(self): - # # index iterator - # epoch_indices = np.random.permutation(len(self.data) // self.batch_size) if self.shuffle \ - # else np.array(range(len(self.data) // self.batch_size)) - - # if self.labels: - # # sentence iterator - # for idx in epoch_indices: - # yield (self.data[idx: idx + self.batch_size], self.labels[idx: idx + self.batch_size]) - # else: - # # sentence iterator - # for idx in epoch_indices: - # yield self.data[idx: idx + self.batch_size] - # def __len__(self): - # return len(self.data) // self.batch_size \ No newline at end of file diff --git a/PyTorch/LanguageModeling/BART/utils/file_utils.py b/PyTorch/LanguageModeling/BART/utils/file_utils.py index 2346b7ff8..0a40a3539 100755 --- a/PyTorch/LanguageModeling/BART/utils/file_utils.py +++ b/PyTorch/LanguageModeling/BART/utils/file_utils.py @@ -1,3 +1,18 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + """ Utilities for working with the local dataset cache. This file is adapted from the AllenNLP library at https://github.com/allenai/allennlp diff --git a/PyTorch/LanguageModeling/BART/utils/generation_beam_search.py b/PyTorch/LanguageModeling/BART/utils/generation_beam_search.py index e98134e50..6c96d2eee 100644 --- a/PyTorch/LanguageModeling/BART/utils/generation_beam_search.py +++ b/PyTorch/LanguageModeling/BART/utils/generation_beam_search.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The HuggingFace Inc. team # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/utils/generation_logits_process.py b/PyTorch/LanguageModeling/BART/utils/generation_logits_process.py index 248289f74..8449a2658 100644 --- a/PyTorch/LanguageModeling/BART/utils/generation_logits_process.py +++ b/PyTorch/LanguageModeling/BART/utils/generation_logits_process.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 The HuggingFace Inc. team # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/utils/generation_utils.py b/PyTorch/LanguageModeling/BART/utils/generation_utils.py index 547177e75..0fbea1911 100755 --- a/PyTorch/LanguageModeling/BART/utils/generation_utils.py +++ b/PyTorch/LanguageModeling/BART/utils/generation_utils.py @@ -1,6 +1,6 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 The Google AI Language Team Authors, Facebook AI Research authors and The HuggingFace Inc. team. -# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -42,1009 +42,6 @@ logger = logging.getLogger(__name__) -# class GenerationMixin: -# """ -# A class contraining all of the functions supporting generation, to be used as a mixin in -# :class:`~transfomers.PreTrainedModel`. -# """ - -# def prepare_inputs_for_generation(self, input_ids, **kwargs): -# """ -# Implement in subclasses of :class:`~transfomers.PreTrainedModel` for custom behavior to prepare inputs in the -# generate method. -# """ -# return {"input_ids": input_ids} - -# def adjust_logits_during_generation(self, logits, **kwargs): -# """ -# Implement in subclasses of :class:`~transfomers.PreTrainedModel` for custom behavior to adjust the logits in -# the generate method. -# """ -# return logits - -# def _use_cache(self, outputs, use_cache): -# """During generation, decide whether to pass the `past` variable to the next forward pass.""" -# if len(outputs) <= 1 or use_cache is False: -# return False -# if hasattr(self.config, "mem_len") and self.config.mem_len == 0: -# return False -# return True - -# def enforce_repetition_penalty_(self, lprobs, batch_size, num_beams, prev_output_tokens, repetition_penalty): -# """ -# Enforce the repetition penalty (from the `CTRL paper `__). -# """ -# for i in range(batch_size * num_beams): -# for previous_token in set(prev_output_tokens[i].tolist()): -# # if score < 0 then repetition penalty has to multiplied to reduce the previous token probability -# if lprobs[i, previous_token] < 0: -# lprobs[i, previous_token] *= repetition_penalty -# else: -# lprobs[i, previous_token] /= repetition_penalty - -# def postprocess_next_token_scores( -# self, -# scores, -# input_ids, -# no_repeat_ngram_size, -# bad_words_ids, -# cur_len, -# min_length, -# max_length, -# eos_token_id, -# repetition_penalty, -# batch_size, -# num_beams, -# ): -# # repetition penalty (from CTRL paper https://arxiv.org/abs/1909.05858) -# if repetition_penalty != 1.0: -# self.enforce_repetition_penalty_( -# scores, batch_size, num_beams, input_ids, repetition_penalty, -# ) - -# # set eos token prob to zero if min_length is not reached -# if eos_token_id is not None and cur_len < min_length: -# scores[:, eos_token_id] = -float("inf") - -# if no_repeat_ngram_size > 0: -# # calculate a list of banned tokens to prevent repetitively generating the same ngrams -# num_batch_hypotheses = batch_size * num_beams -# # from fairseq: https://github.com/pytorch/fairseq/blob/a07cb6f40480928c9e0548b737aadd36ee66ac76/fairseq/sequence_generator.py#L345 -# banned_batch_tokens = calc_banned_ngram_tokens( -# input_ids, num_batch_hypotheses, no_repeat_ngram_size, cur_len -# ) -# for i, banned_tokens in enumerate(banned_batch_tokens): -# scores[i, banned_tokens] = -float("inf") - -# if bad_words_ids is not None: -# # Exclude EOS token (already processed) -# bad_words_ids = list(filter(lambda bad_token_seq: bad_token_seq != [eos_token_id], bad_words_ids)) -# # calculate a list of banned tokens according to bad words -# banned_tokens = calc_banned_bad_words_ids(input_ids.tolist(), bad_words_ids) -# # Modify the scores in place by setting the banned tokens logits to `-inf` -# set_scores_to_inf_for_banned_tokens(scores, banned_tokens) - -# return scores - -# @torch.no_grad() -# def generate( -# self, -# input_ids: Optional[torch.LongTensor] = None, -# max_length: Optional[int] = None, -# min_length: Optional[int] = None, -# do_sample: Optional[bool] = None, -# early_stopping: Optional[bool] = None, -# num_beams: Optional[int] = None, -# temperature: Optional[float] = None, -# top_k: Optional[int] = None, -# top_p: Optional[float] = None, -# repetition_penalty: Optional[float] = None, -# bad_words_ids: Optional[Iterable[int]] = None, -# bos_token_id: Optional[int] = None, -# pad_token_id: Optional[int] = None, -# eos_token_id: Optional[int] = None, -# length_penalty: Optional[float] = None, -# no_repeat_ngram_size: Optional[int] = None, -# num_return_sequences: Optional[int] = None, -# attention_mask: Optional[torch.LongTensor] = None, -# decoder_start_token_id: Optional[int] = None, -# use_cache: Optional[bool] = None, -# **model_specific_kwargs -# ) -> torch.LongTensor: -# r""" -# Generates sequences for models with a language modeling head. The method currently supports greedy decoding, -# beam-search decoding, sampling with temperature, sampling with top-k or nucleus sampling. - -# Adapted in part from `Facebook's XLM beam search code -# `__. - -# Apart from :obj:`input_ids` and :obj:`attention_mask`, all the arguments below will default to the value of the -# attribute of the same name inside the :class:`~transformers.PretrainedConfig` of the model. The default values -# indicated are the default values of those config. - -# Most of these parameters are explained in more detail in `this blog post -# `__. - -# Parameters: - -# input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`): -# The sequence used as a prompt for the generation. If :obj:`None` the method initializes -# it as an empty :obj:`torch.LongTensor` of shape :obj:`(1,)`. -# max_length (:obj:`int`, `optional`, defaults to 20): -# The maximum length of the sequence to be generated. -# min_length (:obj:`int`, `optional`, defaults to 10): -# The minimum length of the sequence to be generated. -# do_sample (:obj:`bool`, `optional`, defaults to :obj:`False`): -# Whether or not to use sampling ; use greedy decoding otherwise. -# early_stopping (:obj:`bool`, `optional`, defaults to :obj:`False`): -# Whether to stop the beam search when at least ``num_beams`` sentences are finished per batch or not. -# num_beams (:obj:`int`, `optional`, defaults to 1): -# Number of beams for beam search. 1 means no beam search. -# temperature (:obj:`float`, `optional`, defaults tp 1.0): -# The value used to module the next token probabilities. -# top_k (:obj:`int`, `optional`, defaults to 50): -# The number of highest probability vocabulary tokens to keep for top-k-filtering. -# top_p (:obj:`float`, `optional`, defaults to 1.0): -# If set to float < 1, only the most probable tokens with probabilities that add up to ``top_p`` or -# higher are kept for generation. -# repetition_penalty (:obj:`float`, `optional`, defaults to 1.0): -# The parameter for repetition penalty. 1.0 means no penalty. See `this paper -# `__ for more details. -# pad_token_id (:obj:`int`, `optional`): -# The id of the `padding` token. -# bos_token_id (:obj:`int`, `optional`): -# The id of the `beginning-of-sequence` token. -# eos_token_id (:obj:`int`, `optional`): -# The id of the `end-of-sequence` token. -# length_penalty (:obj:`float`, `optional`, defaults to 1.0): -# Exponential penalty to the length. 1.0 means no penalty. - -# Set to values < 1.0 in order to encourage the model to generate shorter sequences, to a value > 1.0 in -# order to encourage the model to produce longer sequences. -# no_repeat_ngram_size (:obj:`int`, `optional`, defaults to 0): -# If set to int > 0, all ngrams of that size can only occur once. -# bad_words_ids(:obj:`List[int]`, `optional`): -# List of token ids that are not allowed to be generated. In order to get the tokens of the words that -# should not appear in the generated text, use :obj:`tokenizer.encode(bad_word, add_prefix_space=True)`. -# num_return_sequences(:obj:`int`, `optional`, defaults to 1): -# The number of independently computed returned sequences for each element in the batch. -# attention_mask (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`): -# Mask to avoid performing attention on padding token indices. Mask values are in ``[0, 1]``, 1 for -# tokens that are not masked, and 0 for masked tokens. - -# If not provided, will default to a tensor the same shape as :obj:`input_ids` that masks the pad token. - -# `What are attention masks? <../glossary.html#attention-mask>`__ -# decoder_start_token_id (:obj:`int`, `optional`): -# If an encoder-decoder model starts decoding with a different token than `bos`, the id of that token. -# use_cache: (:obj:`bool`, `optional`, defaults to :obj:`True`): -# Whether or not the model should use the past last key/values attentions (if applicable to the model) to -# speed up decoding. -# model_specific_kwargs: -# Additional model specific kwargs will be forwarded to the :obj:`forward` function of the model. - -# Return: - -# :obj:`torch.LongTensor` of shape :obj:`(batch_size * num_return_sequences, sequence_length)`: -# The generated sequences. The second dimension (sequence_length) is either equal to :obj:`max_length` or -# shorter if all batches finished early due to the :obj:`eos_token_id`. - -# Examples:: - -# tokenizer = AutoTokenizer.from_pretrained('distilgpt2') # Initialize tokenizer -# model = AutoModelWithLMHead.from_pretrained('distilgpt2') # Download model and configuration from S3 and cache. -# outputs = model.generate(max_length=40) # do greedy decoding -# print('Generated: {}'.format(tokenizer.decode(outputs[0], skip_special_tokens=True))) - -# tokenizer = AutoTokenizer.from_pretrained('openai-gpt') # Initialize tokenizer -# model = AutoModelWithLMHead.from_pretrained('openai-gpt') # Download model and configuration from S3 and cache. -# input_context = 'The dog' -# input_ids = tokenizer.encode(input_context, return_tensors='pt') # encode input context -# outputs = model.generate(input_ids=input_ids, num_beams=5, num_return_sequences=3, temperature=1.5) # generate 3 independent sequences using beam search decoding (5 beams) with sampling from initial context 'The dog' -# for i in range(3): # 3 output sequences were generated -# print('Generated {}: {}'.format(i, tokenizer.decode(outputs[i], skip_special_tokens=True))) - -# tokenizer = AutoTokenizer.from_pretrained('distilgpt2') # Initialize tokenizer -# model = AutoModelWithLMHead.from_pretrained('distilgpt2') # Download model and configuration from S3 and cache. -# input_context = 'The dog' -# input_ids = tokenizer.encode(input_context, return_tensors='pt') # encode input context -# outputs = model.generate(input_ids=input_ids, max_length=40, temperature=0.7, num_return_sequences=3, do_sample=True) # generate 3 candidates using sampling -# for i in range(3): # 3 output sequences were generated -# print('Generated {}: {}'.format(i, tokenizer.decode(outputs[i], skip_special_tokens=True))) - -# tokenizer = AutoTokenizer.from_pretrained('ctrl') # Initialize tokenizer -# model = AutoModelWithLMHead.from_pretrained('ctrl') # Download model and configuration from S3 and cache. -# input_context = 'Legal My neighbor is' # "Legal" is one of the control codes for ctrl -# input_ids = tokenizer.encode(input_context, return_tensors='pt') # encode input context -# outputs = model.generate(input_ids=input_ids, max_length=50, temperature=0.7, repetition_penalty=1.2) # generate sequences -# print('Generated: {}'.format(tokenizer.decode(outputs[0], skip_special_tokens=True))) - -# tokenizer = AutoTokenizer.from_pretrained('gpt2') # Initialize tokenizer -# model = AutoModelWithLMHead.from_pretrained('gpt2') # Download model and configuration from S3 and cache. -# input_context = 'My cute dog' # "Legal" is one of the control codes for ctrl -# bad_words_ids = [tokenizer.encode(bad_word, add_prefix_space=True) for bad_word in ['idiot', 'stupid', 'shut up']] -# input_ids = tokenizer.encode(input_context, return_tensors='pt') # encode input context -# outputs = model.generate(input_ids=input_ids, max_length=100, do_sample=True, bad_words_ids=bad_words_ids) # generate sequences without allowing bad_words to be generated -# """ - -# # We cannot generate if the model does not have a LM head -# if self.get_output_embeddings() is None: -# raise AttributeError( -# "You tried to generate sequences with a model that does not have a LM Head." -# "Please use another model class (e.g. `OpenAIGPTLMHeadModel`, `XLNetLMHeadModel`, `GPT2LMHeadModel`, `CTRLLMHeadModel`, `T5WithLMHeadModel`, `TransfoXLLMHeadModel`, `XLMWithLMHeadModel`, `BartForConditionalGeneration` )" -# ) - -# max_length = max_length if max_length is not None else self.config.max_length -# min_length = min_length if min_length is not None else self.config.min_length -# do_sample = do_sample if do_sample is not None else self.config.do_sample -# early_stopping = early_stopping if early_stopping is not None else self.config.early_stopping -# use_cache = use_cache if use_cache is not None else self.config.use_cache -# num_beams = num_beams if num_beams is not None else self.config.num_beams -# temperature = temperature if temperature is not None else self.config.temperature -# top_k = top_k if top_k is not None else self.config.top_k -# top_p = top_p if top_p is not None else self.config.top_p -# repetition_penalty = repetition_penalty if repetition_penalty is not None else self.config.repetition_penalty -# bos_token_id = bos_token_id if bos_token_id is not None else self.config.bos_token_id -# pad_token_id = pad_token_id if pad_token_id is not None else self.config.pad_token_id -# eos_token_id = eos_token_id if eos_token_id is not None else self.config.eos_token_id -# length_penalty = length_penalty if length_penalty is not None else self.config.length_penalty -# no_repeat_ngram_size = ( -# no_repeat_ngram_size if no_repeat_ngram_size is not None else self.config.no_repeat_ngram_size -# ) -# bad_words_ids = bad_words_ids if bad_words_ids is not None else self.config.bad_words_ids -# num_return_sequences = ( -# num_return_sequences if num_return_sequences is not None else self.config.num_return_sequences -# ) -# decoder_start_token_id = ( -# decoder_start_token_id if decoder_start_token_id is not None else self.config.decoder_start_token_id -# ) - -# if input_ids is not None: -# batch_size = input_ids.shape[0] # overriden by the input batch_size -# else: -# batch_size = 1 - -# assert isinstance(max_length, int) and max_length > 0, "`max_length` should be a strictly positive integer." -# assert isinstance(min_length, int) and min_length >= 0, "`min_length` should be a positive integer." -# assert isinstance(do_sample, bool), "`do_sample` should be a boolean." -# assert isinstance(early_stopping, bool), "`early_stopping` should be a boolean." -# assert isinstance(use_cache, bool), "`use_cache` should be a boolean." -# assert isinstance(num_beams, int) and num_beams > 0, "`num_beams` should be a strictly positive integer." -# assert temperature > 0, "`temperature` should be strictly positive." -# assert isinstance(top_k, int) and top_k >= 0, "`top_k` should be a positive integer." -# assert 0 <= top_p <= 1, "`top_p` should be between 0 and 1." -# assert repetition_penalty >= 1.0, "`repetition_penalty` should be >= 1." -# assert input_ids is not None or ( -# isinstance(bos_token_id, int) and bos_token_id >= 0 -# ), "If input_ids is not defined, `bos_token_id` should be a positive integer." -# assert pad_token_id is None or ( -# isinstance(pad_token_id, int) and (pad_token_id >= 0) -# ), "`pad_token_id` should be a positive integer." -# assert (eos_token_id is None) or ( -# isinstance(eos_token_id, int) and (eos_token_id >= 0) -# ), "`eos_token_id` should be a positive integer." -# assert length_penalty > 0, "`length_penalty` should be strictly positive." -# assert ( -# isinstance(no_repeat_ngram_size, int) and no_repeat_ngram_size >= 0 -# ), "`no_repeat_ngram_size` should be a positive integer." -# assert ( -# isinstance(num_return_sequences, int) and num_return_sequences > 0 -# ), "`num_return_sequences` should be a strictly positive integer." -# assert ( -# bad_words_ids is None or isinstance(bad_words_ids, list) and isinstance(bad_words_ids[0], list) -# ), "`bad_words_ids` is either `None` or a list of lists of tokens that should not be generated" - -# if input_ids is None: -# assert isinstance(bos_token_id, int) and bos_token_id >= 0, ( -# "you should either supply a context to complete as `input_ids` input " -# "or a `bos_token_id` (integer >= 0) as a first token to start the generation." -# ) -# input_ids = torch.full( -# (batch_size, 1), bos_token_id, dtype=torch.long, device=next(self.parameters()).device, -# ) -# else: -# assert input_ids.dim() == 2, "Input prompt should be of shape (batch_size, sequence length)." - -# # not allow to duplicate outputs when greedy decoding -# if do_sample is False: -# if num_beams == 1: -# # no_beam_search greedy generation conditions -# assert ( -# num_return_sequences == 1 -# ), "Greedy decoding will always produce the same output for num_beams == 1 and num_return_sequences > 1. Please set num_return_sequences = 1" - -# else: -# # beam_search greedy generation conditions -# assert ( -# num_beams >= num_return_sequences -# ), "Greedy beam search decoding cannot return more sequences than it has beams. Please set num_beams >= num_return_sequences" - -# # create attention mask if necessary -# # TODO (PVP): this should later be handled by the forward fn() in each model in the future see PR 3140 -# if (attention_mask is None) and (pad_token_id is not None) and (pad_token_id in input_ids): -# attention_mask = input_ids.ne(pad_token_id).long() -# elif attention_mask is None: -# attention_mask = input_ids.new_ones(input_ids.shape) - -# # set pad_token_id to eos_token_id if not set. Important that this is done after -# # attention_mask is created -# if pad_token_id is None and eos_token_id is not None: -# logger.warning( -# "Setting `pad_token_id` to {} (first `eos_token_id`) to generate sequence".format(eos_token_id) -# ) -# pad_token_id = eos_token_id - -# # current position and vocab size -# if hasattr(self.config, "vocab_size"): -# vocab_size = self.config.vocab_size -# elif ( -# self.config.is_encoder_decoder -# and hasattr(self.config, "decoder") -# and hasattr(self.config.decoder, "vocab_size") -# ): -# vocab_size = self.config.decoder.vocab_size - -# # set effective batch size and effective batch multiplier according to do_sample -# if do_sample: -# effective_batch_size = batch_size * num_return_sequences -# effective_batch_mult = num_return_sequences -# else: -# effective_batch_size = batch_size -# effective_batch_mult = 1 - -# if self.config.is_encoder_decoder: -# if decoder_start_token_id is None: -# # see if BOS token can be used for decoder_start_token_id -# if bos_token_id is not None: -# decoder_start_token_id = bos_token_id -# elif hasattr(self.config, "decoder") and hasattr(self.config.decoder, "bos_token_id"): -# decoder_start_token_id = self.config.decoder.bos_token_id -# else: -# raise ValueError( -# "decoder_start_token_id or bos_token_id has to be defined for encoder-decoder generation" -# ) - -# assert hasattr(self, "get_encoder"), "{} should have a 'get_encoder' function defined".format(self) -# assert callable(self.get_encoder), "{} should be a method".format(self.get_encoder) - -# # get encoder and store encoder outputs -# encoder = self.get_encoder() -# encoder_outputs: tuple = encoder(input_ids, attention_mask=attention_mask) - -# # Expand input ids if num_beams > 1 or num_return_sequences > 1 -# if num_return_sequences > 1 or num_beams > 1: -# input_ids_len = input_ids.shape[-1] -# input_ids = input_ids.unsqueeze(1).expand(batch_size, effective_batch_mult * num_beams, input_ids_len) -# attention_mask = attention_mask.unsqueeze(1).expand( -# batch_size, effective_batch_mult * num_beams, input_ids_len -# ) - -# input_ids = input_ids.contiguous().view( -# effective_batch_size * num_beams, input_ids_len -# ) # shape: (batch_size * num_return_sequences * num_beams, cur_len) -# attention_mask = attention_mask.contiguous().view( -# effective_batch_size * num_beams, input_ids_len -# ) # shape: (batch_size * num_return_sequences * num_beams, cur_len) - -# if self.config.is_encoder_decoder: -# # create empty decoder_input_ids -# input_ids = torch.full( -# (effective_batch_size * num_beams, 1), -# decoder_start_token_id, -# dtype=torch.long, -# device=next(self.parameters()).device, -# ) -# cur_len = 1 - -# assert ( -# batch_size == encoder_outputs[0].shape[0] -# ), f"expected encoder_outputs[0] to have 1st dimension bs={batch_size}, got {encoder_outputs[0].shape[0]} " - -# # expand batch_idx to assign correct encoder output for expanded input_ids (due to num_beams > 1 and num_return_sequences > 1) -# expanded_batch_idxs = ( -# torch.arange(batch_size) -# .view(-1, 1) -# .repeat(1, num_beams * effective_batch_mult) -# .view(-1) -# .to(input_ids.device) -# ) -# # expand encoder_outputs -# encoder_outputs = (encoder_outputs[0].index_select(0, expanded_batch_idxs), *encoder_outputs[1:]) - -# else: -# encoder_outputs = None -# cur_len = input_ids.shape[-1] - -# assert ( -# cur_len < max_length -# ), f"The context has {cur_len} number of tokens, but `max_length` is only {max_length}. Please make sure that `max_length` is bigger than the number of tokens, by setting either `generate(max_length=...,...)` or `config.max_length = ...`" - -# if num_beams > 1: -# output = self._generate_beam_search( -# input_ids, -# cur_len=cur_len, -# max_length=max_length, -# min_length=min_length, -# do_sample=do_sample, -# early_stopping=early_stopping, -# temperature=temperature, -# top_k=top_k, -# top_p=top_p, -# repetition_penalty=repetition_penalty, -# no_repeat_ngram_size=no_repeat_ngram_size, -# bad_words_ids=bad_words_ids, -# pad_token_id=pad_token_id, -# eos_token_id=eos_token_id, -# batch_size=effective_batch_size, -# num_return_sequences=num_return_sequences, -# length_penalty=length_penalty, -# num_beams=num_beams, -# vocab_size=vocab_size, -# encoder_outputs=encoder_outputs, -# attention_mask=attention_mask, -# use_cache=use_cache, -# model_specific_kwargs=model_specific_kwargs, -# ) -# else: -# output = self._generate_no_beam_search( -# input_ids, -# cur_len=cur_len, -# max_length=max_length, -# min_length=min_length, -# do_sample=do_sample, -# temperature=temperature, -# top_k=top_k, -# top_p=top_p, -# repetition_penalty=repetition_penalty, -# no_repeat_ngram_size=no_repeat_ngram_size, -# bad_words_ids=bad_words_ids, -# pad_token_id=pad_token_id, -# eos_token_id=eos_token_id, -# batch_size=effective_batch_size, -# encoder_outputs=encoder_outputs, -# attention_mask=attention_mask, -# use_cache=use_cache, -# model_specific_kwargs=model_specific_kwargs, -# ) - -# return output - -# def _generate_no_beam_search( -# self, -# input_ids, -# cur_len, -# max_length, -# min_length, -# do_sample, -# temperature, -# top_k, -# top_p, -# repetition_penalty, -# no_repeat_ngram_size, -# bad_words_ids, -# pad_token_id, -# eos_token_id, -# batch_size, -# encoder_outputs, -# attention_mask, -# use_cache, -# model_specific_kwargs, -# ): -# """ Generate sequences for each example without beam search (num_beams == 1). -# All returned sequence are generated independantly. -# """ -# # length of generated sentences / unfinished sentences -# unfinished_sents = input_ids.new(batch_size).fill_(1) -# sent_lengths = input_ids.new(batch_size).fill_(max_length) - -# past = (encoder_outputs, None) if encoder_outputs is not None else None - -# while cur_len < max_length: -# model_inputs = self.prepare_inputs_for_generation( -# input_ids, past=past, attention_mask=attention_mask, use_cache=use_cache, **model_specific_kwargs -# ) - -# outputs = self(**model_inputs) -# next_token_logits = outputs[0][:, -1, :] - -# scores = self.postprocess_next_token_scores( -# scores=next_token_logits, -# input_ids=input_ids, -# no_repeat_ngram_size=no_repeat_ngram_size, -# bad_words_ids=bad_words_ids, -# cur_len=cur_len, -# min_length=min_length, -# max_length=max_length, -# eos_token_id=eos_token_id, -# repetition_penalty=repetition_penalty, -# batch_size=batch_size, -# num_beams=1, -# ) - -# # if model has past, then set the past variable to speed up decoding -# if self._use_cache(outputs, use_cache): -# past = outputs[1] - -# if do_sample: -# # Temperature (higher temperature => more likely to sample low probability tokens) -# if temperature != 1.0: -# scores = scores / temperature -# # Top-p/top-k filtering -# next_token_logscores = top_k_top_p_filtering(scores, top_k=top_k, top_p=top_p) -# # Sample -# probs = F.softmax(next_token_logscores, dim=-1) -# next_token = torch.multinomial(probs, num_samples=1).squeeze(1) -# else: -# # Greedy decoding -# next_token = torch.argmax(next_token_logits, dim=-1) - -# # update generations and finished sentences -# if eos_token_id is not None: -# # pad finished sentences if eos_token_id exist -# tokens_to_add = next_token * unfinished_sents + (pad_token_id) * (1 - unfinished_sents) -# else: -# tokens_to_add = next_token - -# # add token and increase length by one -# input_ids = torch.cat([input_ids, tokens_to_add.unsqueeze(-1)], dim=-1) -# cur_len = cur_len + 1 - -# if eos_token_id is not None: -# eos_in_sents = tokens_to_add == eos_token_id -# # if sentence is unfinished and the token to add is eos, sent_lengths is filled with current length -# is_sents_unfinished_and_token_to_add_is_eos = unfinished_sents.mul(eos_in_sents.long()).bool() -# sent_lengths.masked_fill_(is_sents_unfinished_and_token_to_add_is_eos, cur_len) -# # unfinished_sents is set to zero if eos in sentence -# unfinished_sents.mul_((~eos_in_sents).long()) - -# # stop when there is a in each sentence, or if we exceed the maximul length -# if unfinished_sents.max() == 0: -# break - -# # extend attention_mask for new generated input if only decoder -# if self.config.is_encoder_decoder is False: -# attention_mask = torch.cat( -# [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1 -# ) - -# return input_ids - -# def _generate_beam_search( -# self, -# input_ids, -# cur_len, -# max_length, -# min_length, -# do_sample, -# early_stopping, -# temperature, -# top_k, -# top_p, -# repetition_penalty, -# no_repeat_ngram_size, -# bad_words_ids, -# pad_token_id, -# eos_token_id, -# batch_size, -# num_return_sequences, -# length_penalty, -# num_beams, -# vocab_size, -# encoder_outputs, -# attention_mask, -# use_cache, -# model_specific_kwargs, -# ): -# """ Generate sequences for each example with beam search. -# """ - -# # generated hypotheses -# generated_hyps = [ -# BeamHypotheses(num_beams, max_length, length_penalty, early_stopping=early_stopping) -# for _ in range(batch_size) -# ] - -# # scores for each sentence in the beam -# beam_scores = torch.zeros((batch_size, num_beams), dtype=torch.float, device=input_ids.device) - -# # for greedy decoding it is made sure that only tokens of the first beam are considered to avoid sampling the exact same tokens three times -# if do_sample is False: -# beam_scores[:, 1:] = -1e9 -# beam_scores = beam_scores.view(-1) # shape (batch_size * num_beams,) - -# # cache compute states -# past = (encoder_outputs, None) if encoder_outputs is not None else None - -# # done sentences -# done = [False for _ in range(batch_size)] - -# while cur_len < max_length: -# model_inputs = self.prepare_inputs_for_generation( -# input_ids, past=past, attention_mask=attention_mask, use_cache=use_cache, **model_specific_kwargs -# ) -# print(model_inputs) -# outputs = self(**model_inputs) # (batch_size * num_beams, cur_len, vocab_size) -# next_token_logits = outputs[0][:, -1, :] # (batch_size * num_beams, vocab_size) - -# # if model has past, then set the past variable to speed up decoding -# if self._use_cache(outputs, use_cache): -# past = outputs[1] -# if self.config.is_encoder_decoder and do_sample is False: -# # TODO (PVP) still a bit hacky here - there might be a better solution -# next_token_logits = self.adjust_logits_during_generation( -# next_token_logits, cur_len=cur_len, max_length=max_length -# ) - -# scores = F.log_softmax(next_token_logits, dim=-1) # (batch_size * num_beams, vocab_size) - -# scores = self.postprocess_next_token_scores( -# scores=scores, -# input_ids=input_ids, -# no_repeat_ngram_size=no_repeat_ngram_size, -# bad_words_ids=bad_words_ids, -# cur_len=cur_len, -# min_length=min_length, -# max_length=max_length, -# eos_token_id=eos_token_id, -# repetition_penalty=repetition_penalty, -# batch_size=batch_size, -# num_beams=num_beams, -# ) - -# assert scores.shape == (batch_size * num_beams, vocab_size), "Shapes of scores: {} != {}".format( -# scores.shape, (batch_size * num_beams, vocab_size) -# ) - -# if do_sample: -# _scores = scores + beam_scores[:, None].expand_as(scores) # (batch_size * num_beams, vocab_size) -# # Temperature -# if temperature != 1.0: -# _scores = _scores / temperature -# # Top-p/top-k filtering -# _scores = top_k_top_p_filtering( -# _scores, top_k=top_k, top_p=top_p, min_tokens_to_keep=2 -# ) # (batch_size * num_beams, vocab_size) -# # re-organize to group the beam together to sample from all beam_idxs -# _scores = _scores.contiguous().view( -# batch_size, num_beams * vocab_size -# ) # (batch_size, num_beams * vocab_size) - -# # Sample 2 next tokens for each beam (so we have some spare tokens and match output of greedy beam search) -# probs = F.softmax(_scores, dim=-1) -# next_tokens = torch.multinomial(probs, num_samples=2 * num_beams) # (batch_size, num_beams * 2) -# # Compute next scores -# next_scores = torch.gather(_scores, -1, next_tokens) # (batch_size, num_beams * 2) -# # sort the sampled vector to make sure that the first num_beams samples are the best -# next_scores, next_scores_indices = torch.sort(next_scores, descending=True, dim=1) -# next_tokens = torch.gather(next_tokens, -1, next_scores_indices) # (batch_size, num_beams * 2) - -# else: -# next_scores = scores + beam_scores[:, None].expand_as(scores) # (batch_size * num_beams, vocab_size) - -# # re-organize to group the beam together (we are keeping top hypothesis accross beams) -# next_scores = next_scores.view( -# batch_size, num_beams * vocab_size -# ) # (batch_size, num_beams * vocab_size) - -# next_scores, next_tokens = torch.topk(next_scores, 2 * num_beams, dim=1, largest=True, sorted=True) - -# assert next_scores.size() == next_tokens.size() == (batch_size, 2 * num_beams) - -# # next batch beam content -# next_batch_beam = [] - -# # for each sentence -# for batch_idx in range(batch_size): - -# # if we are done with this sentence, add a pad token -# if done[batch_idx]: -# assert ( -# len(generated_hyps[batch_idx]) >= num_beams -# ), "Batch can only be done if at least {} beams have been generated".format(num_beams) -# assert ( -# eos_token_id is not None and pad_token_id is not None -# ), "generated beams >= num_beams -> eos_token_id and pad_token have to be defined" -# next_batch_beam.extend([(0, pad_token_id, 0)] * num_beams) # pad the batch -# continue - -# # next sentence beam content, this will get added to next_batch_beam -# next_sent_beam = [] - -# # next tokens for this sentence -# for beam_token_rank, (beam_token_id, beam_token_score) in enumerate( -# zip(next_tokens[batch_idx], next_scores[batch_idx]) -# ): -# # get beam and token IDs -# beam_id = beam_token_id // vocab_size -# token_id = beam_token_id % vocab_size - -# effective_beam_id = batch_idx * num_beams + beam_id -# # add to generated hypotheses if end of sentence -# if (eos_token_id is not None) and (token_id.item() == eos_token_id): -# # if beam_token does not belong to top num_beams tokens, it should not be added -# is_beam_token_worse_than_top_num_beams = beam_token_rank >= num_beams -# if is_beam_token_worse_than_top_num_beams: -# continue -# generated_hyps[batch_idx].add( -# input_ids[effective_beam_id].clone(), beam_token_score.item(), -# ) -# else: -# # add next predicted token since it is not eos_token -# next_sent_beam.append((beam_token_score, token_id, effective_beam_id)) - -# # once the beam for next step is full, don't add more tokens to it. -# if len(next_sent_beam) == num_beams: -# break - -# # Check if we are done so that we can save a pad step if all(done) -# done[batch_idx] = done[batch_idx] or generated_hyps[batch_idx].is_done( -# next_scores[batch_idx].max().item(), cur_len -# ) - -# # update next beam content -# assert len(next_sent_beam) == num_beams, "Beam should always be full" -# next_batch_beam.extend(next_sent_beam) -# assert len(next_batch_beam) == num_beams * (batch_idx + 1), "We should have added num_beams each step" - -# # stop when we are done with each sentence -# if all(done): -# break - -# # sanity check / prepare next batch -# assert len(next_batch_beam) == batch_size * num_beams -# beam_scores = beam_scores.new([x[0] for x in next_batch_beam]) -# beam_tokens = input_ids.new([x[1] for x in next_batch_beam]) -# beam_idx = input_ids.new([x[2] for x in next_batch_beam]) - -# # re-order batch and update current length -# input_ids = input_ids[beam_idx, :] -# input_ids = torch.cat([input_ids, beam_tokens.unsqueeze(1)], dim=-1) -# cur_len = cur_len + 1 - -# # re-order internal states -# if past is not None: -# past = self._reorder_cache(past, beam_idx) - -# # extend attention_mask for new generated input if only decoder -# if self.config.is_encoder_decoder is False: -# attention_mask = torch.cat( -# [attention_mask, attention_mask.new_ones((attention_mask.shape[0], 1))], dim=-1 -# ) - -# # finalize all open beam hypotheses and add to generated hypotheses -# for batch_idx in range(batch_size): -# if done[batch_idx]: -# continue - -# # test that beam scores match previously calculated scores if not eos and batch_idx not done -# if eos_token_id is not None and all( -# (token_id % vocab_size).item() != eos_token_id for token_id in next_tokens[batch_idx] -# ): -# assert torch.all( -# next_scores[batch_idx, :num_beams] == beam_scores.view(batch_size, num_beams)[batch_idx] -# ), "If batch_idx is not done, final next scores: {} have to equal to accumulated beam_scores: {}".format( -# next_scores[:, :num_beams][batch_idx], beam_scores.view(batch_size, num_beams)[batch_idx], -# ) - -# # need to add best num_beams hypotheses to generated hyps -# for beam_id in range(num_beams): -# effective_beam_id = batch_idx * num_beams + beam_id -# final_score = beam_scores[effective_beam_id].item() -# final_tokens = input_ids[effective_beam_id] -# generated_hyps[batch_idx].add(final_tokens, final_score) - -# # depending on whether greedy generation is wanted or not define different output_batch_size and output_num_return_sequences_per_batch -# output_batch_size = batch_size if do_sample else batch_size * num_return_sequences -# output_num_return_sequences_per_batch = 1 if do_sample else num_return_sequences - -# # select the best hypotheses -# sent_lengths = input_ids.new(output_batch_size) -# best = [] - -# # retrieve best hypotheses -# for i, hypotheses in enumerate(generated_hyps): -# sorted_hyps = sorted(hypotheses.beams, key=lambda x: x[0]) -# for j in range(output_num_return_sequences_per_batch): -# effective_batch_idx = output_num_return_sequences_per_batch * i + j -# best_hyp = sorted_hyps.pop()[1] -# sent_lengths[effective_batch_idx] = len(best_hyp) -# best.append(best_hyp) - -# # shorter batches are padded -# if sent_lengths.min().item() != sent_lengths.max().item(): -# assert pad_token_id is not None, "`Pad_token_id` has to be defined" -# sent_max_len = min(sent_lengths.max().item() + 1, max_length) -# decoded = input_ids.new(output_batch_size, sent_max_len).fill_(pad_token_id) - -# # fill with hypothesis and eos_token_id if necessary -# for i, hypo in enumerate(best): -# decoded[i, : sent_lengths[i]] = hypo -# if sent_lengths[i] < max_length: -# decoded[i, sent_lengths[i]] = eos_token_id -# else: -# # none of the hypotheses have an eos_token -# assert (len(hypo) == max_length for hypo in best) -# decoded = torch.stack(best).type(torch.long).to(next(self.parameters()).device) - -# return decoded - -# @staticmethod -# def _reorder_cache(past: Tuple, beam_idx: Tensor) -> Tuple[Tensor]: -# return tuple(layer_past.index_select(1, beam_idx) for layer_past in past) - - -# def calc_banned_ngram_tokens(prev_input_ids: Tensor, num_hypos: int, no_repeat_ngram_size: int, cur_len: int) -> None: -# """Copied from fairseq for no_repeat_ngram in beam_search""" -# if cur_len + 1 < no_repeat_ngram_size: -# # return no banned tokens if we haven't generated no_repeat_ngram_size tokens yet -# return [[] for _ in range(num_hypos)] -# generated_ngrams = [{} for _ in range(num_hypos)] -# for idx in range(num_hypos): -# gen_tokens = prev_input_ids[idx].tolist() -# generated_ngram = generated_ngrams[idx] -# for ngram in zip(*[gen_tokens[i:] for i in range(no_repeat_ngram_size)]): -# prev_ngram_tuple = tuple(ngram[:-1]) -# generated_ngram[prev_ngram_tuple] = generated_ngram.get(prev_ngram_tuple, []) + [ngram[-1]] - -# def _get_generated_ngrams(hypo_idx): -# # Before decoding the next token, prevent decoding of ngrams that have already appeared -# start_idx = cur_len + 1 - no_repeat_ngram_size -# ngram_idx = tuple(prev_input_ids[hypo_idx, start_idx:cur_len].tolist()) -# return generated_ngrams[hypo_idx].get(ngram_idx, []) - -# banned_tokens = [_get_generated_ngrams(hypo_idx) for hypo_idx in range(num_hypos)] -# return banned_tokens - - -# def calc_banned_bad_words_ids(prev_input_ids: Iterable[int], bad_words_ids: Iterable[int]) -> Iterable[int]: -# banned_tokens = [] - -# def _tokens_match(prev_tokens, tokens): -# if len(tokens) == 0: -# # if bad word tokens is just one token always ban it -# return True -# if len(tokens) > len(prev_tokens): -# # if bad word tokens are longer than prev tokens they can't be equal -# return False - -# if prev_tokens[-len(tokens) :] == tokens: -# # if tokens match -# return True -# else: -# return False - -# for prev_input_ids_slice in prev_input_ids: -# banned_tokens_slice = [] - -# for banned_token_seq in bad_words_ids: -# assert len(banned_token_seq) > 0, "Banned words token sequences {} cannot have an empty list".format( -# bad_words_ids -# ) - -# if _tokens_match(prev_input_ids_slice, banned_token_seq[:-1]) is False: -# # if tokens do not match continue -# continue - -# banned_tokens_slice.append(banned_token_seq[-1]) - -# banned_tokens.append(banned_tokens_slice) - -# return banned_tokens - - -# def set_scores_to_inf_for_banned_tokens(scores: torch.Tensor, banned_tokens: List[List[int]]) -> None: -# """ Modifies the scores in place by setting the banned token positions to `-inf`. Banned token is expected to be -# a list of list of banned tokens to ban in the format [[batch index, vocabulary position],...] -# Args: -# scores: logits distribution of shape (batch size, vocabulary size) -# banned_tokens: list of list of tokens to ban of length (batch_size) -# """ -# banned_mask_list = [] -# for idx, batch_banned_tokens in enumerate(banned_tokens): -# for token in batch_banned_tokens: -# banned_mask_list.append([idx, token]) -# if not banned_mask_list: -# return -# banned_mask = torch.LongTensor(banned_mask_list) -# indices = torch.ones(len(banned_mask)) -# # A sparse tensor is generated from a list of coordinates: [[0, 1], [0, 2], [2, 0]]. A conversion to dense tensor generates: -# # [ 0 1 1 ] -# # [ 0 0 0 ] -# # [ 1 0 0 ] - -# banned_mask = torch.sparse.LongTensor(banned_mask.t(), indices, scores.size()).to(scores.device).to_dense().bool() -# scores.masked_fill_(banned_mask, -float("inf")) - - -# def top_k_top_p_filtering( -# logits: Tensor, -# top_k: int = 0, -# top_p: float = 1.0, -# filter_value: float = -float("Inf"), -# min_tokens_to_keep: int = 1, -# ) -> Tensor: -# """ Filter a distribution of logits using top-k and/or nucleus (top-p) filtering -# Args: -# logits: logits distribution shape (batch size, vocabulary size) -# if top_k > 0: keep only top k tokens with highest probability (top-k filtering). -# if top_p < 1.0: keep the top tokens with cumulative probability >= top_p (nucleus filtering). -# Nucleus filtering is described in Holtzman et al. (http://arxiv.org/abs/1904.09751) -# Make sure we keep at least min_tokens_to_keep per batch example in the output -# From: https://gist.github.com/thomwolf/1a5a29f6962089e871b94cbd09daf317 -# """ -# if top_k > 0: -# top_k = min(max(top_k, min_tokens_to_keep), logits.size(-1)) # Safety check -# # Remove all tokens with a probability less than the last token of the top-k -# indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None] -# logits[indices_to_remove] = filter_value - -# if top_p < 1.0: -# sorted_logits, sorted_indices = torch.sort(logits, descending=True) -# cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1) - -# # Remove tokens with cumulative probability above the threshold (token with 0 are kept) -# sorted_indices_to_remove = cumulative_probs > top_p -# if min_tokens_to_keep > 1: -# # Keep at least min_tokens_to_keep (set to min_tokens_to_keep-1 because we add the first one below) -# sorted_indices_to_remove[..., :min_tokens_to_keep] = 0 -# # Shift the indices to the right to keep also the first token above the threshold -# sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone() -# sorted_indices_to_remove[..., 0] = 0 - -# # scatter sorted tensors to original indexing -# indices_to_remove = sorted_indices_to_remove.scatter(1, sorted_indices, sorted_indices_to_remove) -# logits[indices_to_remove] = filter_value -# return logits - - -# class BeamHypotheses(object): -# def __init__(self, num_beams, max_length, length_penalty, early_stopping): -# """ -# Initialize n-best list of hypotheses. -# """ -# self.max_length = max_length - 1 # ignoring bos_token -# self.length_penalty = length_penalty -# self.early_stopping = early_stopping -# self.num_beams = num_beams -# self.beams = [] -# self.worst_score = 1e9 - -# def __len__(self): -# """ -# Number of hypotheses in the list. -# """ -# return len(self.beams) - -# def add(self, hyp, sum_logprobs): -# """ -# Add a new hypothesis to the list. -# """ -# score = sum_logprobs / len(hyp) ** self.length_penalty -# if len(self) < self.num_beams or score > self.worst_score: -# self.beams.append((score, hyp)) -# if len(self) > self.num_beams: -# sorted_scores = sorted([(s, idx) for idx, (s, _) in enumerate(self.beams)]) -# del self.beams[sorted_scores[0][1]] -# self.worst_score = sorted_scores[1][0] -# else: -# self.worst_score = min(score, self.worst_score) - -# def is_done(self, best_sum_logprobs, cur_len): -# """ -# If there are enough hypotheses and that none of the hypotheses being generated -# can become better than the worst one in the heap, then we are done with this sentence. -# """ - -# if len(self) < self.num_beams: -# return False -# elif self.early_stopping: -# return True -# else: -# cur_score = best_sum_logprobs / cur_len ** self.length_penalty -# ret = self.worst_score >= cur_score -# return ret - - @dataclass class GreedySearchDecoderOnlyOutput(ModelOutput): """ diff --git a/PyTorch/LanguageModeling/BART/utils/logging.py b/PyTorch/LanguageModeling/BART/utils/logging.py index baa456ffb..a327ac24c 100755 --- a/PyTorch/LanguageModeling/BART/utils/logging.py +++ b/PyTorch/LanguageModeling/BART/utils/logging.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2020 Optuna, Hugging Face # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/utils/make_datafiles.py b/PyTorch/LanguageModeling/BART/utils/make_datafiles.py new file mode 100644 index 000000000..8a95c93a2 --- /dev/null +++ b/PyTorch/LanguageModeling/BART/utils/make_datafiles.py @@ -0,0 +1,153 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +import sys +import os +import hashlib + + +dm_single_close_quote = u'\u2019' # unicode +dm_double_close_quote = u'\u201d' +END_TOKENS = ['.', '!', '?', '...', "'", "`", '"', dm_single_close_quote, dm_double_close_quote, ")"] # acceptable ways to end a sentence + +all_train_urls = "url_lists/all_train.txt" +all_val_urls = "url_lists/all_val.txt" +all_test_urls = "url_lists/all_test.txt" + +finished_files_dir = "cnn_dm" + +# These are the number of .story files we expect there to be in cnn_stories_dir and dm_stories_dir +num_expected_cnn_stories = 92579 +num_expected_dm_stories = 219506 + +def read_text_file(text_file): + lines = [] + with open(text_file, "r") as f: + for line in f: + lines.append(line.strip()) + return lines + + +def hashhex(s): + """Returns a heximal formated SHA1 hash of the input string.""" + h = hashlib.sha1() + h.update(s.encode()) + return h.hexdigest() + + +def get_url_hashes(url_list): + return [hashhex(url) for url in url_list] + + +def fix_missing_period(line): + """Adds a period to a line that is missing a period""" + if "@highlight" in line: return line + if line=="": return line + if line[-1] in END_TOKENS: return line + # print line[-1] + return line + " ." + + +def get_art_abs(story_file): + lines = read_text_file(story_file) + + # Put periods on the ends of lines that are missing them (this is a problem in the dataset because many image captions don't end in periods; consequently they end up in the body of the article as run-on sentences) + lines = [fix_missing_period(line) for line in lines] + + # Separate out article and abstract sentences + article_lines = [] + highlights = [] + next_is_highlight = False + for idx,line in enumerate(lines): + if line == "": + continue # empty line + elif line.startswith("@highlight"): + next_is_highlight = True + elif next_is_highlight: + highlights.append(line) + else: + article_lines.append(line) + + # Make article into a single string + article = ' '.join(article_lines) + + # Make abstract into a signle string + abstract = ' '.join(highlights) + + return article, abstract + + +def write_to_bin(url_file, out_name): + """Reads the tokenized .story files corresponding to the urls listed in the url_file and writes them to a out_file.""" + print("Making bin file for URLs listed in %s..." % url_file) + url_list = read_text_file(url_file) + url_hashes = get_url_hashes(url_list) + story_fnames = [s+".story" for s in url_hashes] + num_stories = len(story_fnames) + + article_out = out_name + '.source' + abstract_out = out_name + '.target' + + with open(article_out, 'w') as article_writer, open(abstract_out, 'w') as abstract_writer: + for idx,s in enumerate(story_fnames): + if idx % 1000 == 0: + print("Writing story %i of %i; %.2f percent done" % (idx, num_stories, float(idx)*100.0/float(num_stories))) + + # Look in the tokenized story dirs to find the .story file corresponding to this url + if os.path.isfile(os.path.join(cnn_stories_dir, s)): + story_file = os.path.join(cnn_stories_dir, s) + elif os.path.isfile(os.path.join(dm_stories_dir, s)): + story_file = os.path.join(dm_stories_dir, s) + else: + print("Error: Couldn't find story file %s in story directories %s and %s." % (s, cnn_stories_dir, dm_stories_dir)) + # Check again if stories directories contain correct number of files + print("Checking that the stories directories %s and %s contain correct number of files..." % (cnn_stories_dir, dm_stories_dir)) + check_num_stories(cnn_stories_dir, num_expected_cnn_stories) + check_num_stories(dm_stories_dir, num_expected_dm_stories) + raise Exception("Stories directories %s and %s contain correct number of files but story file %s found in neither." % (cnn_stories_dir, dm_stories_dir, s)) + + # Get the strings to write to .bin file + article, abstract = get_art_abs(story_file) + + article_writer.write(article + '\n') + abstract_writer.write(abstract + '\n') + + print("Finished writing file %s and %s\n" % (article_out, abstract_out)) + +def check_num_stories(stories_dir, num_expected): + num_stories = len(os.listdir(stories_dir)) + if num_stories != num_expected: + raise Exception("stories directory %s contains %i files but should contain %i" % (stories_dir, num_stories, num_expected)) + + +if __name__ == '__main__': + if len(sys.argv) != 3: + print("USAGE: python make_datafiles.py ") + sys.exit() + cnn_stories_dir = sys.argv[1] + dm_stories_dir = sys.argv[2] + + # Check the stories directories contain the correct number of .story files + check_num_stories(cnn_stories_dir, num_expected_cnn_stories) + check_num_stories(dm_stories_dir, num_expected_dm_stories) + + # Create some new directories + if not os.path.exists(finished_files_dir): os.makedirs(finished_files_dir) + + # Read the tokenized stories, do a little postprocessing then write to bin files + write_to_bin(all_test_urls, os.path.join(finished_files_dir, "test")) + write_to_bin(all_val_urls, os.path.join(finished_files_dir, "val")) + write_to_bin(all_train_urls, os.path.join(finished_files_dir, "train")) + diff --git a/PyTorch/LanguageModeling/BART/utils/optimization.py b/PyTorch/LanguageModeling/BART/utils/optimization.py index 4c65dc92a..8fc79fb1e 100755 --- a/PyTorch/LanguageModeling/BART/utils/optimization.py +++ b/PyTorch/LanguageModeling/BART/utils/optimization.py @@ -1,4 +1,5 @@ # coding=utf-8 +# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. # Copyright 2018 The Google AI Language Team Authors and The HuggingFace Inc. team. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/PyTorch/LanguageModeling/BART/utils/utils.py b/PyTorch/LanguageModeling/BART/utils/utils.py index 0252fe23f..9886b0cb6 100755 --- a/PyTorch/LanguageModeling/BART/utils/utils.py +++ b/PyTorch/LanguageModeling/BART/utils/utils.py @@ -20,6 +20,8 @@ import os import pickle import socket +import time +import logging from logging import getLogger from pathlib import Path from typing import Callable, Dict, Iterable, List, Union @@ -30,13 +32,14 @@ import torch import torch.distributed as dist from rouge_score import rouge_scorer, scoring -from sacrebleu import corpus_bleu from torch import nn -from torch.utils.data import Dataset, Sampler +from torch.utils.data import Dataset, Sampler, IterableDataset from bart.tokenization.tokenization_bart import BartTokenizer from utils.file_utils import cached_property - +from lddl.torch.datasets import ParquetDataset +from lddl.torch.log import DatasetLogger +from lddl.torch.utils import get_node_rank, get_nproc_per_node try: from fairseq.data.data_utils import batch_by_size @@ -101,7 +104,7 @@ def trim_batch( num_keeps = torch.count_nonzero(keep_column_mask) #Pad to multiples of 8 - pad_num_keeps = num_keeps if num_keeps % 8 == 0 else (num_keeps//8 + 1) * 8 + pad_num_keeps = num_keeps if num_keeps % 8 == 0 else (torch.div(num_keeps, 8, rounding_mode='floor') + 1) * 8 keep_column_mask[num_keeps:pad_num_keeps] = True if attention_mask is None: @@ -211,6 +214,98 @@ def collate_fn(self, batch): raise NotImplementedError("You must implement this") +class LegacySeq2SeqDataset(AbstractSeq2SeqDataset): + def __getitem__(self, index) -> Dict[str, torch.Tensor]: + """Call tokenizer on src and tgt_lines""" + index = index + 1 # linecache starts at 1 + source_line = self.prefix + linecache.getline(str(self.src_file), index).rstrip("\n") + tgt_line = linecache.getline(str(self.tgt_file), index).rstrip("\n") + # assert source_line, f"empty source line for index {index}" + # assert tgt_line, f"empty tgt line for index {index}" + # Some CNN/dm source lines are empty + source_inputs = encode_line(self.tokenizer, source_line, self.max_source_length) + target_inputs = encode_line(self.tokenizer, tgt_line, self.max_target_length) + + source_ids = source_inputs["input_ids"].squeeze() + target_ids = target_inputs["input_ids"].squeeze() + src_mask = source_inputs["attention_mask"].squeeze() + return { + "input_ids": source_ids, + "attention_mask": src_mask, + "labels": target_ids, + } + + + def collate_fn(self, batch) -> Dict[str, torch.Tensor]: + input_ids = torch.stack([x["input_ids"] for x in batch]) + masks = torch.stack([x["attention_mask"] for x in batch]) + target_ids = torch.stack([x["labels"] for x in batch]) + pad_token_id = self.pad_token_id + y = trim_batch(target_ids, pad_token_id) + source_ids, source_mask = trim_batch(input_ids, pad_token_id, attention_mask=masks) + batch = { + "input_ids": source_ids, + "attention_mask": source_mask, + "labels": y, + } + return batch + + +class PretrainingSeq2SeqDataset(ParquetDataset): + def __init__( + self, + path, + tokenizer, + max_source_length, + type_path="train", + n_obs=None, #@TODO fix n_obs input, not used + prefix="", + log_dir=None, + log_level=logging.INFO, + **dataset_kwargs + ): + + logger = DatasetLogger( + log_dir=log_dir, + node_rank=get_node_rank(nproc_per_node=get_nproc_per_node(dataset_kwargs["local_rank"])), + local_rank=dataset_kwargs["local_rank"], + log_level=log_level, + ) + + super().__init__( + path, + transform=dataset_kwargs["transform"], + local_rank=dataset_kwargs["local_rank"], + shuffle_buffer_size=dataset_kwargs["shuffle_buffer_size"], + shuffle_buffer_warmup_factor=dataset_kwargs["shuffle_buffer_warmup_factor"], + base_seed=dataset_kwargs["base_seed"], + logger=logger + ) + + self.max_source_length = max_source_length + self.tokenizer = tokenizer + self.prefix = prefix if prefix is not None else "" + + self.pad_token_id = self.tokenizer.pad_token_id + self.dataset_kwargs = dataset_kwargs + dataset_kwargs.update({"add_prefix_space": True} if isinstance(self.tokenizer, BartTokenizer) else {}) + + def _decode_record_batch(self, batch): + batch = batch.to_pydict() + + for source_line in batch["sentences"]: + source_line = self.prefix + source_line.rstrip("\n") + assert source_line, f"empty source line for index {index}" + source_inputs = encode_line(self.tokenizer, source_line, self.max_source_length) + + source_ids = source_inputs["input_ids"].squeeze() + src_mask = source_inputs["attention_mask"].squeeze() + yield { + "input_ids": source_ids, + "attention_mask": src_mask, + } + + class LegacySeq2SeqDataset(AbstractSeq2SeqDataset): def __getitem__(self, index) -> Dict[str, torch.Tensor]: """Call tokenizer on src and tgt_lines""" @@ -247,6 +342,39 @@ def collate_fn(self, batch) -> Dict[str, torch.Tensor]: return batch +class ShuffleAndChainDataset(IterableDataset): + def __init__(self, datasets, buffer_size): + super().__init__() + self.datasets = datasets + self.buffer_size = buffer_size + + def chain_iter(self): + for i, d in enumerate(self.datasets): + for j, x in enumerate(d): + yield x + + def __iter__(self): + shufbuf = [] + try: + dataset_iter = self.chain_iter() + for i in range(self.buffer_size): + shufbuf.append(next(dataset_iter)) + except: + self.buffer_size = len(shufbuf) + try: + while True: + try: + item = next(dataset_iter) + evict_idx = random.randint(0, self.buffer_size - 1) + yield shufbuf[evict_idx] + shufbuf[evict_idx] = item + except StopIteration: + break + while len(shufbuf) > 0: + yield shufbuf.pop() + except GeneratorExit: + pass + class Seq2SeqDataset(AbstractSeq2SeqDataset): """A dataset that calls prepare_seq2seq_batch.""" @@ -526,4 +654,34 @@ def format_step(step): s = "" if len(step) > 0: s += "Global Step : {} ".format(step[0]) - return s \ No newline at end of file + return s + +def get_readable_time(elapsed): + d, h, m, s = [int(x) for x in time.strftime("%d:%H:%M:%S", time.gmtime(elapsed)).split(':')] + d -= 1 + return '{:2d}h{:2d}m{:2d}s'.format(24*d + h, m, s) + +class Mean: + def __init__(self, **kwargs): + self.reset() + + def reset(self): + self._total = 0.0 + self._num_examples = 0 + + def update(self, values, sample_weight=None): + if sample_weight is None: + if not isinstance(values, torch.Tensor): + values = torch.tensor(values) + if len(values.shape) == 0: + values = values.unsqueeze(-1) + self._total += torch.sum(values).item() + self._num_examples += values.shape[0] + else: + self._total += torch.sum(values * sample_weight).item() + self._num_examples += torch.sum(sample_weight).item() + + def result(self): + if self._num_examples == 0: + return float("nan") + return self._total / self._num_examples diff --git a/PyTorch/LanguageModeling/BERT/Dockerfile b/PyTorch/LanguageModeling/BERT/Dockerfile index 4183a09d6..c9c494c96 100755 --- a/PyTorch/LanguageModeling/BERT/Dockerfile +++ b/PyTorch/LanguageModeling/BERT/Dockerfile @@ -20,7 +20,7 @@ WORKDIR /workspace WORKDIR /workspace/bert RUN pip install --no-cache-dir \ - tqdm boto3 requests six ipdb h5py nltk progressbar onnxruntime tokenizers>=0.7\ + tqdm boto3 requests six ipdb h5py nltk progressbar onnxruntime==1.12.0 tokenizers>=0.7\ git+https://github.com/NVIDIA/dllogger wget RUN apt-get install -y iputils-ping diff --git a/PyTorch/LanguageModeling/BERT/run.sub b/PyTorch/LanguageModeling/BERT/run.sub index 08ab5fe09..f10b39078 100644 --- a/PyTorch/LanguageModeling/BERT/run.sub +++ b/PyTorch/LanguageModeling/BERT/run.sub @@ -41,7 +41,7 @@ STEPS_THIS_RUN=${STEPS_THIS_RUN:-"none"} GPUS=${GPUS:-"8"} # The bin size for binned LDDL data loading. 'none' or an integer that divides # 128 (for Phase1) or 512 (for Phase2). -BIN_SIZE=${BIN_SIZE:-"none"} +BIN_SIZE=${BIN_SIZE:-"64"} # Number of parquet shards per each LDDL data loader worker process. 'none' or # an integer. NUM_SHARDS_PER_WORKER=${NUM_SHARDS_PER_WORKER:-"none"} diff --git a/PyTorch/LanguageModeling/Transformer-XL/pytorch/eval.py b/PyTorch/LanguageModeling/Transformer-XL/pytorch/eval.py index 25b2bc08d..29e6e565a 100644 --- a/PyTorch/LanguageModeling/Transformer-XL/pytorch/eval.py +++ b/PyTorch/LanguageModeling/Transformer-XL/pytorch/eval.py @@ -168,7 +168,9 @@ def format_log(loss, split, args): return log_str -def evaluate(eval_iter, model, meters, log_interval, max_size=None, repeat=1): +def evaluate( + eval_iter, model, device, meters, log_interval, max_size=None, repeat=1 +): total_len, total_loss = 0, 0. eval_step = 0 @@ -176,8 +178,9 @@ def evaluate(eval_iter, model, meters, log_interval, max_size=None, repeat=1): log_latency = 0 log_loss = 0 - torch.cuda.synchronize() + utils.distributed.barrier() start_time = time.time() + with torch.no_grad(): mems = None for _ in range(repeat): @@ -186,10 +189,12 @@ def evaluate(eval_iter, model, meters, log_interval, max_size=None, repeat=1): break eval_step += 1 - torch.cuda.synchronize() + utils.distributed.barrier() start_iter = time.time() + loss, mems = model(data, target, mems) - torch.cuda.synchronize() + + utils.distributed.barrier() elapsed = time.time() - start_iter loss = loss.float().mean() @@ -204,7 +209,7 @@ def evaluate(eval_iter, model, meters, log_interval, max_size=None, repeat=1): target_tokens = target.numel() throughput = target_tokens / elapsed throughput = utils.distributed.all_reduce_item(throughput, op='sum') - meters['eval_throughput'].update(throughput) + meters['eval_throughput'].update(throughput, elapsed) log_throughput += throughput if eval_step % log_interval == 0: @@ -238,8 +243,8 @@ def evaluate(eval_iter, model, meters, log_interval, max_size=None, repeat=1): log_loss = 0 utils.distributed.barrier() - torch.cuda.synchronize() total_time = time.time() - start_time + logging.info('Time : {:.2f}s, {:.2f}ms/segment'.format( total_time, 1000 * total_time / (idx+1))) @@ -251,13 +256,18 @@ def evaluate(eval_iter, model, meters, log_interval, max_size=None, repeat=1): def compile_model(model, device, args): inp = torch.randint(0, 1000, (args.tgt_len, args.batch_size)).to(device) tgt = torch.randint(0, 1000, (args.tgt_len, args.batch_size)).to(device) + + utils.distributed.barrier() start = time.time() + with torch.no_grad(): mems = None for _ in range(2): _, mems = model(inp, tgt, mems) - torch.cuda.synchronize() + + utils.distributed.barrier() stop = time.time() + logging.info(f'Building the model took {stop - start:.2f} seconds') @@ -450,7 +460,7 @@ def main(): meters['eval_throughput'] = AverageMeter(warmup=warmup, keep=args.save_data) meters['eval_latency'] = AverageMeter(warmup=warmup, keep=args.save_data) - loss = evaluate(iter, model, meters, args.log_interval, args.max_size, args.repeat) + loss = evaluate(iter, model, device, meters, args.log_interval, args.max_size, args.repeat) perplexity = math.exp(loss) log_str = format_log(loss, args.split, args) @@ -476,7 +486,9 @@ def main(): } with open(data_path, 'wb') as f: pickle.dump(data, f) - logging.info(f'Throughput Avg: {throughput_data.mean():.2f} tok/s') + + avg_throughput = meters['eval_throughput'].avg + logging.info(f'Throughput Avg: {avg_throughput:.2f} tok/s') logging.info(f'Latency Avg: {1000.0 * latency_data.mean():.2f} ms') for p in args.percentiles: logging.info(f'Latency {p}%: {1000.0 * np.percentile(latency_data, p):.2f} ms') @@ -484,7 +496,7 @@ def main(): logging.info('=' * 100) summary.update({ - 'eval_throughput': throughput_data.mean(), + 'eval_throughput': avg_throughput, 'eval_avg_latency': 1000 * latency_data.mean(), }) for p in args.percentiles: diff --git a/PyTorch/LanguageModeling/Transformer-XL/pytorch/train.py b/PyTorch/LanguageModeling/Transformer-XL/pytorch/train.py index e0c94d645..f79ac8bd1 100644 --- a/PyTorch/LanguageModeling/Transformer-XL/pytorch/train.py +++ b/PyTorch/LanguageModeling/Transformer-XL/pytorch/train.py @@ -513,6 +513,7 @@ def train(tr_iter, va_iter, model, para_model, mems, model_config, optimizer, cur_loss = float('inf') target_tokens = 0 log_step = 0 + utils.distributed.barrier() log_start_time = time.time() if args.varlen: @@ -586,16 +587,18 @@ def train(tr_iter, va_iter, model, para_model, mems, model_config, optimizer, cur_loss = utils.distributed.all_reduce_item(cur_loss, op='mean') train_loss = 0 - elapsed = time.time() - log_start_time + utils.distributed.barrier() + current_time = time.time() + elapsed = current_time - log_start_time avg_elapsed = elapsed / log_step avg_elapsed = utils.distributed.all_reduce_item(avg_elapsed, op='max') - log_start_time = time.time() + log_start_time = current_time log_step = 0 lr = optimizer.param_groups[0]['lr'] throughput = target_tokens / elapsed throughput = utils.distributed.all_reduce_item(throughput, op='sum') - meters['train_throughput'].update(throughput) + meters['train_throughput'].update(throughput, elapsed) target_tokens = 0 log_str = '| epoch {:3d} step {:>8d} | batches {:>6d} / {:d} | lr {:.3e} ' \ @@ -634,21 +637,26 @@ def train(tr_iter, va_iter, model, para_model, mems, model_config, optimizer, interrupted = timeout_handler.interrupted if (do_periodic_eval or is_final_step or interrupted) and not args.no_eval: + utils.distributed.barrier() eval_start_time = time.time() + val_loss = evaluate(va_iter, model, args) val_loss = utils.distributed.all_reduce_item(val_loss, op='mean') + utils.distributed.barrier() + eval_elapsed = time.time() - eval_start_time + logging.info('-' * 100) log_str = '| Eval {:3d} at step {:>8d} | time: {:5.2f}s ' \ '| valid loss {:5.2f}'.format( train_step // args.eval_interval, train_step, - (time.time() - eval_start_time), + eval_elapsed, val_loss, ) dllogger_data = { - 'valid_elapsed': (time.time() - eval_start_time), + 'valid_elapsed': eval_elapsed, 'valid_loss': val_loss, } @@ -683,6 +691,7 @@ def train(tr_iter, va_iter, model, para_model, mems, model_config, optimizer, scheduler_sparse.step(val_loss) # subtract eval time from timers for training + utils.distributed.barrier() log_start_time += time.time() - eval_start_time if interrupted: @@ -1022,7 +1031,10 @@ def lr_lambda(step): ########################################################################### # Loop over epochs. # At any point you can hit Ctrl + C to break out of training early. + + utils.distributed.barrier() start_time = time.time() + with TimeoutHandler() as timeout_handler: try: for epoch in itertools.count(start=start_epoch): @@ -1046,6 +1058,7 @@ def lr_lambda(step): except KeyboardInterrupt: logging.info('-' * 100) logging.info('Exiting from training early') + utils.distributed.barrier() elapsed = time.time() - start_time ########################################################################### @@ -1064,9 +1077,13 @@ def lr_lambda(step): model.load_state_dict(checkpoint['model_state']) # Run on test data. + utils.distributed.barrier() test_start_time = time.time() + test_loss = evaluate(te_iter, model, args) test_loss = utils.distributed.all_reduce_item(test_loss, 'mean') + + utils.distributed.barrier() test_elapsed = time.time() - test_start_time logging.info('=' * 100) diff --git a/PyTorch/LanguageModeling/Transformer-XL/pytorch/utils/distributed.py b/PyTorch/LanguageModeling/Transformer-XL/pytorch/utils/distributed.py index 7a8e38a2c..85da524e5 100644 --- a/PyTorch/LanguageModeling/Transformer-XL/pytorch/utils/distributed.py +++ b/PyTorch/LanguageModeling/Transformer-XL/pytorch/utils/distributed.py @@ -37,10 +37,13 @@ def init_distributed(cuda): def barrier(): """ - Call torch.distributed.barrier() if distritubed is in use + Call torch.distributed.barrier() if distritubed is in use, else calls + torch.cuda.synchronize() if CUDA is initialized. """ if torch.distributed.is_available() and torch.distributed.is_initialized(): torch.distributed.barrier() + elif torch.cuda.is_available() and torch.cuda.is_initialized(): + torch.cuda.synchronize() def get_rank(): diff --git a/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/fused_gather_embedding.py b/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/fused_gather_embedding.py index 03c04ef54..637d720d6 100644 --- a/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/fused_gather_embedding.py +++ b/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/fused_gather_embedding.py @@ -17,7 +17,7 @@ """ from absl import logging -from apex import amp +import torch from torch.autograd import Function from dlrm.cuda_ext import fused_embedding @@ -26,12 +26,14 @@ class BuckleEmbeddingFusedGatherFunction(Function): """Customized embedding gather """ @staticmethod + @torch.cuda.amp.custom_fwd(cast_inputs=torch.float32) def forward(ctx, embedding, indices, offsets, amp_train): output = fused_embedding.gather_gpu_fused_fwd(embedding, indices, offsets, amp_train) ctx.save_for_backward(embedding, indices, offsets) return output @staticmethod + @torch.cuda.amp.custom_bwd def backward(ctx, grad_output): embedding, indices, offsets = ctx.saved_tensors @@ -40,4 +42,4 @@ def backward(ctx, grad_output): return grad_weights, None, None, None -buckle_embedding_fused_gather = amp.float_function(BuckleEmbeddingFusedGatherFunction.apply) +buckle_embedding_fused_gather = BuckleEmbeddingFusedGatherFunction.apply diff --git a/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/sparse_embedding.py b/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/sparse_embedding.py index 41e542e6f..8eda2b599 100644 --- a/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/sparse_embedding.py +++ b/PyTorch/Recommendation/DLRM/dlrm/cuda_ext/sparse_embedding.py @@ -15,7 +15,7 @@ import copy import torch -from apex import amp +from torch.cuda import amp from dlrm.cuda_ext import sparse_gather from torch import nn from torch.autograd import Function @@ -24,6 +24,7 @@ class EmbeddingGatherFunction(Function): """Customized embedding gather with fused plain SGD""" @staticmethod + @torch.cuda.amp.custom_fwd(cast_inputs=torch.float32) def forward(ctx, embedding, indices): output = sparse_gather.gather_gpu_fwd(embedding, indices) ctx.save_for_backward(indices) @@ -31,11 +32,10 @@ def forward(ctx, embedding, indices): return output @staticmethod + @torch.cuda.amp.custom_fwd(cast_inputs=torch.float32) def backward(ctx, grad_output): indices = ctx.saved_tensors[0] - grad_embedding = sparse_gather.gather_gpu_bwd(grad_output, indices, ctx.num_features) - return grad_embedding, None @@ -66,4 +66,4 @@ def forward(self, categorical_inputs): return embedding_out -embedding_gather = amp.float_function(EmbeddingGatherFunction.apply) +embedding_gather = EmbeddingGatherFunction.apply diff --git a/PyTorch/Recommendation/DLRM/dlrm/data/datasets.py b/PyTorch/Recommendation/DLRM/dlrm/data/datasets.py index 101f234bf..9edd130b5 100644 --- a/PyTorch/Recommendation/DLRM/dlrm/data/datasets.py +++ b/PyTorch/Recommendation/DLRM/dlrm/data/datasets.py @@ -93,7 +93,7 @@ def __init__( self._label_file = None self._numerical_bytes_per_batch = bytes_per_feature[numerical_features[0]] * \ len(numerical_features) * batch_size - self._label_bytes_per_batch = np.dtype(np.bool).itemsize * batch_size + self._label_bytes_per_batch = np.dtype(bool).itemsize * batch_size self._number_of_numerical_features = len(numerical_features) chosen_mapping = feature_spec.source_spec[mapping] @@ -187,7 +187,7 @@ def _get_item(self, idx: int) -> Tuple[torch.Tensor, Optional[torch.Tensor], Opt def _get_label(self, idx: int) -> torch.Tensor: raw_label_data = os.pread(self._label_file, self._label_bytes_per_batch, idx * self._label_bytes_per_batch) - array = np.frombuffer(raw_label_data, dtype=np.bool) + array = np.frombuffer(raw_label_data, dtype=bool) return torch.from_numpy(array).to(torch.float32) def _get_numerical_features(self, idx: int) -> Optional[torch.Tensor]: diff --git a/PyTorch/Recommendation/DLRM/dlrm/data/feature_spec.py b/PyTorch/Recommendation/DLRM/dlrm/data/feature_spec.py index b3a2af7b9..858e5534a 100644 --- a/PyTorch/Recommendation/DLRM/dlrm/data/feature_spec.py +++ b/PyTorch/Recommendation/DLRM/dlrm/data/feature_spec.py @@ -172,7 +172,7 @@ def check_feature_spec(self): assert len(contained_features) == 1 # check label dtype - assert np.dtype(self.feature_spec[first_feature][DTYPE_SELECTOR]) == np.bool + assert np.dtype(self.feature_spec[first_feature][DTYPE_SELECTOR]) == bool else: assert False, "Feature of unknown type" @@ -202,7 +202,7 @@ def get_default_feature_spec(number_of_numerical_features, categorical_feature_c zip(categorical_feature_names, cat_feature_types, categorical_feature_cardinalities)} for f_name in numerical_feature_names: feature_dict[f_name] = {DTYPE_SELECTOR: str(np.dtype(np.float16))} - feature_dict[label_feature_name] = {DTYPE_SELECTOR: str(np.dtype(np.bool))} + feature_dict[label_feature_name] = {DTYPE_SELECTOR: str(np.dtype(bool))} channel_spec = {CATEGORICAL_CHANNEL: categorical_feature_names, NUMERICAL_CHANNEL: numerical_feature_names, diff --git a/PyTorch/Recommendation/DLRM/dlrm/scripts/main.py b/PyTorch/Recommendation/DLRM/dlrm/scripts/main.py index 53a21ef31..d83c12c5c 100644 --- a/PyTorch/Recommendation/DLRM/dlrm/scripts/main.py +++ b/PyTorch/Recommendation/DLRM/dlrm/scripts/main.py @@ -17,7 +17,7 @@ import os import sys from absl import app, flags, logging -from apex import amp, parallel, optimizers as apex_optim +from apex import optimizers as apex_optim from dlrm.data.feature_spec import FeatureSpec from dlrm.model.distributed import DistributedDlrm @@ -500,10 +500,7 @@ def parallelize(model): if world_size <= 1: return model - if use_gpu: - model.top_model = parallel.DistributedDataParallel(model.top_model) - else: # Use other backend for CPU - model.top_model = torch.nn.parallel.DistributedDataParallel(model.top_model) + model.top_model = torch.nn.parallel.DistributedDataParallel(model.top_model) return model if FLAGS.mode == 'test': @@ -627,10 +624,8 @@ def weight_update(): batch_iter = prefetcher(iter(data_loader_train), data_stream) for step in range(len(data_loader_train)): - timer.click() - numerical_features, categorical_features, click = next(batch_iter) - torch.cuda.synchronize() + timer.click(synchronize=(device == 'cuda')) global_step = steps_per_epoch * epoch + step @@ -773,7 +768,7 @@ def dist_evaluate(model, data_loader): batch_iter = prefetcher(iter(data_loader), data_stream) loss_fn = torch.nn.BCELoss(reduction="mean") - timer.click() + timer.click(synchronize=(device=='cuda')) for step in range(len(data_loader)): numerical_features, categorical_features, click = next(batch_iter) torch.cuda.synchronize() @@ -815,7 +810,7 @@ def dist_evaluate(model, data_loader): y_true.append(click) y_score.append(output) - timer.click() + timer.click(synchronize=(device == 'cuda')) if timer.measured is not None: metric_logger.update(step_time=timer.measured) diff --git a/PyTorch/Recommendation/DLRM/dlrm/scripts/utils.py b/PyTorch/Recommendation/DLRM/dlrm/scripts/utils.py index f4cb083c4..d1c7b1d42 100644 --- a/PyTorch/Recommendation/DLRM/dlrm/scripts/utils.py +++ b/PyTorch/Recommendation/DLRM/dlrm/scripts/utils.py @@ -210,8 +210,11 @@ def __init__(self): self._new = None self.measured = None - def click(self): + def click(self, synchronize=False): self._previous = self._new + + if synchronize: + torch.cuda.synchronize() self._new = time.time() if self._previous is not None: diff --git a/PyTorch/Recommendation/DLRM/preproc/split_dataset.py b/PyTorch/Recommendation/DLRM/preproc/split_dataset.py index a6d954f48..d10a68900 100644 --- a/PyTorch/Recommendation/DLRM/preproc/split_dataset.py +++ b/PyTorch/Recommendation/DLRM/preproc/split_dataset.py @@ -70,7 +70,7 @@ def split_binary_file( numerical_f.write(numerical_features.astype(np.float16).tobytes()) label = batch_data[:, 0] - label_f.write(label.astype(np.bool).tobytes()) + label_f.write(label.astype(bool).tobytes()) cat_offset = num_numerical_features + 1 for cat_idx, cat_feature_type in enumerate(cat_feature_types): diff --git a/PyTorch/Recommendation/NCF/README.md b/PyTorch/Recommendation/NCF/README.md index 7fad905e1..b813f6b7a 100644 --- a/PyTorch/Recommendation/NCF/README.md +++ b/PyTorch/Recommendation/NCF/README.md @@ -143,23 +143,11 @@ The ability to train deep learning networks with lower precision was introduced For information about: - How to train using mixed precision, refer to the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html) documentation. - Techniques used for mixed precision training, refer to the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. -- APEX tools for mixed precision training, refer to the [NVIDIA Apex: Tools for Easy Mixed-Precision Training in PyTorch](https://devblogs.nvidia.com/apex-pytorch-easy-mixed-precision-training/). #### Enabling mixed precision -Using the Automatic Mixed Precision (AMP) package requires two modifications in the source code. -The first one is to initialize the model and the optimizer using the `amp.initialize` function: -```python -model, optimizer = amp.initialize(model, optimizer, opt_level="O2" - keep_batchnorm_fp32=False, loss_scale='dynamic') -``` - -The second one is to use the AMP's loss scaling context manager: -```python -with amp.scale_loss(loss, optimizer) as scaled_loss: - scaled_loss.backward() -``` +Mixed precision training is turned off by default. To turn it on issue the `--amp` flag to the `main.py` script. #### Enabling TF32 diff --git a/PyTorch/Recommendation/NCF/ncf.py b/PyTorch/Recommendation/NCF/ncf.py index 23a0a6a43..dd0576635 100644 --- a/PyTorch/Recommendation/NCF/ncf.py +++ b/PyTorch/Recommendation/NCF/ncf.py @@ -47,9 +47,10 @@ import dllogger -from apex.parallel import DistributedDataParallel as DDP -from apex import amp +def synchronized_timestamp(): + torch.cuda.synchronize() + return time.time() def parse_args(): parser = ArgumentParser(description="Train a Neural Collaborative" @@ -218,7 +219,7 @@ def main(): torch.distributed.broadcast(torch.tensor([1], device="cuda"), 0) torch.cuda.synchronize() - main_start_time = time.time() + main_start_time = synchronized_timestamp() feature_spec_path = os.path.join(args.data, args.feature_spec_file) feature_spec = FeatureSpec.from_yaml(feature_spec_path) @@ -248,12 +249,8 @@ def main(): model = model.cuda() criterion = criterion.cuda() - if args.amp: - model, optimizer = amp.initialize(model, optimizer, opt_level="O2", - keep_batchnorm_fp32=False, loss_scale='dynamic') - if args.distributed: - model = DDP(model) + model = torch.nn.parallel.DistributedDataParallel(model) local_batch = args.batch_size // args.world_size traced_criterion = torch.jit.trace(criterion.forward, @@ -268,10 +265,10 @@ def main(): model.load_state_dict(state_dict) if args.mode == 'test': - start = time.time() + start = synchronized_timestamp() hr, ndcg, val_loss = val_epoch(model, test_loader, args.topk, distributed=args.distributed, world_size=args.world_size) - val_time = time.time() - start + val_time = synchronized_timestamp() - start eval_size = test_loader.raw_dataset_length eval_throughput = eval_size / val_time @@ -285,12 +282,13 @@ def main(): # to an uninitialized variable. max_hr = 0 best_epoch = 0 - best_model_timestamp = time.time() + best_model_timestamp = synchronized_timestamp() train_throughputs, eval_throughputs = [], [] + scaler = torch.cuda.amp.GradScaler(enabled=args.amp) for epoch in range(args.epochs): - begin = time.time() + begin = synchronized_timestamp() batch_dict_list = train_loader.get_epoch_data() num_batches = len(batch_dict_list) for i in range(num_batches // args.grads_accumulated): @@ -307,23 +305,21 @@ def main(): label_features = batch_dict[LABEL_CHANNEL_NAME] label_batch = label_features[label_feature_name] - outputs = model(user_batch, item_batch) - loss = traced_criterion(outputs, label_batch.view(-1, 1)).float() - loss = torch.mean(loss.view(-1), 0) + with torch.cuda.amp.autocast(enabled=args.amp): + outputs = model(user_batch, item_batch) + loss = traced_criterion(outputs, label_batch.view(-1, 1)) + loss = torch.mean(loss.float().view(-1), 0) - if args.amp: - with amp.scale_loss(loss, optimizer) as scaled_loss: - scaled_loss.backward() - else: - loss.backward() - optimizer.step() + scaler.scale(loss).backward() + scaler.step(optimizer) + scaler.update() for p in model.parameters(): p.grad = None del batch_dict_list - train_time = time.time() - begin - begin = time.time() + train_time = synchronized_timestamp() - begin + begin = synchronized_timestamp() epoch_samples = train_loader.length_after_augmentation train_throughput = epoch_samples / train_time @@ -332,7 +328,7 @@ def main(): hr, ndcg, val_loss = val_epoch(model, test_loader, args.topk, distributed=args.distributed, world_size=args.world_size) - val_time = time.time() - begin + val_time = synchronized_timestamp() - begin eval_size = test_loader.raw_dataset_length eval_throughput = eval_size / val_time eval_throughputs.append(eval_throughput) @@ -358,7 +354,7 @@ def main(): save_checkpoint_path = os.path.join(args.checkpoint_dir, 'model.pth') print("Saving the model to: ", save_checkpoint_path) torch.save(model.state_dict(), save_checkpoint_path) - best_model_timestamp = time.time() + best_model_timestamp = synchronized_timestamp() if args.threshold is not None: if hr >= args.threshold: @@ -372,7 +368,7 @@ def main(): 'mean_eval_throughput': np.mean(eval_throughputs), 'best_accuracy': max_hr, 'best_epoch': best_epoch, - 'time_to_target': time.time() - main_start_time, + 'time_to_target': synchronized_timestamp() - main_start_time, 'time_to_best_model': best_model_timestamp - main_start_time, 'validation_loss': float(val_loss.item()), 'train_loss': float(loss.item())}, diff --git a/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/inference.py b/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/inference.py index 92269547f..4e3d5b863 100755 --- a/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/inference.py +++ b/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/inference.py @@ -10,9 +10,7 @@ from tqdm import tqdm from maskrcnn_benchmark.data.datasets.evaluation import evaluate -from ..utils.comm import is_main_process -from ..utils.comm import all_gather -from ..utils.comm import synchronize +from ..utils.comm import is_main_process, all_gather, synchronize, synchronized_timestamp def compute_on_dataset(model, data_loader, device, steps=-1): @@ -83,7 +81,7 @@ def inference( ) dataset = data_loader.dataset dllogger.log(step="PARAMETER", data={"eval_dataset_name": dataset_name, "eval_num_samples":len(dataset)}) - start_time = time.time() + start_time = synchronized_timestamp() with torch.autograd.profiler.emit_nvtx(enabled=profile): predictions, latency = compute_on_dataset(model, data_loader, device, steps=steps) # wait for all processes to complete before measuring the time diff --git a/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/trainer.py b/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/trainer.py index 6ea610083..7a86b6184 100755 --- a/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/trainer.py +++ b/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/engine/trainer.py @@ -7,7 +7,7 @@ import torch import torch.distributed as dist -from maskrcnn_benchmark.utils.comm import get_world_size +from maskrcnn_benchmark.utils.comm import get_world_size, synchronized_timestamp from maskrcnn_benchmark.utils.metric_logger import MetricLogger def reduce_loss_dict(loss_dict): @@ -90,8 +90,8 @@ def do_train( prefetcher = Prefetcher(data_loader, device) start_iter = arguments["iteration"] model.train() - start_training_time = time.time() - end = time.time() + start_training_time = synchronized_timestamp() + end = start_training_time if use_amp: scaler = torch.cuda.amp.GradScaler(init_scale=8192.0) for iteration, (images, targets) in enumerate(prefetcher, start_iter): @@ -169,7 +169,7 @@ def _take_step(): if early_exit: break - total_training_time = time.time() - start_training_time + total_training_time = synchronized_timestamp() - start_training_time total_time_str = str(datetime.timedelta(seconds=total_training_time)) dllogger.log(step=tuple(), data={"e2e_train_time": total_training_time, "train_perf_fps": max_iter * cfg.SOLVER.IMS_PER_BATCH / total_training_time}) diff --git a/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/utils/comm.py b/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/utils/comm.py index 3967f8ea8..f2c2609a3 100755 --- a/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/utils/comm.py +++ b/PyTorch/Segmentation/MaskRCNN/pytorch/maskrcnn_benchmark/utils/comm.py @@ -116,3 +116,9 @@ def reduce_dict(input_dict, average=True): values /= world_size reduced_dict = {k: v for k, v in zip(names, values)} return reduced_dict + + +def synchronized_timestamp(): + torch.cuda.synchronize() + return time.time() + diff --git a/PyTorch/Segmentation/nnUNet/main.py b/PyTorch/Segmentation/nnUNet/main.py index 5816918e3..3ec37e98b 100755 --- a/PyTorch/Segmentation/nnUNet/main.py +++ b/PyTorch/Segmentation/nnUNet/main.py @@ -15,13 +15,12 @@ import os import torch +from data_loading.data_module import DataModule +from nnunet.nn_unet import NNUnet from pytorch_lightning import Trainer, seed_everything from pytorch_lightning.callbacks import ModelCheckpoint, ModelSummary, RichProgressBar from pytorch_lightning.plugins.io import AsyncCheckpointIO from pytorch_lightning.strategies import DDPStrategy - -from data_loading.data_module import DataModule -from nnunet.nn_unet import NNUnet from utils.args import get_main_args from utils.logger import LoggingCallback from utils.utils import make_empty_dir, set_cuda_devices, set_granularity, verify_ckpt_path diff --git a/PyTorch/Segmentation/nnUNet/nnunet/nn_unet.py b/PyTorch/Segmentation/nnUNet/nnunet/nn_unet.py index 8735d6040..aabfa5a11 100644 --- a/PyTorch/Segmentation/nnUNet/nnunet/nn_unet.py +++ b/PyTorch/Segmentation/nnUNet/nnunet/nn_unet.py @@ -22,16 +22,15 @@ from data_loading.data_module import get_data_path, get_test_fnames from monai.inferers import sliding_window_inference from monai.networks.nets import DynUNet +from nnunet.brats22_model import UNet3D +from nnunet.loss import Loss, LossBraTS +from nnunet.metrics import Dice from pytorch_lightning.utilities import rank_zero_only from scipy.special import expit, softmax from skimage.transform import resize from utils.logger import DLLogger from utils.utils import get_config_file, print0 -from nnunet.brats22_model import UNet3D -from nnunet.loss import Loss, LossBraTS -from nnunet.metrics import Dice - class NNUnet(pl.LightningModule): def __init__(self, args, triton=False, data_dir=None): @@ -279,7 +278,7 @@ def test_epoch_end(self, outputs): @rank_zero_only def on_fit_end(self): - if not self.args.benchmark and self.args.skip_first_n_eval == 0: + if not self.args.benchmark: metrics = {} metrics["dice_score"] = round(self.best_mean.item(), 2) metrics["train_loss"] = round(sum(self.train_loss) / len(self.train_loss), 4) diff --git a/PyTorch/Segmentation/nnUNet/utils/logger.py b/PyTorch/Segmentation/nnUNet/utils/logger.py index 2c075ed40..041bf0b99 100644 --- a/PyTorch/Segmentation/nnUNet/utils/logger.py +++ b/PyTorch/Segmentation/nnUNet/utils/logger.py @@ -17,6 +17,7 @@ import dllogger as logger import numpy as np +import torch from dllogger import JSONStreamBackend, StdOutBackend, Verbosity from pytorch_lightning import Callback from pytorch_lightning.utilities import rank_zero_only @@ -70,6 +71,7 @@ def do_step(self): if self.step > self.warmup_steps: self.step += 1 return + torch.cuda.synchronize() self.timestamps.append(time.perf_counter()) def on_train_batch_end(self, trainer, pl_module, outputs, batch, batch_idx): diff --git a/PyTorch/Segmentation/nnUNet/utils/utils.py b/PyTorch/Segmentation/nnUNet/utils/utils.py index a029e0aca..03f49cc85 100755 --- a/PyTorch/Segmentation/nnUNet/utils/utils.py +++ b/PyTorch/Segmentation/nnUNet/utils/utils.py @@ -58,7 +58,7 @@ def verify_ckpt_path(args): return resume_path_results print("[Warning] Checkpoint not found. Starting training from scratch.") return None - if not os.path.isfile(args.ckpt_path): + if args.ckpt_path is None or not os.path.isfile(args.ckpt_path): print(f"Provided checkpoint {args.ckpt_path} is not a file. Starting training from scratch.") return None return args.ckpt_path diff --git a/PyTorch/SpeechRecognition/Jasper/Dockerfile b/PyTorch/SpeechRecognition/Jasper/Dockerfile index df0fcfe4d..0c8cad41b 100755 --- a/PyTorch/SpeechRecognition/Jasper/Dockerfile +++ b/PyTorch/SpeechRecognition/Jasper/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:20.10-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:23.10-py3 FROM ${FROM_IMAGE_NAME} RUN apt update && apt install -y libsndfile1 && apt install -y sox && rm -rf /var/lib/apt/lists/* @@ -24,7 +24,5 @@ COPY requirements.txt . RUN if [[ ! -z "$(command -v conda)" ]]; then conda install -y pyyaml==5.4.1; fi RUN pip install --disable-pip-version-check -U -r requirements.txt -RUN pip install --force-reinstall --extra-index-url https://developer.download.nvidia.com/compute/redist nvidia-dali-cuda110==1.2.0 - # Copy rest of files COPY . . diff --git a/PyTorch/SpeechRecognition/Jasper/common/audio.py b/PyTorch/SpeechRecognition/Jasper/common/audio.py index 916394f50..505280778 100644 --- a/PyTorch/SpeechRecognition/Jasper/common/audio.py +++ b/PyTorch/SpeechRecognition/Jasper/common/audio.py @@ -45,7 +45,7 @@ def __init__(self, filename, target_sr=None, int_values=False, offset=0, duration=0, trim=False, trim_db=60): """Create audio segment from samples. - Samples are convert float32 internally, with int scaled to [-1, 1]. + Samples are converted to float32 internally, with int scaled to [-1, 1]. Load a file supported by librosa and return as an AudioSegment. :param filename: path of file to load :param target_sr: the desired sample rate @@ -67,10 +67,11 @@ def __init__(self, filename, target_sr=None, int_values=False, offset=0, samples = self._convert_samples_to_float32(samples) if target_sr is not None and target_sr != sample_rate: - samples = librosa.core.resample(samples, sample_rate, target_sr) + samples = librosa.resample(samples, orig_sr=sample_rate, + target_sr=target_sr) sample_rate = target_sr if trim: - samples, _ = librosa.effects.trim(samples, trim_db) + samples, _ = librosa.effects.trim(samples, top_db=trim_db) self._samples = samples self._sample_rate = sample_rate if self._samples.ndim >= 2: diff --git a/PyTorch/SpeechRecognition/Jasper/common/features.py b/PyTorch/SpeechRecognition/Jasper/common/features.py index da57351ac..f60b8a365 100644 --- a/PyTorch/SpeechRecognition/Jasper/common/features.py +++ b/PyTorch/SpeechRecognition/Jasper/common/features.py @@ -233,7 +233,7 @@ def __init__(self, spec_augment=None, cutout_augment=None, window_tensor = window_fn(self.win_length, periodic=False) if window_fn else None filterbanks = torch.tensor( - librosa.filters.mel(sample_rate, self.n_fft, n_mels=n_filt, + librosa.filters.mel(sr=sample_rate, n_fft=self.n_fft, n_mels=n_filt, fmin=lowfreq, fmax=highfreq), dtype=torch.float).unsqueeze(0) # torchscript @@ -244,12 +244,13 @@ def get_seq_len(self, seq_len): return torch.ceil(seq_len.to(dtype=torch.float) / self.hop_length).to( dtype=torch.int) - # do stft # TORCHSCRIPT: center removed due to bug def stft(self, x): - return torch.stft(x, n_fft=self.n_fft, hop_length=self.hop_length, + spec = torch.stft(x, n_fft=self.n_fft, hop_length=self.hop_length, win_length=self.win_length, - window=self.window.to(dtype=torch.float)) + window=self.window.to(dtype=torch.float), + return_complex=True) + return torch.view_as_real(spec) @torch.no_grad() def calculate_features(self, x, seq_len): diff --git a/PyTorch/SpeechRecognition/Jasper/inference.py b/PyTorch/SpeechRecognition/Jasper/inference.py index 4b2524081..045dcad78 100644 --- a/PyTorch/SpeechRecognition/Jasper/inference.py +++ b/PyTorch/SpeechRecognition/Jasper/inference.py @@ -324,7 +324,7 @@ def main(): feats, feat_lens = feat_proc(audio, audio_lens) sync() - t1 = time.perf_counter() + t1 = time.time() if args.amp: feats = feats.half() @@ -340,7 +340,7 @@ def main(): preds = greedy_decoder(log_probs) sync() - t2 = time.perf_counter() + t2 = time.time() # burn-in period; wait for a new loader due to num_workers if it >= 1 and (args.steps == 0 or it >= args.warmup_steps): @@ -358,7 +358,7 @@ def main(): break sync() - t0 = time.perf_counter() + t0 = time.time() # communicate the results if args.transcribe_wav: diff --git a/PyTorch/SpeechRecognition/Jasper/requirements.txt b/PyTorch/SpeechRecognition/Jasper/requirements.txt index ed78397f2..cc1b1d5cb 100755 --- a/PyTorch/SpeechRecognition/Jasper/requirements.txt +++ b/PyTorch/SpeechRecognition/Jasper/requirements.txt @@ -1,8 +1,7 @@ inflect==5.3.0 ipdb -librosa==0.8.0 -pandas==1.1.4 -pycuda==2020.1 +librosa==0.9.0 +pandas==1.5.2 pyyaml>=5.4 soundfile sox==1.4.1 diff --git a/PyTorch/SpeechRecognition/Jasper/train.py b/PyTorch/SpeechRecognition/Jasper/train.py index eedd7f528..43cc567c0 100644 --- a/PyTorch/SpeechRecognition/Jasper/train.py +++ b/PyTorch/SpeechRecognition/Jasper/train.py @@ -54,7 +54,7 @@ def parse_args(): training.add_argument('--amp', '--fp16', action='http://github.com/store_true', default=False, help='Use pytorch native mixed precision training') training.add_argument('--seed', default=42, type=int, help='Random seed') - training.add_argument('--local_rank', default=os.getenv('LOCAL_RANK', 0), + training.add_argument('--local_rank', '--local-rank', default=os.getenv('LOCAL_RANK', 0), type=int, help='GPU id used for distributed training') training.add_argument('--pre_allocate_range', default=None, type=int, nargs=2, help='Warmup with batches of length [min, max] before training') @@ -142,6 +142,7 @@ def evaluate(epoch, step, val_loader, val_feat_proc, labels, model, continue model.eval() + torch.cuda.synchronize() start_time = time.time() agg = {'losses': [], 'preds': [], 'txts': []} @@ -166,6 +167,7 @@ def evaluate(epoch, step, val_loader, val_feat_proc, labels, model, agg['txts'] += helpers.gather_transcripts([txt], [txt_lens], labels) wer, loss = process_evaluation_epoch(agg) + torch.cuda.synchronize() log(() if epoch is None else (epoch,), step, subset, {'loss': loss, 'wer': 100.0 * wer, 'took': time.time() - start_time}) @@ -379,11 +381,11 @@ def main(): if multi_gpu and not use_dali: train_loader.sampler.set_epoch(epoch) + torch.cuda.synchronize() + epoch_start_time = time.time() epoch_utts = 0 epoch_loss = 0 accumulated_batches = 0 - epoch_start_time = time.time() - epoch_eval_time = 0 for batch in train_loader: @@ -461,7 +463,6 @@ def main(): step_start_time = time.time() if step % args.eval_frequency == 0: - tik = time.time() wer = evaluate(epoch, step, val_loader, val_feat_proc, symbols, model, ema_model, ctc_loss, greedy_decoder, args.amp, use_dali) @@ -470,7 +471,6 @@ def main(): checkpointer.save(model, ema_model, optimizer, scaler, epoch, step, best_wer, is_best=True) best_wer = wer - epoch_eval_time += time.time() - tik step += 1 accumulated_batches = 0 @@ -481,6 +481,7 @@ def main(): if not use_dali and step > steps_per_epoch * epoch: break + torch.cuda.synchronize() epoch_time = time.time() - epoch_start_time epoch_loss /= steps_per_epoch log((epoch,), None, 'train_avg', {'throughput': epoch_utts / epoch_time, diff --git a/PyTorch/SpeechRecognition/Jasper/utils/preprocessing_utils.py b/PyTorch/SpeechRecognition/Jasper/utils/preprocessing_utils.py index 15605cea2..2074e3a13 100644 --- a/PyTorch/SpeechRecognition/Jasper/utils/preprocessing_utils.py +++ b/PyTorch/SpeechRecognition/Jasper/utils/preprocessing_utils.py @@ -15,7 +15,6 @@ #!/usr/bin/env python import os import multiprocessing -import librosa import functools import sox diff --git a/PyTorch/SpeechRecognition/QuartzNet/Dockerfile b/PyTorch/SpeechRecognition/QuartzNet/Dockerfile index b95850f37..256bd687b 100644 --- a/PyTorch/SpeechRecognition/QuartzNet/Dockerfile +++ b/PyTorch/SpeechRecognition/QuartzNet/Dockerfile @@ -24,7 +24,5 @@ COPY requirements.txt . RUN if [[ ! -z "$(command -v conda)" ]]; then conda install -y pyyaml==5.4.1; fi RUN pip install --disable-pip-version-check -U -r requirements.txt -RUN pip install --extra-index-url https://developer.download.nvidia.com/compute/redist nvidia-dali-cuda110==1.2.0 - # Copy rest of files COPY . . diff --git a/PyTorch/SpeechRecognition/QuartzNet/common/features.py b/PyTorch/SpeechRecognition/QuartzNet/common/features.py index 6a5479cd1..881fe6a33 100644 --- a/PyTorch/SpeechRecognition/QuartzNet/common/features.py +++ b/PyTorch/SpeechRecognition/QuartzNet/common/features.py @@ -248,12 +248,13 @@ def get_seq_len(self, seq_len): return torch.ceil(seq_len.to(dtype=torch.float) / self.hop_length).to( dtype=torch.int) - # do stft # TORCHSCRIPT: center removed due to bug def stft(self, x): - return torch.stft(x, n_fft=self.n_fft, hop_length=self.hop_length, + spec = torch.stft(x, n_fft=self.n_fft, hop_length=self.hop_length, win_length=self.win_length, - window=self.window.to(dtype=torch.float)) + window=self.window.to(dtype=torch.float), + return_complex=True) + return torch.view_as_real(spec) @torch.no_grad() def calculate_features(self, x, seq_len): diff --git a/PyTorch/SpeechRecognition/QuartzNet/inference.py b/PyTorch/SpeechRecognition/QuartzNet/inference.py index 38dfc8734..8cf12bcfd 100644 --- a/PyTorch/SpeechRecognition/QuartzNet/inference.py +++ b/PyTorch/SpeechRecognition/QuartzNet/inference.py @@ -334,7 +334,7 @@ def main(): feats, feat_lens = feat_proc(audio, audio_lens) sync() - t1 = time.perf_counter() + t1 = time.time() if args.amp: feats = feats.half() @@ -347,7 +347,7 @@ def main(): preds = greedy_decoder(log_probs) sync() - t2 = time.perf_counter() + t2 = time.time() # burn-in period; wait for a new loader due to num_workers if it >= 1 and (args.steps == 0 or it >= args.warmup_steps): @@ -365,7 +365,7 @@ def main(): break sync() - t0 = time.perf_counter() + t0 = time.time() # communicate the results if args.transcribe_wav: diff --git a/PyTorch/SpeechRecognition/QuartzNet/requirements.txt b/PyTorch/SpeechRecognition/QuartzNet/requirements.txt index af777ae1c..cc1b1d5cb 100644 --- a/PyTorch/SpeechRecognition/QuartzNet/requirements.txt +++ b/PyTorch/SpeechRecognition/QuartzNet/requirements.txt @@ -1,8 +1,7 @@ inflect==5.3.0 ipdb librosa==0.9.0 -pandas==1.1.4 -pycuda==2020.1 +pandas==1.5.2 pyyaml>=5.4 soundfile sox==1.4.1 diff --git a/PyTorch/SpeechRecognition/QuartzNet/train.py b/PyTorch/SpeechRecognition/QuartzNet/train.py index 5c8b13b30..4c97d216d 100644 --- a/PyTorch/SpeechRecognition/QuartzNet/train.py +++ b/PyTorch/SpeechRecognition/QuartzNet/train.py @@ -56,7 +56,7 @@ def parse_args(): training.add_argument('--amp', '--fp16', action='http://github.com/store_true', default=False, help='Use pytorch native mixed precision training') training.add_argument('--seed', default=None, type=int, help='Random seed') - training.add_argument('--local_rank', default=os.getenv('LOCAL_RANK', 0), type=int, + training.add_argument('--local_rank', '--local-rank', default=os.getenv('LOCAL_RANK', 0), type=int, help='GPU id used for distributed training') training.add_argument('--pre_allocate_range', default=None, type=int, nargs=2, help='Warmup with batches of length [min, max] before training') @@ -163,6 +163,7 @@ def evaluate(epoch, step, val_loader, val_feat_proc, labels, model, continue model.eval() + torch.cuda.synchronize() start_time = time.time() agg = {'losses': [], 'preds': [], 'txts': []} @@ -187,6 +188,7 @@ def evaluate(epoch, step, val_loader, val_feat_proc, labels, model, agg['txts'] += helpers.gather_transcripts([txt], [txt_lens], labels) wer, loss = process_evaluation_epoch(agg) + torch.cuda.synchronize() log(() if epoch is None else (epoch,), step, subset, {'loss': loss, 'wer': 100.0 * wer, 'took': time.time() - start_time}) @@ -410,11 +412,11 @@ def main(): if multi_gpu and not use_dali: train_loader.sampler.set_epoch(epoch) + torch.cuda.synchronize() + epoch_start_time = time.time() epoch_utts = 0 epoch_loss = 0 accumulated_batches = 0 - epoch_start_time = time.time() - epoch_eval_time = 0 for batch in train_loader: @@ -493,7 +495,6 @@ def main(): step_start_time = time.time() if step % args.eval_frequency == 0: - tik = time.time() wer = evaluate(epoch, step, val_loader, val_feat_proc, symbols, model, ema_model, ctc_loss, greedy_decoder, args.amp, use_dali) @@ -502,7 +503,6 @@ def main(): checkpointer.save(model, ema_model, optimizer, scaler, epoch, step, best_wer, is_best=True) best_wer = wer - epoch_eval_time += time.time() - tik step += 1 accumulated_batches = 0 @@ -513,6 +513,7 @@ def main(): if not use_dali and step > steps_per_epoch * epoch: break + torch.cuda.synchronize() epoch_time = time.time() - epoch_start_time epoch_loss /= steps_per_epoch log((epoch,), None, 'train_avg', {'throughput': epoch_utts / epoch_time, diff --git a/PyTorch/SpeechRecognition/wav2vec2/.dockerignore b/PyTorch/SpeechRecognition/wav2vec2/.dockerignore new file mode 100644 index 000000000..7066d6a35 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/.dockerignore @@ -0,0 +1,6 @@ +datasets/ +results/ +models/ +pretrained_models/ +tb_*/ +*.pt diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/cuml_auto_arima_electricity.yaml b/PyTorch/SpeechRecognition/wav2vec2/Dockerfile similarity index 60% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/cuml_auto_arima_electricity.yaml rename to PyTorch/SpeechRecognition/wav2vec2/Dockerfile index d82464068..f1d7936c1 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/cuml_auto_arima_electricity.yaml +++ b/PyTorch/SpeechRecognition/wav2vec2/Dockerfile @@ -1,10 +1,10 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023 NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,6 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -dataset: - config: - stride: 400 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.11-py3 +FROM ${FROM_IMAGE_NAME} + +ENV PYTHONPATH /workspace/wav2vec2 +WORKDIR /workspace/wav2vec2 + +COPY requirements.txt . +RUN pip install -r requirements.txt + +COPY . . diff --git a/PyTorch/SpeechRecognition/wav2vec2/README.md b/PyTorch/SpeechRecognition/wav2vec2/README.md new file mode 100644 index 000000000..a29ad4d7e --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/README.md @@ -0,0 +1,587 @@ +# wav2vec 2.0 for PyTorch + +This repository provides a script and recipe to train the wav2vec 2.0 model to achieve state-of-the-art accuracy. The content of this repository is tested and maintained by NVIDIA. + +## Table Of Contents + +- [Model overview](#model-overview) + * [Model architecture](#model-architecture) + * [Default configuration](#default-configuration) + * [Feature support matrix](#feature-support-matrix) + * [Features](#features) + * [Mixed precision training](#mixed-precision-training) + * [Enabling mixed precision](#enabling-mixed-precision) + * [Enabling TF32](#enabling-tf32) + * [Glossary](#glossary) +- [Setup](#setup) + * [Requirements](#requirements) +- [Quick Start Guide](#quick-start-guide) +- [Advanced](#advanced) + * [Scripts and sample code](#scripts-and-sample-code) + * [Parameters](#parameters) + * [Adjusting batch size and the number of GPUs](#adjusting-batch-size-and-the-number-of-gpus) + * [Adjusting mixed precision](#adjusting-mixed-precision) + * [Adjusting Hourglass Transformer](#adjusting-hourglass-transformer) + * [Command-line options](#command-line-options) + * [Getting the data](#getting-the-data) + * [Dataset guidelines](#dataset-guidelines) + * [Multi-dataset](#multi-dataset) + * [Training process](#training-process) + * [Inference process](#inference-process) +- [Performance](#performance) + * [Benchmarking](#benchmarking) + * [Training performance benchmark](#training-performance-benchmark) + * [Inference performance benchmark](#inference-performance-benchmark) + * [Results](#results) + * [Training accuracy results](#training-accuracy-results) + * [Training accuracy: NVIDIA DGX A100 (8x A100 80GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-80gb) + * [Training stability test](#training-stability-test) + * [Training performance results](#training-performance-results) + * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-a100-8x-a100-80gb) + * [Inference performance results](#inference-performance-results) + * [Inference performance: NVIDIA DGX A100 (1x A100 80GB)](#inference-performance-nvidia-dgx-a100-1x-a100-80gb) +- [Release notes](#release-notes) + * [Changelog](#changelog) + * [Known issues](#known-issues) + +## Model overview + +This repository provides an optimized implementation of the wav2vec 2.0 model, as described in the paper [wav2vec 2.0: A Framework for Self-Supervised Learning of Speech Representations](https://proceedings.neurips.cc/paper/2020/file/92d1e1eb1cd6f9fba3227870bb6d7f07-Paper.pdf). It is based on the [Fairseq codebase](https://github.com/facebookresearch/fairseq) published by the authors of the paper. The wav2vec 2.0 model is pre-trained unsupervised on large corpora of speech recordings. Afterward, it can be quickly fine-tuned in a supervised way for speech recognition or serve as an extractor of high-level features and pseudo-phonemes for other applications. + +The differences between this wav2vec 2.0 and the reference implementation are: +* Support for increased batch size, which does not change batch-dependent constants for negative sampling and loss calculation and improves hardware utilization +* Support for the [Hourglass Transformer](https://arxiv.org/abs/2110.13711) architecture, which in the default setting improves the training speed of the `Base` model by 1.4x, lowers memory consumption by 38%, and retains accuracy + +This model is trained with mixed precision using Tensor Cores on NVIDIA Volta, NVIDIA Turning, and the NVIDIA Ampere GPU architectures. Therefore, researchers can get results up to 1.35x faster than training without Tensor Cores while experiencing the benefits of mixed precision training. This model is tested against each NGC monthly container release to ensure consistent accuracy and performance over time. + +### Model architecture + +The model takes raw waveforms as its input. A fully convolutional feature extractor reduces the resolution of the signal to a single vector roughly every 20 ms. Most of the computation is performed in the transformer encoder part of the model. The outputs of the transformer, and quantized outputs from the feature extractor, serve as inputs to the contrastive loss. During fine-tuning, this loss is replaced with the CTC loss, and quantization is not performed. + + +

+ wav2vec 2.0 model architecture +

+

+ Figure 1. The architecture of wav2vec 2.0 ([source](https://proceedings.neurips.cc/paper/2020/file/92d1e1eb1cd6f9fba3227870bb6d7f07-Paper.pdf)). The model is composed of a convolutional feature extractor, and a transformer encoder. During fine-tuning, quantization is disabled and contrastive loss is replaced with the CTC loss function. +

+ +In addition, our model uses the Hourglass Transformer architecture for the encoder. This architecture uses fixed-sized pooling in order to reduce the time dimension _T_ of the signal, and thus, lower the _O(T²)_ cost of the self-attention mechanism. + +

+ The Hourglass Transformer module +

+

+ Figure 2. The Hourglass Transformer module ([source](https://arxiv.org/abs/2110.13711)). The signal is processed by the initial layers and downsampled. Most of the layers operate on the downsampled signal. Finally, the signal is upsampled for the final layers. The Hourglass Transformer replaced a regular stack of transformer layers, typically improving throughput and lowering memory consumption. +

+ +### Default configuration + +The following features were implemented in this model: +- general: + - multi-GPU and multi-node training + - Hourglass Transformer architecture + - dynamic loss scaling with backoff for tensor cores (mixed precision) training + - mixed-precision training with `O2` optimization level, based on float16 or bfloat16 +- training: + - support for variable batch size without changing batch-dependent constants for the loss function +- inference: + - masking for inference with a larger batch + +Our main recipes replicate the `Base` model described in the wav2vec 2.0 paper, and use Hourglass Transformer with pooling factor 4. Note that Hourglass Transformer can be entirely disabled and this codebase is compatible with Fairseq checkpoints. + +Below we present performance numbers for the Hourglass Transformer with different pooling factors (`Base` model, pre-training, A100 80GB GPU, bfloat16): + +| Configuration | Throughput speedup | GPU memory (% of Baseline) | +|:-------------------|--------------------:|----------------:| +| Baseline | 1.00 | 100.00% | +| Hourglass factor=2 | 1.25 | 70.98% | +| Hourglass factor=3 | 1.33 | 64.31% | +| **Hourglass factor=4 (default)** | **1.37** | **62.35%** | +| Hourglass factor=5 | 1.39 | 60.00% | +| Hourglass factor=6 | 1.40 | 59.61% | + +### Feature support matrix + +This model supports the following features: + +| Feature | wav2vec 2.0 | +|---------------------------------|-------------| +| Multi-node training | yes | +| Automatic mixed precision (AMP) | yes | + +#### Features + +**Automatic Mixed Precision (AMP)** +This implementation uses automatic mixed-precision training ported from Fairseq. +It allows us to use FP16 or BF16 training with FP16 master weights. + +### Mixed precision training + +Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in NVIDIA Volta, and following with both the NVIDIA Turing and Ampere architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures. Using [mixed precision training](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) previously required two steps: +1. Porting the model to use the FP16 data type where appropriate. +2. Adding loss scaling to preserve small gradient values. + +For information about: +- How to train using mixed precision, refer to the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) documentation. +- Techniques used for mixed precision training, refer to the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. + +#### Enabling mixed precision + +For training and inference, mixed precision can be enabled by adding the `--fp16` flag or `--bf16` flag, depending on the target’s lower precision. NVIDIA Ampere and later architectures provide hardware support for bfloat16, which is beneficial for this model, as it skips certain stabilizing FP32 casts. For NVIDIA Volta and NVIDIA Turing architectures, select `--fp16`. + +#### Enabling TF32 + +TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math, also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on NVIDIA Volta GPUs. + +TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require a high dynamic range for weights or activations. + +For more information, refer to the [TensorFloat-32 in the A100 GPU Accelerates AI Training, HPC up to 20x](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) blog post. + +TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by default. + +### Glossary + +**Brain Floating Point (bfloat16)** +A 16-bit floating point format that uses an 8-bit exponent, a 7-bit fraction, and a sign bit. +Contrary to float16, which uses a 5-bit exponent, bfloat16 retains the same exponent precision as float32, +and its robustness with respect to wide ranges of values during training. + +**Fine-tuning** +Training an already pretrained model further using a task-specific dataset for subject-specific refinements by adding task-specific layers on top if required. + +**Hourglass Transformer** +Architecture proposed in the paper [Hierarchical Transformers Are More Efficient Language Models](https://arxiv.org/abs/2110.13711), which improves resource consumption +of a stack of transformer layers, in many cases retaining the accuracy. + +**Pre-training** +Training a model on vast amounts of data on the same (or different) task to build general understandings. + +**Transformer** +The paper [Attention Is All You Need](https://arxiv.org/abs/1706.03762) introduces a novel architecture called transformer that uses an attention mechanism and transforms one sequence into another. + +**Connectionist Temporal Classification (CTC) Loss** +A loss function introduced in [Connectionist temporal classification: Labelling unsegmented sequence data with recurrent neural networks](https://www.cs.toronto.edu/~graves/icml_2006.pdf). It calculates the probability of all valid output sequences with repetitions, and allows to train end-to-end ASR models without any prior alignments of transcriptions to audio. + +## Setup + +The following section lists the requirements you need to meet in order to start training the wav2vec 2.0 model. + +### Requirements + +This repository contains a Dockerfile that extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: +- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) +- [PyTorch 22.11-py3 NGC container](https://ngc.nvidia.com/registry/nvidia-pytorch) or newer +- Supported GPUs: + - [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) + - [NVIDIA Turing architecture](https://www.nvidia.com/en-us/design-visualization/technologies/turing-architecture/) + - [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) + +For more information about how to get started with NGC containers, refer to the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: +- [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) +- [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) +- [Running PyTorch](https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes/running.html#running) + +For those unable to use the PyTorch NGC container to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). + +## Quick Start Guide + +To train your model using mixed or TF32 precision with Tensor Cores or using FP32, perform the following steps using the default parameters of the wav2vec 2.0 model on the LibriSpeech dataset. For the specifics concerning training and inference, refer to the [Advanced](#advanced) section. + +1. Clone the repository. + ```bash + git clone https://github.com/NVIDIA/DeepLearningExamples + cd DeepLearningExamples/PyTorch/SpeechRecognition/wav2vec2 + ``` + +2. Build the 22.11-py3 PyTorch NGC container and start an interactive session to run training/inference. `DATASET_DIR` on the host will be mounted as `/datasets` inside the container. + ```bash + bash scripts/docker/build.sh + DATASET_DIR=[PATH] bash scripts/docker/run.sh + ``` + +3. Download and preprocess the dataset. The dataset size is about 70GB and this step could take up to a few hours to complete. + ```bash + bash scripts/download_data.sh + ``` + +4. Generate filelists. + ```bash + bash scripts/generate_filelists.sh + ``` + +5. Start pre-training. + ```bash + NUM_GPUS=[NUM] UPDATE_FREQUENCY=[NUM] NUM_CONCAT_BATCHES=[NUM] BF16=[true|false] FP16=[true|false] \ + bash scripts/pretrain_base.sh + ``` + Adjust the variables to maintain `NUM_GPUS x NUM_CONCAT_BATCHES x UPDATE_FREQUENCY = 64`. + For more details, refer to [Adjusting batch size and the number of GPUs](#adjusting-batch-size-and-the-number-of-gpus) and [Adjusting mixed precision](#adjusting-mixed-precision). + + For instance: + ```bash + # Mixed precision training on 4x A100 40GB + NUM_GPUS=4 NUM_CONCAT_BATCHES=8 UPDATE_FREQUENCY=2 BF16=true bash scripts/pretrain_base.sh + ``` + +6. Start fine-tuning. + ```bash + PRETRAINED_MODEL=[PATH] NUM_GPUS=[NUM] UPDATE_FREQUENCY=[NUM] BF16=[true|false] FP16=[true|false] \ + bash scripts/finetune_base_960h.sh + ``` + Adjust the variables to maintain `NUM_GPUS x NUM_CONCAT_BATCHES x UPDATE_FREQUENCY = 8`. + +7. Start inference/predictions. + ```bash + FINETUNED_MODEL=[PATH] BF16=[true|false] FP16=[true|false] BATCH_SIZE=[NUM] bash scripts/inference.sh + ``` + +Now that you have your model trained and evaluated, you can choose to compare your training results with our [Training accuracy results](#training-accuracy-results). You can also choose to benchmark your performance to [Training performance benchmark](#training-performance-results) or [Inference performance benchmark](#inference-performance-results). Following the steps in these sections ensures you achieve the same accuracy and performance results as stated in the [Results](#results) section. +## Advanced + +The following sections provide greater details of the dataset, running training and inference, and the training results. + +### Scripts and sample code + +In the root directory, the most important files are: +```bash +. +├── common # Generic code for training +│ ├── fairseq # Parts of https://github.com/facebookresearch/fairseq +│ └── ... +├── inference.py # Evaluates trained models and measures latency +├── scripts +│ ├── download_wav2vec2_base.sh # Downloads pre-trained models from NGC +│ ├── finetune_base_960h.sh # Helper script for fine-tuning with train.py +│ ├── inference.sh # Helper script for inference.py +│ ├── pretrain_base.sh # Helper script for pre-training with train.py +│ └── ... +├── train.py # Main pre-training and fine-tuning script +├── utils # Misc standalone Python scripts +└── wav2vec2 # Code specific to wav2vec 2.0 model + ├── arg_parser.py + ├── criterion.py + ├── logging.py + ├── model.py + └── utils.py +``` + +### Parameters + +Parameters can be set through environment variables. +The most important available parameters for `scripts/pretrain_base.sh` script are: +```bash +OUTPUT_DIR directory for results, logs, and created checkpoints + (default: "./results/pretrain_base") +NUM_GPUS number of GPUs to use. (default: 8) +MAX_TOKENS upper limit for the number of tokens in a batch; changing + this value alters loss function consts (default: 1400000) +NUM_CONCAT_BATCHES number of sub-batches, each with MAX_TOKENS tokens, + to make up one large batch (default: 8) +UPDATE_FREQ number of grad accumulation steps before the update (default: 1) +MAX_UPDATE training length expressed as the number of updates (default: 400000) +LEARNING_RATE peak learning rate (default: 0.0005) +SEED random seed controlling model weights and data shuffling (default: disabled) +FP16 enables mixed-precision training with float16 (default: false) +BF16 enabled mixed-precision training with bfloat16 (default: false) +DATASET_DIR directory with file lists (default: /datasets/LibriSpeech) +TRAIN_SUBSET base name of the .tsv file list in the DATASET_DIR (default: "train-full-960") +VALID_SUBSET base name of the validation .tsv file list in the DATASET_DIR (default: "dev-other") +SAVE_FREQUENCY frequency of saving checkpoints to disk (default: 1) +HOURGLASS_CONFIG configuration of Hourglass Transformer; refer to the section + below for details (default: "[2,(8,4),2]") +``` + +In addition, important parameters for `scripts/finetune_base_960h.sh` script are: +```bash +PRETRAINED_MODEL a path to a pre-trained model checkpoint for fine-tuning + (default: "./results/pretrain_base/wav2vec2_update400000.pt") +FREEZE_FINETUNE_UPDATES freeze wav2vec 2.0 encoder for an initial number of steps and train only + the output linear projection (default: 0) +``` + +Below we present more details on how to set crucial parameters. + +#### Adjusting batch size and the number of GPUs + +Every training recipe assumes a constant world size, and variables need to be adjusted to maintain that world size, +for example, `NUM_GPUS x NUM_CONCAT_BATCHES x UPDATE_FREQUENCY = 64` for pre-training of the `Base` model: +* first, set `NUM_GPUS` to the number of available GPUs, +* then, adjust `NUM_CONCAT_BATCHES` to a high value that does not cause out-of-memory errors +* finally, adjust the update frequency that controls gradient accumulation, to maintain the effective world size. + +`NUM_CONCAT_BATCHES` controls the number of sub-batches that are forwarded through the model, each with `--max_tokens` tokens. +In the case of out-of-memory errors, it has to be lowered. With Hourglass Transformer and mixed-precision training, +the model should fit within 12GB of GPU memory on the lowest `NUM_CONCAT_BATCHES=1` setting. + +#### Adjusting mixed precision + +By default, the model is trained in TF32 (A100 GPUs) or FP32 (V100 and older GPUs). +Mixed-precision training can be performed in float16 or bfloat16 precisions. +Training in bfloat16 is more stable and requires less stabilizing casts to FP32; thus, it is a bit faster. +It is supported on the hardware level in NVIDIA Ampere and newer architectures. +Scripts `scripts/pretrain_base.sh` and `scripts/finetune_base_960h.sh` provide env vars +for setting appropriate casting flags. +In order to benefit from mixed-precision training, +set either `BF16=true` or `FP16=true`, depending on the architecture of the GPU. + +#### Adjusting Hourglass Transformer + +The Hourglass Transformer architecture is configurable by four parameters: +* the number of initial transformer layers, +* the number of middle transformer layers that process the downsampled signal, +* downsampling rate, +* the number of output transformer layers. + +These are expressed in that exact order by a Python list without whitespace. For instance, the default setting is `HOURGLASS_CONFIG="[2,(8,4),2]"`. +It uses 12 layers in total (two initial, eight middle with a downsampling rate 4, and two output layers). + +During fine-tuning, the same architecture as during pre-training has to be set. + +### Command-line options + +To view the full list of available options and their descriptions, use the `-h` or `--help` command-line option, for example: +`python train.py -h`. Most of the command-line options are a subset of those from the original [Fairseq](https://github.com/facebookresearch/fairseq) wav2vec 2.0 codebase. + +### Getting the data + +The wav2vec 2.0 model described in the paper was pre-trained on either the LibriSpeech or LibriVox datasets. +We publish recipes for training on pre-training and fine-tuning on the LibriSpeech dataset. +The `dev-other` subset is used as a validation dataset, and `test-other` is used as a testing dataset. + +The `./scripts/download_ls_dataset.sh [TARGET_DATA_DIR]` script downloads and extracts the LibriSpeech dataset to the directory of choice, +by default `/datasets/LibriSpeech` if the argument is omitted. + +The `./scripts/generate_ls_filelists.sh [SOURCE_DATA_DIR] [TARGET_FILELISTS_DIR]` script prepares filelists and collect transcriptions. +Again, positional arguments are optional and default to `/datasets/LibriSpeech`. + +#### Dataset guidelines + +LibriSpeech data is kept at the default sampling rate of 16 kHz. +The model works with either `.wav` or `.flac` files. Both are lossless, with `.flac` being more efficient in terms of storage but requiring extra computation during training. +Files are listed in `.tsv` filelists. The first row is the top-level directory, and subsequent lines listths to files and a number of samples delimited by `tab`: +```bash +/datasets/LibriSpeech/test-other +367/293981/367-293981-0017.flac\t46560 +367/293981/367-293981-0009.flac\t52720 +... +``` + +The `.ltr` files, generated alongside `.tsv` filelists, hold character-level transcriptions for filelists with the same basename. +Filelists and transcription lists should list samples in matching order. +```bash +A N D | A | V E R Y | R E S P E C T A B L E | O N E | S A I D | T H E | I N N K E E P E R | +T H E | O F F I C E R | T U R N E D | T O | H I M | A N D | S A I D | W E L L | H O W | G O E S | I T | G O O D | M A N | +... +``` + +Finally, generate a `dict.ltr.txt` dictionary using training `.ltr` transcripts: +```bash +python utils/generate_dictionary.py /my/dataset/path/train.ltr /my/dataset/path/dict.ltr.txt +``` + +#### Multi-dataset + +In order to train on multiple datasets, prepare a filelist and transcription list with all files from those datasets. +Refer to `scripts/generate_filelists.sh` for an example of concatenating LibriSpeech training filelists. + +### Training process + +Training of wav2vec 2.0 is performed in two stages: unsupervised pre-training and supervised fine-tuning. Both are performed with the `train.py` script. + +**Pre-training** +The `scripts/pretrain_base.sh` script sets command-line arguments for `train.py` +and runs a job on a single node that trains the wav2vec 2.0 model from scratch. +Key variables can be conveniently changed via env variables. + +**Fine-tuning** +The `scripts/finetune_base_960h.sh` script sets command-line arguments for `train.py` +and runs a job on a single node that fine-tunes a pre-trained wav2vec 2.0 model. +Key variables can be conveniently changed via env variables. +Note that a checkpoint trained with Fairseq can be loaded and fine-tuned +using this repository. + +Apart from the arguments as listed in the [Parameters](#parameters) section, by default both training scripts: +* Run on eight GPUs with at least 80GB of memory with increased batch size, so that gradient accumulation is not necessary +* Use TF32 precision (A100 GPU) or FP32 (other GPUs) +* Use Hourglass Transformer architecture with shortening factor of 4 +* Train on 960 hours of LibriSpeech training data and evaluate on the dev-other subset +* Remove old checkpoints and preserve milestone checkpoints automatically +* Maintain a separate checkpoint with the lowest WER on the dev set +* Create a DLLogger log file and a TensorBoard log +* Set the remaining parameters according to the recipes published with the original paper + +The current training setup recreates WER [Results](#results) published in the original paper, +while significantly lowering the time and memory required for training. + +### Inference process + +Inference is performed using the `inference.py` script along with parameters defined in `scripts/inference.sh`. +The `scripts/inference.sh` script runs the job on a single GPU, taking a fine-tuned wav2vec 2.0 model checkpoint +and running it on the specified dataset. +Apart from the default arguments as listed in the [Parameters](#parameters) section, by default, the inference script: +* Evaluates on the LibriSpeech test-other dataset and prints out the final word error rate +* Uses a batch size of 8 +* Creates a log file with progress and results, which will be stored in the `results` folder +* Does greedy decoding and optionally saves the transcriptions in the results folder +* Has the option to save the model output tensors for more complex decoding, for example, beam search + +To view all available options for inference, run `python inference.py --help` + +## Performance +The performance measurements in this document were conducted at the time of publication and may not reflect the performance +achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, +go to [NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). + +### Benchmarking + +The following section shows how to run benchmarks measuring the model performance in training and inference modes. + +#### Training performance benchmark + +To benchmark the training performance with a number of specific configurations, run: +```bash +NUM_GPUS=[NUM] UPDATE_FREQ=[NUM] NUM_CONCAT_BATCHES=[NUM] NUM_EPOCHS=[NUM] NUM_WARUP_EPOCHS=[NUM] \ + BF16=[true|false] FP16=[true|false] bash scripts/pretrain_base_benchmark.sh + +NUM_GPUS=[NUM] UPDATE_FREQ=[NUM] NUM_CONCAT_BATCHES=[NUM] NUM_EPOCHS=[NUM] NUM_WARUP_EPOCHS=[NUM] \ + BF16=[true|false] FP16=[true|false] bash scripts/finetune_base_benchmark.sh +``` +for example: +```bash +NUM_GPUS=8 UPDATE_FREQ=1 NUM_CONCAT_BATCHES=8 BF16=true bash scripts/pretrain_base_benchmark.sh +NUM_GPUS=8 UPDATE_FREQ=1 NUM_CONCAT_BATCHES=1 BF16=true bash scripts/finetune_base_benchmark.sh +``` + +By default, these scripts run initially for `NUM_WARMUP_EPOCHS=2`, and collect performance results for another `NUM_EPOCHS=5` on the `train-clean-100` subset of LibriSpeech. + +#### Inference performance benchmark + +To benchmark the inference performance on a specific batch size, run: + +```bash +NUM_WARMUP_REPEATS=[NUM] NUM_REPEATS=[NUM] BATCH_SIZE=[NUM] BF16=[true|false] FP16=[true|false] \ + bash scripts/inference_benchmark.sh +``` +for example: +```bash +NUM_WARMUP_REPEATS=2 NUM_REPEATS=10 BATCH_SIZE=8 BF16=true bash scripts/inference_benchmark.sh +``` +By default, the model will process all samples in the `test-other` subset of LibriSpeech initially `NUM_WARMUP_REPEATS` times for warmup, +and then `NUM_REPEATS` times recording the measurements. The number of iterations will depend on the batch size. + +### Results + +The following sections provide details on how we achieved our performance and accuracy in training and inference. + +#### Training accuracy results + +##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) + +Pre-training results were obtained by running the `scripts/pretrain_base.sh` training script in the PyTorch 22.11-py3 NGC container on NVIDIA A100 (8x A100 80GB) GPUs. +We report a median of eight (BF16 mixed precision) and three (TF32) runs. + +| GPUs | (Concatenated) batch size / GPU | Accuracy - TF32 | Accuracy - mixed precision | Time to train - TF32 | Time to train - mixed precision | Time to train speedup (TF32 to mixed precision) | +|--------:|--------------------------------:|-----------------:|----------------------------:|----------------------:|---------------------------------:|------------------------------------------------:| +| 8 | 8 x 1400k max tokens | 0.619 | 0.633 | 64.9 h | 48.1 h | 1.35 | + +

+ Accuracy during pre-training +

+ +Fine-tuning results were obtained by running the `scripts/finetune_base_960h.sh` training script in the PyTorch 22.11-py3 NGC container on NVIDIA A100 (8x A100 80GB) GPUs. +We report a median of eight runs; each resumed from a different pre-training checkpoint. + +| GPUs | (Concatenated) batch size / GPU | WER - mixed precision | Time to train - TF32 | Time to train - mid precision | Time to train speedup (TF32 to mixed precision) | +|--------:|--------------------------------:|-----------------------:|----------------------:|---------------------------------:|------------------------------------------------:| +| 8 | 1 x 3200k max tokens | 8.878 | 8.2 h | 6.5 h | 1.27 | + +

+ Word error rate during fine-tuning +

+ +##### Training stability test + +The wav2vec 2.0 Base model was pre-trained with eight different initial random seeds in bfloat16 precision in the PyTorch 22.11-py3 NGC container on NVIDIA DGX A100 with 8x A100 80GB. + +Below we present accuracy of this model in the self-training task: + +| Update | Average | Std | Min | Max | Median | +|---------:|----------:|------:|------:|------:|---------:| +| 50k | 0.491 | 0.011 | 0.471 | 0.514 | 0.493 | +| 100k | 0.537 | 0.009 | 0.518 | 0.550 | 0.539 | +| 150k | 0.564 | 0.009 | 0.544 | 0.577 | 0.564 | +| 200k | 0.580 | 0.009 | 0.558 | 0.589 | 0.583 | +| 250k | 0.599 | 0.008 | 0.586 | 0.607 | 0.602 | +| 300k | 0.610 | 0.010 | 0.589 | 0.622 | 0.611 | +| 350k | 0.619 | 0.009 | 0.607 | 0.634 | 0.617 | +| 400k | 0.629 | 0.007 | 0.614 | 0.636 | 0.633 | + +Afterward, each of those runs was fine-tuned on LibriSpeech 960 h dataset with yet another different initial random seed. +Below we present the word error rate (WER) on the `dev-other` subset of LibriSpeech: + +| Update | Average | Std | Min | Max | Median | +|---------:|----------:|------:|-------:|-------:|---------:| +| 50k | 11.198 | 0.303 | 10.564 | 11.628 | 11.234 | +| 100k | 10.825 | 0.214 | 10.574 | 11.211 | 10.763 | +| 150k | 10.507 | 0.160 | 10.224 | 10.778 | 10.518 | +| 200k | 9.567 | 0.186 | 9.235 | 9.836 | 9.530 | +| 250k | 9.115 | 0.193 | 8.764 | 9.339 | 9.194 | +| 300k | 8.885 | 0.201 | 8.507 | 9.151 | 8.972 | +| 320k | 8.827 | 0.188 | 8.440 | 9.043 | 8.878 | + +#### Training performance results + +##### Training performance: NVIDIA DGX A100 (8x A100 80GB) + +**Pre-training** + +Our results were obtained by running the `scripts/pretrain_base_benchmark.sh` training script in the PyTorch 22.11-py3 NGC container on NVIDIA A100 (8x A100 80GB) GPUs. Performance numbers in transformer tokens per second were averaged over an entire training epoch. + +| GPUs | Concat batches / GPU | Grad accumulation | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 to mixed precision) | Strong scaling - TF32 | Strong scaling - mixed precision | +|-------:|-----------------------:|--------------------:|--------------------:|-------------------------------:|-----------------------------------------------:|------------------------:|-----------------------------------:| +| 1 | 8 | 8 | 28045.27 | 37609.84 | 1.34 | 1.00 | 1.00 | +| 4 | 8 | 2 | 103842.47 | 138956.38 | 1.34 | 3.70 | 3.69 | +| 8 | 8 | 1 | 194306.46 | 261881.29 | 1.35 | 6.93 | 6.96 | + +To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +**Fine-tuning** + +Our results were obtained by running the `scripts/finetune_base_benchmark.sh` training script in the PyTorch 22.11-py3 NGC container on NVIDIA A100 (8x A100 80GB) GPUs. Performance numbers in transformer tokens per second were averaged over an entire training epoch. + +| GPUs | Concat batches / GPU | Grad accumulation | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 to mixed precision) | Strong scaling - TF32 | Strong scaling - mixed precision | +|-------:|-------------------:|--------------------:|--------------------:|-------------------------------:|-----------------------------------------------:|------------------------:|-----------------------------------:| +| 1 | 8 | 1 | 34813.46 | 41275.76 | 1.19 | 1.00 | 1.00 | +| 4 | 2 | 1 | 102326.57 | 132361.62 | 1.29 | 2.94 | 3.21 | +| 8 | 1 | 1 | 163610.16 | 207200.91 | 1.27 | 4.70 | 5.02 | + +To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +#### Inference performance results + +##### Inference performance: NVIDIA DGX A100 (1x A100 80GB) + +Our results were obtained by running the `scripts/inference_benchmark.sh` inferencing benchmarking script in the PyTorch 22.11-py3 NGC container on the NVIDIA A100 (1x A100 80GB) GPU. +The script runs inference on the `test-other` subset of LibriSpeech in variable-length batches. + +| | Duration | BF16 Latency (ms) Percentiles | | | | TF32 Latency (ms) Percentiles | | | | BF16/TF32 speedup | +|-----:|-------:|------:|-------:|-------:|------:|-------:|-------:|-------:|------:|------:| +| BS | Avg | 90% | 95% | 99% | Avg | 90% | 95% | 99% | Avg | Avg | +| 1 | 6.54 s | 11.02 | 11.41 | 12.42 | 10.45 | 10.88 | 11.23 | 12.51 | 10.31 | 0.99 | +| 4 | 6.54 s | 21.74 | 24.12 | 35.80 | 17.69 | 23.17 | 26.85 | 41.62 | 18.42 | 1.04 | +| 8 | 6.54 s | 40.06 | 48.07 | 74.59 | 28.70 | 46.43 | 54.86 | 88.73 | 31.30 | 1.09 | +| 16 | 6.54 s | 88.78 | 117.40 | 151.37 | 58.82 | 102.64 | 135.92 | 175.68 | 67.44 | 1.15 | + +To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +## Release notes + +### Changelog + +December 2022 +- Initial release + +### Known issues + +There are no known issues in this release. diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/__init__.py b/PyTorch/SpeechRecognition/wav2vec2/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/dataset.py b/PyTorch/SpeechRecognition/wav2vec2/common/dataset.py new file mode 100644 index 000000000..a7cf02a8c --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/dataset.py @@ -0,0 +1,156 @@ +# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import numpy as np +from torch.utils.data import DataLoader + +from common.fairseq.data import data_utils +from common.helpers import print_once +from common.sampler import DistributedIndicesSampler + + +def adjust_max_tokens(train_dataset, world_size, args): + + def get_steps_per_epoch(world_size, max_tokens, update_freq): + train_loader, sampler = get_batch_iterator( + train_dataset, + True, + max_tokens=max_tokens, + max_sentences=args.batch_size, + max_positions=(max_tokens, max_tokens), + ignore_invalid_inputs=True, + required_batch_size_multiple=args.required_batch_size_multiple, + seed=args.seed, + num_shards=world_size, + shard_id=0, + num_workers=args.num_workers) + + steps_per_epoch = len(train_loader) // update_freq + return steps_per_epoch + + steps_ref = get_steps_per_epoch(args.ref_world_size, args.ref_max_tokens, 1) + + min_ = args.ref_max_tokens // 20 + max_ = args.ref_max_tokens * 20 + + prev_max_tokens = 0 + align_to = 1000 + while min_ < max_: + max_tokens = (max_ + min_) // 2 // align_to * align_to # try to round + if max_tokens == prev_max_tokens: + break + prev_max_tokens = max_tokens + steps = get_steps_per_epoch(world_size, max_tokens, args.update_freq) + print_once(f"max_tokens={max_tokens} yields {steps} steps " + f"(adjusting for {steps_ref}).") + if steps == steps_ref: + break + elif steps > steps_ref: + min_ = max_tokens + else: + max_ = max_tokens + + args.max_tokens = max_tokens + args.max_tokens_valid = max_tokens + + +def filter_indices_by_size( + indices, dataset, max_positions=None, ignore_invalid_inputs=False +): + """ + Filter examples that are too large + + Args: + indices (np.array): original array of sample indices + dataset (~fairseq.data.FairseqDataset): dataset to batch + max_positions (optional): max sentence length supported by the + model (default: None). + ignore_invalid_inputs (bool, optional): don't raise Exception for + sentences that are too long (default: False). + Returns: + np.array: array of filtered sample indices + """ + indices, ignored = dataset.filter_indices_by_size(indices, max_positions) + # TODO: consider removing this function. If `len(ignored) > 0`, + # an error is raised in fairseq dataset code, both in sup and unsup case + if len(ignored) > 0: + if not ignore_invalid_inputs: + raise Exception( + ( + "Size of sample #{} is invalid (={}) since max_positions={}, " + "skip this example with --skip-invalid-size-inputs-valid-test" + ).format(ignored[0], dataset.size(ignored[0]), max_positions) + ) + print( + ( + "WARNING: {:,} samples have invalid sizes and will be skipped, " + "max_positions={}, first few sample ids={}" + ).format(len(ignored), max_positions, ignored[:10]) + ) + return indices + + +def get_batch_iterator( + dataset, + training, + max_tokens=None, + max_sentences=None, + max_positions=None, + ignore_invalid_inputs=False, + required_batch_size_multiple=1, + seed=1, + num_shards=1, + shard_id=0, + num_workers=0, + num_concat_batches=1, +): + # get indices ordered by example size + with data_utils.numpy_seed(seed): + indices = dataset.ordered_indices() + + # filter examples that are too large + if max_positions is not None: + indices = filter_indices_by_size( + indices, dataset, max_positions, ignore_invalid_inputs) + + # create mini-batches with given size constraints + batch_inds, non_grouped_batch_inds = dataset.batch_by_size( + indices, + max_tokens=max_tokens, + max_sentences=max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + num_concat_batches=num_concat_batches, + ) + + batch_ids = copy.deepcopy(non_grouped_batch_inds) + [bi.fill(i) for i, bi in enumerate(batch_ids)] + inds_ids = zip(np.concatenate(batch_inds), np.concatenate(batch_ids)) + dataset.batch_ids = {idx: batch_idx for idx, batch_idx in inds_ids} + + # Batches are already specified, now we just need to shuffle them + batch_ind_sampler = DistributedIndicesSampler(batch_inds, shuffle=training, + num_replicas=num_shards, + rank=shard_id, seed=seed, + drop_last=training, + fillvalue=[]) + loader = DataLoader( + dataset=dataset, + collate_fn=dataset.collater, + batch_sampler=batch_ind_sampler, + num_workers=num_workers, + pin_memory=True, + persistent_workers=num_workers > 0, + ) + return loader, batch_ind_sampler diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/__init__.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/__init__.py new file mode 100644 index 000000000..9c99d604f --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/__init__.py @@ -0,0 +1,30 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""isort:skip_file""" + +from .add_target_dataset import AddTargetDataset, BaseWrapperDataset +from .audio.raw_audio_dataset import FileAudioDataset +from .dictionary import Dictionary + + +__all__ = [ + "AddTargetDataset", + "Dictionary", + "FileAudioDataset", +] diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/add_target_dataset.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/add_target_dataset.py new file mode 100644 index 000000000..6c8e3b050 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/add_target_dataset.py @@ -0,0 +1,134 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch + +from . import data_utils + + +class BaseWrapperDataset(torch.utils.data.Dataset): + def __init__(self, dataset): + super().__init__() + self.dataset = dataset + + def __getitem__(self, index): + return self.dataset[index] + + def __len__(self): + return len(self.dataset) + + @property + def sizes(self): + return self.dataset.sizes + + def num_tokens(self, index): + return self.dataset.num_tokens(index) + + def size(self, index): + return self.dataset.size(index) + + def ordered_indices(self): + return self.dataset.ordered_indices() + + def batch_by_size( + self, + indices, + max_tokens=None, + max_sentences=None, + required_batch_size_multiple=1, + num_concat_batches=1, + ): + return self.dataset.batch_by_size( + indices, + max_tokens=max_tokens, + max_sentences=max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + num_concat_batches=num_concat_batches, + ) + + def filter_indices_by_size(self, indices, max_sizes): + return self.dataset.filter_indices_by_size(indices, max_sizes) + + +class AddTargetDataset(BaseWrapperDataset): + def __init__( + self, + dataset, + labels, + pad, + eos, + batch_targets, + process_label=None, + add_to_input=False, + ): + super().__init__(dataset) + self.labels = labels + self.batch_targets = batch_targets + self.pad = pad + self.eos = eos + self.process_label = process_label + self.add_to_input = add_to_input + + def get_label(self, index): + return ( + self.labels[index] + if self.process_label is None + else self.process_label(self.labels[index]) + ) + + def __getitem__(self, index): + item = self.dataset[index] + item["label"] = self.get_label(index) + return item + + def size(self, index): + sz = self.dataset.size(index) + own_sz = len(self.get_label(index)) + return (sz, own_sz) + + def collater(self, samples): + collated = self.dataset.collater(samples) + if len(collated) == 0: + return collated + indices = set(collated["id"].tolist()) + target = [s["label"] for s in samples if s["id"] in indices] + + if self.batch_targets: + collated["target_lengths"] = torch.LongTensor([len(t) for t in target]) + target = data_utils.collate_tokens(target, pad_idx=self.pad, left_pad=False) + collated["ntokens"] = collated["target_lengths"].sum().item() + else: + collated["ntokens"] = sum([len(t) for t in target]) + + collated["target"] = target + + if self.add_to_input: + eos = target.new_full((target.size(0), 1), self.eos) + collated["target"] = torch.cat([target, eos], dim=-1).long() + collated["net_input"]["prev_output_tokens"] = torch.cat( + [eos, target], dim=-1 + ).long() + collated["ntokens"] += target.size(0) + return collated + + def __setattr__(self, attr, val): + if attr == "batch_ids": + self.dataset.batch_ids = val + else: + super().__setattr__(attr, val) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/audio/audio_utils.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/audio/audio_utils.py new file mode 100644 index 000000000..561ff8e20 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/audio/audio_utils.py @@ -0,0 +1,193 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import Path +from typing import BinaryIO, Optional, Tuple, Union, List + +import numpy as np +import torch + + +SF_AUDIO_FILE_EXTENSIONS = {".wav", ".flac", ".ogg"} +FEATURE_OR_SF_AUDIO_FILE_EXTENSIONS = {".npy", ".wav", ".flac", ".ogg"} + + +def _convert_to_mono( + waveform: torch.FloatTensor, sample_rate: int +) -> torch.FloatTensor: + if waveform.shape[0] > 1: + try: + import torchaudio.sox_effects as ta_sox + except ImportError: + raise ImportError( + "Please install torchaudio to convert multi-channel audios" + ) + effects = [['channels', '1']] + return ta_sox.apply_effects_tensor(waveform, sample_rate, effects)[0] + return waveform + + +def convert_to_mono(waveform: np.ndarray, sample_rate: int) -> np.ndarray: + if waveform.shape[0] > 1: + _waveform = torch.from_numpy(waveform) + return _convert_to_mono(_waveform, sample_rate).numpy() + return waveform + + +def get_waveform( + path_or_fp: Union[str, BinaryIO], normalization=True, mono=True, + frames=-1, start=0, always_2d=True +) -> Tuple[np.ndarray, int]: + """Get the waveform and sample rate of a 16-bit WAV/FLAC/OGG Vorbis audio. + + Args: + path_or_fp (str or BinaryIO): the path or file-like object + normalization (bool): Normalize values to [-1, 1] (Default: True) + mono (bool): convert multi-channel audio to mono-channel one + frames (int): the number of frames to read. (-1 for reading all) + start (int): Where to start reading. A negative value counts from the end. + always_2d (bool): always return 2D array even for mono-channel audios + Returns: + waveform (numpy.ndarray): 1D or 2D waveform (channels x length) + sample_rate (float): sample rate + """ + if isinstance(path_or_fp, str): + ext = Path(path_or_fp).suffix + if ext not in SF_AUDIO_FILE_EXTENSIONS: + raise ValueError(f"Unsupported audio format: {ext}") + + try: + import soundfile as sf + except ImportError: + raise ImportError( + "Please install soundfile to load WAV/FLAC/OGG Vorbis audios" + ) + + waveform, sample_rate = sf.read( + path_or_fp, dtype="float32", always_2d=True, frames=frames, start=start + ) + waveform = waveform.T # T x C -> C x T + if mono and waveform.shape[0] > 1: + waveform = convert_to_mono(waveform, sample_rate) + if not normalization: + waveform *= 2 ** 15 # denormalized to 16-bit signed integers + if not always_2d: + waveform = waveform.squeeze(axis=0) + return waveform, sample_rate + + +def _get_kaldi_fbank( + waveform: np.ndarray, sample_rate: int, n_bins=80 +) -> Optional[np.ndarray]: + """Get mel-filter bank features via PyKaldi.""" + try: + from kaldi.feat.mel import MelBanksOptions + from kaldi.feat.fbank import FbankOptions, Fbank + from kaldi.feat.window import FrameExtractionOptions + from kaldi.matrix import Vector + + mel_opts = MelBanksOptions() + mel_opts.num_bins = n_bins + frame_opts = FrameExtractionOptions() + frame_opts.samp_freq = sample_rate + opts = FbankOptions() + opts.mel_opts = mel_opts + opts.frame_opts = frame_opts + fbank = Fbank(opts=opts) + features = fbank.compute(Vector(waveform.squeeze()), 1.0).numpy() + return features + except ImportError: + return None + + +def _get_torchaudio_fbank( + waveform: np.ndarray, sample_rate, n_bins=80 +) -> Optional[np.ndarray]: + """Get mel-filter bank features via TorchAudio.""" + try: + import torchaudio.compliance.kaldi as ta_kaldi + waveform = torch.from_numpy(waveform) + features = ta_kaldi.fbank( + waveform, num_mel_bins=n_bins, sample_frequency=sample_rate + ) + return features.numpy() + except ImportError: + return None + + +def get_fbank(path_or_fp: Union[str, BinaryIO], n_bins=80) -> np.ndarray: + """Get mel-filter bank features via PyKaldi or TorchAudio. Prefer PyKaldi + (faster CPP implementation) to TorchAudio (Python implementation). Note that + Kaldi/TorchAudio requires 16-bit signed integers as inputs and hence the + waveform should not be normalized.""" + waveform, sample_rate = get_waveform(path_or_fp, normalization=False) + + features = _get_kaldi_fbank(waveform, sample_rate, n_bins) + if features is None: + features = _get_torchaudio_fbank(waveform, sample_rate, n_bins) + if features is None: + raise ImportError( + "Please install pyKaldi or torchaudio to enable " + "online filterbank feature extraction" + ) + + return features + + +def is_npy_data(data: bytes) -> bool: + return data[0] == 147 and data[1] == 78 + + +def is_sf_audio_data(data: bytes) -> bool: + is_wav = (data[0] == 82 and data[1] == 73 and data[2] == 70) + is_flac = (data[0] == 102 and data[1] == 76 and data[2] == 97) + is_ogg = (data[0] == 79 and data[1] == 103 and data[2] == 103) + return is_wav or is_flac or is_ogg + + +def read_from_stored_zip(zip_path: str, offset: int, file_size: int) -> bytes: + with open(zip_path, "rb") as f: + f.seek(offset) + data = f.read(file_size) + return data + + +def parse_path(path: str) -> Tuple[str, List[int]]: + """Parse data path which is either a path to + 1. a .npy/.wav/.flac/.ogg file + 2. a stored ZIP file with slicing info: "[zip_path]:[offset]:[length]" + + Args: + path (str): the data path to parse + + Returns: + file_path (str): the file path + slice_ptr (list of int): empty in case 1; + byte offset and length for the slice in case 2 + """ + + if Path(path).suffix in FEATURE_OR_SF_AUDIO_FILE_EXTENSIONS: + _path, slice_ptr = path, [] + else: + _path, *slice_ptr = path.split(":") + if not Path(_path).is_file(): + raise FileNotFoundError(f"File not found: {_path}") + assert len(slice_ptr) in {0, 2}, f"Invalid path: {path}" + slice_ptr = [int(i) for i in slice_ptr] + return _path, slice_ptr diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/audio/raw_audio_dataset.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/audio/raw_audio_dataset.py new file mode 100644 index 000000000..0a8d19bde --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/audio/raw_audio_dataset.py @@ -0,0 +1,425 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import io +import logging +import os +import sys +from itertools import groupby + +import numpy as np +import torch +import torch.nn.functional as F +import torch.utils + +from common.fairseq.data import data_utils +from common.fairseq.data.audio.audio_utils import ( + parse_path, + read_from_stored_zip, + is_sf_audio_data, +) +from common.fairseq.data.data_utils import ( + compute_mask_indices, + get_bucketed_sizes, + get_buckets, +) +from common.utils import print_once + + +logger = logging.getLogger(__name__) + + +class RawAudioDataset(torch.utils.data.Dataset): + + def __init__( + self, + sample_rate, + max_sample_size=None, + min_sample_size=0, + shuffle=True, + pad=False, + normalize=False, + compute_mask_indices=False, + **mask_compute_kwargs, + ): + super().__init__() + + self.sample_rate = sample_rate + self.sizes = [] + self.max_sample_size = ( + max_sample_size if max_sample_size is not None else sys.maxsize + ) + self.min_sample_size = min_sample_size + self.pad = pad + self.shuffle = shuffle + self.normalize = normalize + self.compute_mask_indices = compute_mask_indices + if self.compute_mask_indices: + self.mask_compute_kwargs = mask_compute_kwargs + self._features_size_map = {} + self._C = mask_compute_kwargs["encoder_embed_dim"] + self._conv_feature_layers = eval(mask_compute_kwargs["conv_feature_layers"]) + + def __getitem__(self, index): + raise NotImplementedError() + + def __len__(self): + return len(self.sizes) + + def postprocess(self, feats, curr_sample_rate): + if feats.dim() == 2: + feats = feats.mean(-1) + + if curr_sample_rate != self.sample_rate: + raise Exception(f"sample rate: {curr_sample_rate}, need {self.sample_rate}") + + assert feats.dim() == 1, feats.dim() + + if self.normalize: + with torch.no_grad(): + feats = F.layer_norm(feats, feats.shape) + return feats + + def crop_to_max_size(self, wav, target_size): + size = len(wav) + diff = size - target_size + if diff <= 0: + return wav + + start = np.random.randint(0, diff + 1) + end = size - diff + start + return wav[start:end] + + def _compute_mask_indices(self, dims, padding_mask): + B, T, C = dims + mask_indices, mask_channel_indices = None, None + if self.mask_compute_kwargs["mask_prob"] > 0: + mask_indices = compute_mask_indices( + (B, T), + padding_mask, + self.mask_compute_kwargs["mask_prob"], + self.mask_compute_kwargs["mask_length"], + self.mask_compute_kwargs["mask_selection"], + self.mask_compute_kwargs["mask_other"], + min_masks=2, + no_overlap=self.mask_compute_kwargs["no_mask_overlap"], + min_space=self.mask_compute_kwargs["mask_min_space"], + ) + mask_indices = torch.from_numpy(mask_indices) + if self.mask_compute_kwargs["mask_channel_prob"] > 0: + mask_channel_indices = compute_mask_indices( + (B, C), + None, + self.mask_compute_kwargs["mask_channel_prob"], + self.mask_compute_kwargs["mask_channel_length"], + self.mask_compute_kwargs["mask_channel_selection"], + self.mask_compute_kwargs["mask_channel_other"], + no_overlap=self.mask_compute_kwargs["no_mask_channel_overlap"], + min_space=self.mask_compute_kwargs["mask_channel_min_space"], + ) + mask_channel_indices = ( + torch.from_numpy(mask_channel_indices).unsqueeze(1).expand(-1, T, -1) + ) + + return mask_indices, mask_channel_indices + + @staticmethod + def _bucket_tensor(tensor, num_pad, value): + return F.pad(tensor, (0, num_pad), value=value) + + def collater(self, samples): + samples = [s for s in samples if s["source"] is not None] + if len(samples) == 0: + return {} + + sources = [s["source"] for s in samples] + sizes = [len(s) for s in sources] + + if self.pad: + target_size = min(max(sizes), self.max_sample_size) + else: + target_size = min(min(sizes), self.max_sample_size) + + input, out = {}, {} + if "batch_id" in samples[0]: + # The data for wav2vec 2.0 is sorted by len and cut into batches. + # We concat --num_concat_batches together to better utilize GPUs. + # Yet, we split them back to calculate masking, sample negatives, + # and calculate loss, as these ops are dependent on batch size. + # In order to split, we need to remember original (sub)batch ids. + batch_inds = [s['batch_id'] for s in samples] + sub_batch_lens = [len(list(b)) for _, b in groupby(batch_inds)] + starts_ends = np.cumsum([0] + sub_batch_lens) + target_sizes = np.array( + [min(max(sizes[s:e]), self.max_sample_size) + for s, e in zip(starts_ends[:-1], starts_ends[1:])] + ) + out["sub_batch_sizes"] = torch.LongTensor(sub_batch_lens) + out["sub_batch_lens"] = torch.LongTensor(target_sizes) + + collated_sources = sources[0].new_zeros(len(sources), target_size) + padding_mask = ( + torch.BoolTensor(collated_sources.shape).fill_(False) if self.pad else None + ) + for i, (source, size) in enumerate(zip(sources, sizes)): + diff = size - target_size + if diff == 0: + collated_sources[i] = source + elif diff > 0: + collated_sources[i] = self.crop_to_max_size(source, target_size) + else: # diff < 0: + assert self.pad + collated_sources[i] = torch.cat( + [source, source.new_full((-diff,), 0.0)] + ) + padding_mask[i, diff:] = True + + input["source"] = collated_sources + out["id"] = torch.LongTensor([s["id"] for s in samples]) + if self.pad: + input["padding_mask"] = padding_mask + + if hasattr(self, "num_buckets") and self.num_buckets > 0: + assert self.pad, "Cannot bucket without padding first." + bucket = max(self._bucketed_sizes[s["id"]] for s in samples) + num_pad = bucket - collated_sources.size(-1) + if num_pad: + input["source"] = self._bucket_tensor(collated_sources, num_pad, 0) + input["padding_mask"] = self._bucket_tensor(padding_mask, num_pad, True) + + if self.compute_mask_indices: + B = input["source"].size(0) + T = self._get_mask_indices_dims(input["source"].size(-1)) + padding_mask_reshaped = input["padding_mask"].clone() + extra = padding_mask_reshaped.size(1) % T + if extra > 0: + padding_mask_reshaped = padding_mask_reshaped[:, :-extra] + padding_mask_reshaped = padding_mask_reshaped.view( + padding_mask_reshaped.size(0), T, -1 + ) + padding_mask_reshaped = padding_mask_reshaped.all(-1) + input["padding_count"] = padding_mask_reshaped.sum(-1).max().item() + mask_indices, mask_channel_indices = self._compute_mask_indices( + (B, T, self._C), + padding_mask_reshaped, + ) + input["mask_indices"] = mask_indices + input["mask_channel_indices"] = mask_channel_indices + out["sample_size"] = mask_indices.sum().item() + + out["net_input"] = input + return out + + def _get_mask_indices_dims(self, size, padding=0, dilation=1): + if size not in self._features_size_map: + L_in = size + for (_, kernel_size, stride) in self._conv_feature_layers: + L_out = L_in + 2 * padding - dilation * (kernel_size - 1) - 1 + L_out = 1 + L_out // stride + L_in = L_out + self._features_size_map[size] = L_out + return self._features_size_map[size] + + def num_tokens(self, index): + return self.size(index) + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + if self.pad: + return self.sizes[index] + return min(self.sizes[index], self.max_sample_size) + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + + if self.shuffle: + order = [np.random.permutation(len(self))] + order.append( + np.minimum( + np.array(self.sizes), + self.max_sample_size, + ) + ) + return np.lexsort(order)[::-1] + else: + return np.arange(len(self)) + + def set_bucket_info(self, num_buckets): + self.num_buckets = num_buckets + if self.num_buckets > 0: + self._collated_sizes = np.minimum( + np.array(self.sizes), + self.max_sample_size, + ) + self.buckets = get_buckets( + self._collated_sizes, + self.num_buckets, + ) + self._bucketed_sizes = get_bucketed_sizes( + self._collated_sizes, self.buckets + ) + logger.info( + f"{len(self.buckets)} bucket(s) for the audio dataset: " + f"{self.buckets}" + ) + + def batch_by_size( + self, + indices, + max_tokens=None, + max_sentences=None, + required_batch_size_multiple=1, + num_concat_batches=1, + ): + """ + Given an ordered set of indices, return batches according to + *max_tokens*, *max_sentences* and *required_batch_size_multiple*. + """ + from common.fairseq.data import data_utils + + return data_utils.batch_by_size( + indices, + num_tokens_fn=self.num_tokens, + num_tokens_vec=None, + max_tokens=max_tokens, + max_sentences=max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + num_concat_batches=num_concat_batches, + ) + + def filter_indices_by_size(self, indices, max_sizes): + """ + Filter a list of sample indices. Remove those that are longer than + specified in *max_sizes*. + + WARNING: don't update, override method in child classes + + Args: + indices (np.array): original array of sample indices + max_sizes (int or list[int] or tuple[int]): max sample size, + can be defined separately for src and tgt (then list or tuple) + + Returns: + np.array: filtered sample array + list: list of removed indices + """ + if isinstance(max_sizes, float) or isinstance(max_sizes, int): + if hasattr(self, "sizes") and isinstance(self.sizes, np.ndarray): + ignored = indices[self.sizes[indices] > max_sizes].tolist() + indices = indices[self.sizes[indices] <= max_sizes] + elif ( + hasattr(self, "sizes") + and isinstance(self.sizes, list) + and len(self.sizes) == 1 + ): + ignored = indices[self.sizes[0][indices] > max_sizes].tolist() + indices = indices[self.sizes[0][indices] <= max_sizes] + else: + indices, ignored = data_utils._filter_by_size_dynamic( + indices, self.size, max_sizes + ) + else: + indices, ignored = data_utils._filter_by_size_dynamic( + indices, self.size, max_sizes + ) + return indices, ignored + + +class FileAudioDataset(RawAudioDataset): + def __init__( + self, + manifest_path, + sample_rate, + max_sample_size=None, + min_sample_size=0, + shuffle=True, + pad=False, + normalize=False, + num_buckets=0, + compute_mask_indices=False, + **mask_compute_kwargs, + ): + super().__init__( + sample_rate=sample_rate, + max_sample_size=max_sample_size, + min_sample_size=min_sample_size, + shuffle=shuffle, + pad=pad, + normalize=normalize, + compute_mask_indices=compute_mask_indices, + **mask_compute_kwargs, + ) + + skipped = 0 + self.fnames = [] + sizes = [] + self.skipped_indices = set() + + with open(manifest_path, "r") as f: + self.root_dir = f.readline().strip() + for i, line in enumerate(f): + items = line.strip().split("\t") + assert len(items) == 2, line + sz = int(items[1]) + if min_sample_size is not None and sz < min_sample_size: + skipped += 1 + self.skipped_indices.add(i) + continue + self.fnames.append(items[0]) + sizes.append(sz) + print_once(f"loaded {len(self.fnames)}, skipped {skipped} samples") + + self.sizes = np.array(sizes, dtype=np.int64) + + try: + import pyarrow + self.fnames = pyarrow.array(self.fnames) + except: + logger.debug("Could not create a pyarrow array. " + "Please install pyarrow for better performance") + pass + + self.set_bucket_info(num_buckets) + + def __getitem__(self, index): + import soundfile as sf + + path_or_fp = os.path.join(self.root_dir, str(self.fnames[index])) + _path, slice_ptr = parse_path(path_or_fp) + if len(slice_ptr) == 2: + byte_data = read_from_stored_zip(_path, slice_ptr[0], slice_ptr[1]) + assert is_sf_audio_data(byte_data) + path_or_fp = io.BytesIO(byte_data) + + try: + wav, curr_sample_rate = sf.read(path_or_fp, dtype="float32") + except RuntimeError as e: + if not os.path.isfile(path_or_fp): + raise FileNotFoundError(path_or_fp) + else: + raise e + + feats = torch.from_numpy(wav).float() + feats = self.postprocess(feats, curr_sample_rate) + ret = {"id": index, "source": feats} + if hasattr(self, 'batch_ids'): + ret['batch_id'] = self.batch_ids[index] + return ret diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/data_utils.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/data_utils.py new file mode 100644 index 000000000..127f251b5 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/data_utils.py @@ -0,0 +1,568 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +try: + from collections.abc import Iterable +except ImportError: + from collections import Iterable +import contextlib +import itertools +import logging +import os +import re +import warnings +from typing import Optional, Tuple + +import numpy as np +import torch + +from common.fairseq import utils +from common.fairseq.data.data_utils_fast import batch_by_size_vec +from common.fairseq.file_io import PathManager + +logger = logging.getLogger(__name__) + + +def infer_language_pair(path): + """Infer language pair from filename: .-.(...).idx""" + src, dst = None, None + for filename in PathManager.ls(path): + parts = filename.split(".") + if len(parts) >= 3 and len(parts[1].split("-")) == 2: + return parts[1].split("-") + return src, dst + + +def collate_tokens( + values, + pad_idx, + eos_idx=None, + left_pad=False, + move_eos_to_beginning=False, + pad_to_length=None, + pad_to_multiple=1, + pad_to_bsz=None, +): + """Convert a list of 1d tensors into a padded 2d tensor.""" + size = max(v.size(0) for v in values) + size = size if pad_to_length is None else max(size, pad_to_length) + if pad_to_multiple != 1 and size % pad_to_multiple != 0: + size = int(((size - 0.1) // pad_to_multiple + 1) * pad_to_multiple) + + batch_size = len(values) if pad_to_bsz is None else max(len(values), pad_to_bsz) + res = values[0].new(batch_size, size).fill_(pad_idx) + + def copy_tensor(src, dst): + assert dst.numel() == src.numel() + if move_eos_to_beginning: + if eos_idx is None: + # if no eos_idx is specified, then use the last token in src + dst[0] = src[-1] + else: + dst[0] = eos_idx + dst[1:] = src[:-1] + else: + dst.copy_(src) + + for i, v in enumerate(values): + copy_tensor(v, res[i][size - len(v) :] if left_pad else res[i][: len(v)]) + return res + +def load_indexed_dataset( + path, dictionary=None, dataset_impl=None, combine=False, default="cached" +): + """A helper function for loading indexed datasets. + + Args: + path (str): path to indexed dataset (e.g., 'data-bin/train') + dictionary (~fairseq.data.Dictionary): data dictionary + dataset_impl (str, optional): which dataset implementation to use. If + not provided, it will be inferred automatically. For legacy indexed + data we use the 'cached' implementation by default. + combine (bool, optional): automatically load and combine multiple + datasets. For example, if *path* is 'data-bin/train', then we will + combine 'data-bin/train', 'data-bin/train1', ... and return a + single ConcatDataset instance. + """ + import fairseq.data.indexed_dataset as indexed_dataset + from fairseq.data.concat_dataset import ConcatDataset + + datasets = [] + for k in itertools.count(): + path_k = path + (str(k) if k > 0 else "") + try: + path_k = indexed_dataset.get_indexed_dataset_to_local(path_k) + except Exception as e: + if "StorageException: [404] Path not found" in str(e): + logger.warning(f"path_k: {e} not found") + else: + raise e + + dataset_impl_k = dataset_impl + if dataset_impl_k is None: + dataset_impl_k = indexed_dataset.infer_dataset_impl(path_k) + dataset = indexed_dataset.make_dataset( + path_k, + impl=dataset_impl_k or default, + fix_lua_indexing=True, + dictionary=dictionary, + ) + if dataset is None: + break + logger.info("loaded {:,} examples from: {}".format(len(dataset), path_k)) + datasets.append(dataset) + if not combine: + break + if len(datasets) == 0: + return None + elif len(datasets) == 1: + return datasets[0] + else: + return ConcatDataset(datasets) + + +@contextlib.contextmanager +def numpy_seed(seed, *addl_seeds): + """Context manager which seeds the NumPy PRNG with the specified seed and + restores the state afterward""" + if seed is None: + yield + return + if len(addl_seeds) > 0: + seed = int(hash((seed, *addl_seeds)) % 1e6) + state = np.random.get_state() + np.random.seed(seed) + try: + yield + finally: + np.random.set_state(state) + + +def collect_filtered(function, iterable, filtered): + """ + Similar to :func:`filter` but collects filtered elements in ``filtered``. + + Args: + function (callable): function that returns ``False`` for elements that + should be filtered + iterable (iterable): iterable to filter + filtered (list): list to store filtered elements + """ + for el in iterable: + if function(el): + yield el + else: + filtered.append(el) + + +def _filter_by_size_dynamic(indices, size_fn, max_positions, raise_exception=False): + + def check_size(idx): + if isinstance(max_positions, float) or isinstance(max_positions, int): + return size_fn(idx) <= max_positions + elif isinstance(max_positions, dict): + idx_size = size_fn(idx) + assert isinstance(idx_size, dict) + intersect_keys = set(max_positions.keys()) & set(idx_size.keys()) + return all( + all( + a is None or b is None or a <= b + for a, b in zip(idx_size[key], max_positions[key]) + ) + for key in intersect_keys + ) + else: + # For MultiCorpusSampledDataset, will generalize it later + if not isinstance(size_fn(idx), Iterable): + return all(size_fn(idx) <= b for b in max_positions) + return all( + a is None or b is None or a <= b + for a, b in zip(size_fn(idx), max_positions) + ) + + ignored = [] + itr = collect_filtered(check_size, indices, ignored) + indices = np.fromiter(itr, dtype=np.int64, count=-1) + return indices, ignored + + +def filter_by_size(indices, dataset, max_positions, raise_exception=False): + """ + [deprecated] Filter indices based on their size. + Use `FairseqDataset::filter_indices_by_size` instead. + + Args: + indices (List[int]): ordered list of dataset indices + dataset (FairseqDataset): fairseq dataset instance + max_positions (tuple): filter elements larger than this size. + Comparisons are done component-wise. + raise_exception (bool, optional): if ``True``, raise an exception if + any elements are filtered (default: False). + """ + warnings.warn( + "data_utils.filter_by_size is deprecated. " + "Use `FairseqDataset::filter_indices_by_size` instead.", + stacklevel=2, + ) + if isinstance(max_positions, float) or isinstance(max_positions, int): + if hasattr(dataset, "sizes") and isinstance(dataset.sizes, np.ndarray): + ignored = indices[dataset.sizes[indices] > max_positions].tolist() + indices = indices[dataset.sizes[indices] <= max_positions] + elif ( + hasattr(dataset, "sizes") + and isinstance(dataset.sizes, list) + and len(dataset.sizes) == 1 + ): + ignored = indices[dataset.sizes[0][indices] > max_positions].tolist() + indices = indices[dataset.sizes[0][indices] <= max_positions] + else: + indices, ignored = _filter_by_size_dynamic( + indices, dataset.size, max_positions + ) + else: + indices, ignored = _filter_by_size_dynamic(indices, dataset.size, max_positions) + + if len(ignored) > 0 and raise_exception: + raise Exception( + ( + "Size of sample #{} is invalid (={}) since max_positions={}, " + "skip this example with --skip-invalid-size-inputs-valid-test" + ).format(ignored[0], dataset.size(ignored[0]), max_positions) + ) + if len(ignored) > 0: + logger.warning( + ( + "{} samples have invalid sizes and will be skipped, " + "max_positions={}, first few sample ids={}" + ).format(len(ignored), max_positions, ignored[:10]) + ) + return indices + + +def filter_paired_dataset_indices_by_size(src_sizes, tgt_sizes, indices, max_sizes): + """Filter a list of sample indices. Remove those that are longer + than specified in max_sizes. + + Args: + indices (np.array): original array of sample indices + max_sizes (int or list[int] or tuple[int]): max sample size, + can be defined separately for src and tgt (then list or tuple) + + Returns: + np.array: filtered sample array + list: list of removed indices + """ + if max_sizes is None: + return indices, [] + if type(max_sizes) in (int, float): + max_src_size, max_tgt_size = max_sizes, max_sizes + else: + max_src_size, max_tgt_size = max_sizes + if tgt_sizes is None: + ignored = indices[src_sizes[indices] > max_src_size] + else: + ignored = indices[ + (src_sizes[indices] > max_src_size) | (tgt_sizes[indices] > max_tgt_size) + ] + if len(ignored) > 0: + if tgt_sizes is None: + indices = indices[src_sizes[indices] <= max_src_size] + else: + indices = indices[ + (src_sizes[indices] <= max_src_size) + & (tgt_sizes[indices] <= max_tgt_size) + ] + return indices, ignored.tolist() + + +def batch_by_size( + indices, + num_tokens_fn, + num_tokens_vec=None, + max_tokens=None, + max_sentences=None, + required_batch_size_multiple=1, + num_concat_batches=1, +): + """ + Yield mini-batches of indices bucketed by size. Batches may contain + sequences of different lengths. + + Args: + indices (List[int]): ordered list of dataset indices + num_tokens_fn (callable): function that returns the number of tokens at + a given index + num_tokens_vec (List[int], optional): precomputed vector of the number + of tokens for each index in indices (to enable faster batch generation) + max_tokens (int, optional): max number of tokens in each batch + (default: None). + max_sentences (int, optional): max number of sentences in each + batch (default: None). + required_batch_size_multiple (int, optional): require batch size to + be less than N or a multiple of N (default: 1). + """ + # added int() to avoid TypeError: an integer is required + max_tokens = int(max_tokens) if max_tokens is not None else -1 + max_sentences = max_sentences if max_sentences is not None else -1 + bsz_mult = required_batch_size_multiple + + if not isinstance(indices, np.ndarray): + indices = np.fromiter(indices, dtype=np.int64, count=-1) + + if num_tokens_vec is not None and not isinstance(num_tokens_vec, np.ndarray): + num_tokens_vec = np.fromiter(num_tokens_vec, dtype=np.int64, count=-1) + + assert num_tokens_vec is None # XXX(Adrian) erase if redundant + + num_tokens_vec = np.zeros(indices.shape[0], dtype=np.int64) + for pos in range(indices.shape[0]): + num_tokens_vec[pos] = num_tokens_fn(indices[pos]) + + assert max_tokens <= 0 or np.max(num_tokens_vec) <= max_tokens, ( + f"Sentences lengths should not exceed max_tokens={max_tokens}" + ) + + if indices.shape[0] == 0: + return [] + + batches = batch_by_size_vec(indices, num_tokens_vec, max_tokens, + max_sentences, bsz_mult) + + if num_concat_batches > 1: + # Concatenate subsequent batches + ga = num_concat_batches + grouped = [batches[i*ga:(i+1)*ga] for i in range(len(batches) // ga)] + grouped_batches = [np.concatenate(g) for g in grouped] + + return grouped_batches, batches + else: + return batches, batches + + +def post_process(sentence: str, symbol: str): + if symbol == "sentencepiece": + sentence = sentence.replace(" ", "").replace("\u2581", " ").strip() + elif symbol == "wordpiece": + sentence = sentence.replace(" ", "").replace("_", " ").strip() + elif symbol == "letter": + sentence = sentence.replace(" ", "").replace("|", " ").strip() + elif symbol == "silence": + import re + sentence = sentence.replace("", "") + sentence = re.sub(' +', ' ', sentence).strip() + elif symbol == "_EOW": + sentence = sentence.replace(" ", "").replace("_EOW", " ").strip() + elif symbol in {"subword_nmt", "@@ ", "@@"}: + if symbol == "subword_nmt": + symbol = "@@ " + sentence = (sentence + " ").replace(symbol, "").rstrip() + elif symbol == "none": + pass + elif symbol is not None: + raise NotImplementedError(f"Unknown post_process option: {symbol}") + return sentence + + +def compute_mask_indices( + shape: Tuple[int, int], + padding_mask: Optional[torch.Tensor], + mask_prob: float, + mask_length: int, + mask_type: str = "static", + mask_other: float = 0.0, + min_masks: int = 0, + no_overlap: bool = False, + min_space: int = 0, + require_same_masks: bool = True, + mask_dropout: float = 0.0, +) -> np.ndarray: + """ + Computes random mask spans for a given shape + + Args: + shape: the the shape for which to compute masks. + should be of size 2 where first element is batch size and 2nd is timesteps + padding_mask: optional padding mask of the same size as shape, which will prevent masking padded elements + mask_prob: probability for each token to be chosen as start of the span to be masked. this will be multiplied by + number of timesteps divided by length of mask span to mask approximately this percentage of all elements. + however due to overlaps, the actual number will be smaller (unless no_overlap is True) + mask_type: how to compute mask lengths + static = fixed size + uniform = sample from uniform distribution [mask_other, mask_length*2] + normal = sample from normal distribution with mean mask_length and stdev mask_other. mask is min 1 element + poisson = sample from possion distribution with lambda = mask length + min_masks: minimum number of masked spans + no_overlap: if false, will switch to an alternative recursive algorithm that prevents spans from overlapping + min_space: only used if no_overlap is True, this is how many elements to keep unmasked between spans + require_same_masks: if true, will randomly drop out masks until same amount of masks remains in each sample + mask_dropout: randomly dropout this percentage of masks in each example + """ + assert require_same_masks + assert mask_dropout == 0.0 + + bsz, all_sz = shape + mask = np.full((bsz, all_sz), False) + + all_num_mask = int( + # add a random number for probabilistic rounding + mask_prob * all_sz / float(mask_length) + + np.random.rand() + ) + + all_num_mask = max(min_masks, all_num_mask) + min_len = float("inf") + + mask_idcs = [] + for i in range(bsz): + if padding_mask is not None: + sz = all_sz - padding_mask[i].long().sum().item() + num_mask = int( + # add a random number for probabilistic rounding + mask_prob * sz / float(mask_length) + + np.random.rand() + ) + num_mask = max(min_masks, num_mask) + else: + sz = all_sz + num_mask = all_num_mask + + def get_lengths(num_mask): + if mask_type == "static": + lengths = np.full(num_mask, mask_length) + elif mask_type == "uniform": + lengths = np.random.randint(mask_other, mask_length * 2 + 1, size=num_mask) + elif mask_type == "normal": + lengths = np.random.normal(mask_length, mask_other, size=num_mask) + lengths = [max(1, int(round(x))) for x in lengths] + elif mask_type == "poisson": + lengths = np.random.poisson(mask_length, size=num_mask) + lengths = [int(round(x)) for x in lengths] + else: + raise ValueError("unknown mask selection " + mask_type) + return lengths + + lengths = get_lengths(num_mask) + + if sum(lengths) == 0: + lengths[0] = min(mask_length, sz - 1) + + if no_overlap: + mask_idc = [] + + def arrange(s, e, length, keep_length): + span_start = np.random.randint(s, e - length) + mask_idc.extend(span_start + i for i in range(length)) + + new_parts = [] + if span_start - s - min_space >= keep_length: + new_parts.append((s, span_start - min_space + 1)) + if e - span_start - keep_length - min_space > keep_length: + new_parts.append((span_start + length + min_space, e)) + return new_parts + + parts = [(0, sz)] + min_length = min(lengths) + for length in sorted(lengths, reverse=True): + lens = np.fromiter( + (e - s if e - s >= length + min_space else 0 for s, e in parts), + np.int, + ) + l_sum = np.sum(lens) + if l_sum == 0: + break + probs = lens / np.sum(lens) + c = np.random.choice(len(parts), p=probs) + s, e = parts.pop(c) + parts.extend(arrange(s, e, length, min_length)) + mask_idc = np.asarray(mask_idc) + mask_idc = np.unique(mask_idc[mask_idc < sz]) + else: + min_len = min(lengths) + if sz - min_len <= num_mask: + min_len = sz - num_mask - 1 + + mask_idc = np.random.choice(sz - min_len, num_mask, replace=False) + + mask_idc = np.asarray( + [ + mask_idc[j] + offset + for j in range(len(mask_idc)) + for offset in range(lengths[j]) + ] + ) + + mask_idcs.append(np.unique(mask_idc[mask_idc < sz])) + + min_len = min([len(m) for m in mask_idcs]) + for i, mask_idc in enumerate(mask_idcs): + if len(mask_idc) > min_len and require_same_masks: + mask_idc = np.random.choice(mask_idc, min_len, replace=False) + if mask_dropout > 0: + num_holes = np.rint(len(mask_idc) * mask_dropout).astype(int) + mask_idc = np.random.choice( + mask_idc, len(mask_idc) - num_holes, replace=False + ) + + mask[i, mask_idc] = True + + return mask + + +def get_mem_usage(): + try: + import psutil + + mb = 1024 * 1024 + return f"used={psutil.virtual_memory().used / mb}Mb; avail={psutil.virtual_memory().available / mb}Mb" + except ImportError: + return "N/A" + + +def get_buckets(sizes, num_buckets): + buckets = np.unique( + np.percentile( + sizes, + np.linspace(0, 100, num_buckets + 1), + interpolation='lower', + )[1:] + ) + return buckets + + +def get_bucketed_sizes(orig_sizes, buckets): + sizes = np.copy(orig_sizes) + assert np.min(sizes) >= 0 + start_val = -1 + for end_val in buckets: + mask = (sizes > start_val) & (sizes <= end_val) + sizes[mask] = end_val + start_val = end_val + return sizes + + +def _find_extra_valid_paths(dataset_path: str) -> set: + paths = utils.split_paths(dataset_path) + all_valid_paths = set() + for sub_dir in paths: + contents = PathManager.ls(sub_dir) + valid_paths = [c for c in contents if re.match("valid*[0-9].*", c) is not None] + all_valid_paths |= {os.path.basename(p) for p in valid_paths} + # Remove .bin, .idx etc + roots = {os.path.splitext(p)[0] for p in all_valid_paths} + return roots diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/data_utils_fast.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/data_utils_fast.py new file mode 100644 index 000000000..0fa76b591 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/data_utils_fast.py @@ -0,0 +1,96 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +from numba import jit + + +@jit(nopython=True) +def batch_by_size_vec(indices, num_tokens_vec, max_tokens, max_sentences, bsz_mult): + """A numba version of cython batch_by_size_vec from data_utils_fast.pyx""" + + indices_len = indices.shape[0] + batches_ends = np.zeros(indices_len, dtype=np.int32) + batches_ends_view = batches_ends + num_tokens_view = num_tokens_vec + + pos = 0 + new_batch_end = 0 + + new_batch_max_tokens = 0 + new_batch_sentences = 0 + new_batch_num_tokens = 0 + + overflow = False + size_matches_with_bsz_mult = False + + batches_count = 0 + batch_start = 0 + tail_max_tokens = 0 + batch_max_tokens = 0 + + for pos in range(indices_len): + # At every pos we keep stats about the last complete batch [batch_start:batch_end), + # and tail [batch_end:pos]. + # 1) Every time when (batch + tail) forms a valid batch + # (according to max_tokens, max_sentences and bsz_mult) we append tail to batch. + # 2) When (batch+tail) violates max_tokens or max_sentences constraints + # we finalize running batch, and tail becomes a new batch. + # 3) There is a corner case when tail also violates constraints. + # In that situation [batch_end:pos-1] (tail without the current pos) + # gets added to the finalized batches, while [pos:pos] becomes a new tail. + # + # Important: For the sake of performance try to avoid using function calls within this loop. + + tail_max_tokens = tail_max_tokens \ + if tail_max_tokens > num_tokens_view[pos] \ + else num_tokens_view[pos] + new_batch_end = pos + 1 + new_batch_max_tokens = batch_max_tokens \ + if batch_max_tokens > tail_max_tokens \ + else tail_max_tokens + new_batch_sentences = new_batch_end - batch_start + new_batch_num_tokens = new_batch_sentences * new_batch_max_tokens + + overflow = (new_batch_sentences > max_sentences > 0 or + new_batch_num_tokens > max_tokens > 0) + size_matches_with_bsz_mult = (new_batch_sentences < bsz_mult or + new_batch_sentences % bsz_mult == 0) + + if overflow: + tail_num_tokens = tail_max_tokens * \ + (new_batch_end - batches_ends_view[batches_count]) + tail_overflow = tail_num_tokens > max_tokens > 0 + # In case of a tail overflow finalize two batches + if tail_overflow: + batches_count += 1 + batches_ends_view[batches_count] = pos + tail_max_tokens = num_tokens_view[pos] + batch_start = batches_ends_view[batches_count] + batches_count += 1 + new_batch_max_tokens = tail_max_tokens + + if overflow or size_matches_with_bsz_mult: + batches_ends_view[batches_count] = new_batch_end + batch_max_tokens = new_batch_max_tokens + tail_max_tokens = 0 + if batches_ends_view[batches_count] != indices_len: + batches_count += 1 + # Memory and time-efficient split + return np.split(indices, batches_ends[:batches_count]) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/dictionary.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/dictionary.py new file mode 100644 index 000000000..e68dca966 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/data/dictionary.py @@ -0,0 +1,394 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +from collections import Counter +from multiprocessing import Pool + +import torch +from common.fairseq import utils +from common.fairseq.data import data_utils +from common.fairseq.file_chunker_utils import Chunker, find_offsets +from common.fairseq.file_io import PathManager +from common.fairseq.tokenizer import tokenize_line + + +class Dictionary: + """A mapping from symbols to consecutive integers""" + + def __init__( + self, + *, # begin keyword-only arguments + bos="", + pad="", + eos="", + unk="", + extra_special_symbols=None, + ): + self.bos_word, self.unk_word, self.pad_word, self.eos_word = bos, unk, pad, eos + self.symbols = [] + self.count = [] + self.indices = {} + self.bos_index = self.add_symbol(bos) + self.pad_index = self.add_symbol(pad) + self.eos_index = self.add_symbol(eos) + self.unk_index = self.add_symbol(unk) + if extra_special_symbols: + for s in extra_special_symbols: + self.add_symbol(s) + self.nspecial = len(self.symbols) + + def __eq__(self, other): + return self.indices == other.indices + + def __getitem__(self, idx): + if idx < len(self.symbols): + return self.symbols[idx] + return self.unk_word + + def get_count(self, idx): + return self.count[idx] + + def __len__(self): + """Returns the number of symbols in the dictionary""" + return len(self.symbols) + + def __contains__(self, sym): + return sym in self.indices + + def index(self, sym): + """Returns the index of the specified symbol""" + assert isinstance(sym, str) + if sym in self.indices: + return self.indices[sym] + return self.unk_index + + def string( + self, + tensor, + bpe_symbol=None, + escape_unk=False, + extra_symbols_to_ignore=None, + unk_string=None, + include_eos=False, + separator=" ", + ): + """Helper for converting a tensor of token indices to a string. + + Can optionally remove BPE symbols or escape words. + """ + if torch.is_tensor(tensor) and tensor.dim() == 2: + return "\n".join( + self.string( + t, + bpe_symbol, + escape_unk, + extra_symbols_to_ignore, + include_eos=include_eos, + ) + for t in tensor + ) + + extra_symbols_to_ignore = set(extra_symbols_to_ignore or []) + extra_symbols_to_ignore.add(self.eos()) + + def token_string(i): + if i == self.unk(): + if unk_string is not None: + return unk_string + else: + return self.unk_string(escape_unk) + else: + return self[i] + + if hasattr(self, "bos_index"): + extra_symbols_to_ignore.add(self.bos()) + + sent = separator.join( + token_string(i) + for i in tensor + if utils.item(i) not in extra_symbols_to_ignore + ) + + return data_utils.post_process(sent, bpe_symbol) + + def unk_string(self, escape=False): + """Return unknown string, optionally escaped as: <>""" + if escape: + return "<{}>".format(self.unk_word) + else: + return self.unk_word + + def add_symbol(self, word, n=1, overwrite=False): + """Adds a word to the dictionary""" + if word in self.indices and not overwrite: + idx = self.indices[word] + self.count[idx] = self.count[idx] + n + return idx + else: + idx = len(self.symbols) + self.indices[word] = idx + self.symbols.append(word) + self.count.append(n) + return idx + + def update(self, new_dict): + """Updates counts from new dictionary.""" + for word in new_dict.symbols: + idx2 = new_dict.indices[word] + if word in self.indices: + idx = self.indices[word] + self.count[idx] = self.count[idx] + new_dict.count[idx2] + else: + idx = len(self.symbols) + self.indices[word] = idx + self.symbols.append(word) + self.count.append(new_dict.count[idx2]) + + def finalize(self, threshold=-1, nwords=-1, padding_factor=8): + """Sort symbols by frequency in descending order, ignoring special ones. + + Args: + - threshold defines the minimum word count + - nwords defines the total number of words in the final dictionary, + including special symbols + - padding_factor can be used to pad the dictionary size to be a + multiple of 8, which is important on some hardware (e.g., Nvidia + Tensor Cores). + """ + if nwords <= 0: + nwords = len(self) + + new_indices = dict(zip(self.symbols[: self.nspecial], range(self.nspecial))) + new_symbols = self.symbols[: self.nspecial] + new_count = self.count[: self.nspecial] + + c = Counter( + dict( + sorted(zip(self.symbols[self.nspecial :], self.count[self.nspecial :])) + ) + ) + for symbol, count in c.most_common(nwords - self.nspecial): + if count >= threshold: + new_indices[symbol] = len(new_symbols) + new_symbols.append(symbol) + new_count.append(count) + else: + break + + assert len(new_symbols) == len(new_indices) + + self.count = list(new_count) + self.symbols = list(new_symbols) + self.indices = new_indices + + self.pad_to_multiple_(padding_factor) + + def pad_to_multiple_(self, padding_factor): + """Pad Dictionary size to be a multiple of *padding_factor*.""" + if padding_factor > 1: + i = 0 + while len(self) % padding_factor != 0: + symbol = "madeupword{:04d}".format(i) + self.add_symbol(symbol, n=0) + i += 1 + + def bos(self): + """Helper to get index of beginning-of-sentence symbol""" + return self.bos_index + + def pad(self): + """Helper to get index of pad symbol""" + return self.pad_index + + def eos(self): + """Helper to get index of end-of-sentence symbol""" + return self.eos_index + + def unk(self): + """Helper to get index of unk symbol""" + return self.unk_index + + @classmethod + def load(cls, f): + """Loads the dictionary from a text file with the format: + + ``` + + + ... + ``` + """ + d = cls() + d.add_from_file(f) + return d + + def add_from_file(self, f): + """ + Loads a pre-existing dictionary from a text file and adds its symbols + to this instance. + """ + if isinstance(f, str): + try: + with open(PathManager.get_local_path(f), "r", encoding="utf-8") as fd: + self.add_from_file(fd) + except FileNotFoundError as fnfe: + raise fnfe + except UnicodeError: + raise Exception( + "Incorrect encoding detected in {}, please " + "rebuild the dataset".format(f) + ) + return + + lines = f.readlines() + indices_start_line = self._load_meta(lines) + + for line in lines[indices_start_line:]: + try: + line, field = line.rstrip().rsplit(" ", 1) + if field == "#fairseq:overwrite": + overwrite = True + line, field = line.rsplit(" ", 1) + else: + overwrite = False + count = int(field) + word = line + if word in self and not overwrite: + raise RuntimeError( + "Duplicate word found when loading Dictionary: '{}'. " + "Duplicate words can overwrite earlier ones by adding the " + "#fairseq:overwrite flag at the end of the corresponding row " + "in the dictionary file. If using the Camembert model, please " + "download an updated copy of the model file.".format(word) + ) + self.add_symbol(word, n=count, overwrite=overwrite) + except ValueError: + raise ValueError( + "Incorrect dictionary format, expected ' [flags]'" + ) + + def _save(self, f, kv_iterator): + if isinstance(f, str): + PathManager.mkdirs(os.path.dirname(f)) + with PathManager.open(f, "w", encoding="utf-8") as fd: + return self.save(fd) + for k, v in kv_iterator: + print("{} {}".format(k, v), file=f) + + def _get_meta(self): + return [], [] + + def _load_meta(self, lines): + return 0 + + def save(self, f): + """Stores dictionary into a text file""" + ex_keys, ex_vals = self._get_meta() + self._save( + f, + zip( + ex_keys + self.symbols[self.nspecial :], + ex_vals + self.count[self.nspecial :], + ), + ) + + def dummy_sentence(self, length): + t = torch.Tensor(length).uniform_(self.nspecial + 1, len(self)).long() + t[-1] = self.eos() + return t + + def encode_line( + self, + line, + line_tokenizer=tokenize_line, + add_if_not_exist=True, + consumer=None, + append_eos=True, + reverse_order=False, + ) -> torch.IntTensor: + words = line_tokenizer(line) + if reverse_order: + words = list(reversed(words)) + nwords = len(words) + ids = torch.IntTensor(nwords + 1 if append_eos else nwords) + + for i, word in enumerate(words): + if add_if_not_exist: + idx = self.add_symbol(word) + else: + idx = self.index(word) + if consumer is not None: + consumer(word, idx) + ids[i] = idx + if append_eos: + ids[nwords] = self.eos_index + return ids + + @staticmethod + def _add_file_to_dictionary_single_worker( + filename, + tokenize, + eos_word, + start_offset, + end_offset, + ): + counter = Counter() + with Chunker(filename, start_offset, end_offset) as line_iterator: + for line in line_iterator: + for word in tokenize(line): + counter.update([word]) + counter.update([eos_word]) + return counter + + @staticmethod + def add_file_to_dictionary(filename, dict, tokenize, num_workers): + def merge_result(counter): + for w, c in sorted(counter.items()): + dict.add_symbol(w, c) + + local_file = PathManager.get_local_path(filename) + offsets = find_offsets(local_file, num_workers) + if num_workers > 1: + chunks = zip(offsets, offsets[1:]) + pool = Pool(processes=num_workers) + results = [] + for (start_offset, end_offset) in chunks: + results.append( + pool.apply_async( + Dictionary._add_file_to_dictionary_single_worker, + ( + local_file, + tokenize, + dict.eos_word, + start_offset, + end_offset, + ), + ) + ) + pool.close() + pool.join() + for r in results: + merge_result(r.get()) + else: + merge_result( + Dictionary._add_file_to_dictionary_single_worker( + local_file, tokenize, dict.eos_word, offsets[0], offsets[1] + ) + ) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/dist.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/dist.py new file mode 100644 index 000000000..e7677c42f --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/dist.py @@ -0,0 +1,69 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch + + +class ModuleProxyWrapper(torch.nn.Module): + """ + Wrap a DistributedDataParallel module and forward requests for missing + attributes to the module wrapped by DDP (the twice-wrapped module). + Also forward calls to :func:`state_dict` and :func:`load_state_dict`. + + Usage:: + + module.xyz = "hello world" + wrapped_module = DistributedDataParallel(module, **ddp_args) + wrapped_module = ModuleProxyWrapper(wrapped_module) + assert wrapped_module.xyz == "hello world" + assert wrapped_module.state_dict().keys() == module.state_dict().keys() + + Args: + module (nn.Module): module to wrap + """ + + def __init__(self, module: torch.nn.Module): + super().__init__() + assert hasattr(module, "module"), \ + "ModuleProxyWrapper expects input to wrap another module" + self.module = module + + def __getattr__(self, name): + """Forward missing attributes to twice-wrapped module.""" + try: + # defer to nn.Module's logic + return super().__getattr__(name) + except AttributeError: + try: + # forward to the once-wrapped module + return getattr(self.module, name) + except AttributeError: + # forward to the twice-wrapped module + return getattr(self.module.module, name) + + def state_dict(self, *args, **kwargs): + """Forward to the twice-wrapped module.""" + return self.module.module.state_dict(*args, **kwargs) + + def load_state_dict(self, *args, **kwargs): + """Forward to the twice-wrapped module.""" + return self.module.module.load_state_dict(*args, **kwargs) + + def forward(self, *args, **kwargs): + return self.module(*args, **kwargs) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/file_chunker_utils.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/file_chunker_utils.py new file mode 100644 index 000000000..b191da943 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/file_chunker_utils.py @@ -0,0 +1,98 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import typing as tp + + +def _safe_readline(fd) -> str: + pos = fd.tell() + while True: + try: + return fd.readline() + except UnicodeDecodeError: + pos -= 1 + fd.seek(pos) # search where this character begins + + +def find_offsets(filename: str, num_chunks: int) -> tp.List[int]: + """ + given a file and a number of chuncks, find the offsets in the file + to be able to chunk around full lines. + """ + with open(filename, "r", encoding="utf-8") as f: + size = os.fstat(f.fileno()).st_size + chunk_size = size // num_chunks + offsets = [0 for _ in range(num_chunks + 1)] + for i in range(1, num_chunks): + f.seek(chunk_size * i) + _safe_readline(f) + offsets[i] = f.tell() + offsets[-1] = size + return offsets + + +class ChunkLineIterator: + """ + Iterator to properly iterate over lines of a file chunck. + """ + + def __init__(self, fd, start_offset: int, end_offset: int): + self._fd = fd + self._start_offset = start_offset + self._end_offset = end_offset + + def __iter__(self) -> tp.Iterable[str]: + self._fd.seek(self._start_offset) + # next(f) breaks f.tell(), hence readline() must be used + line = _safe_readline(self._fd) + while line: + pos = self._fd.tell() + # f.tell() does not always give the byte position in the file + # sometimes it skips to a very large number + # it is unlikely that through a normal read we go from + # end bytes to end + 2**32 bytes (4 GB) and this makes it unlikely + # that the procedure breaks by the undeterministic behavior of + # f.tell() + if ( + self._end_offset > 0 + and pos > self._end_offset + and pos < self._end_offset + 2 ** 32 + ): + break + yield line + line = self._fd.readline() + + +class Chunker: + """ + contextmanager to read a chunck of a file line by line. + """ + + def __init__(self, path: str, start_offset: int, end_offset: int): + self.path = path + self.start_offset = start_offset + self.end_offset = end_offset + + def __enter__(self) -> ChunkLineIterator: + self.fd = open(self.path, "r", encoding="utf-8") + return ChunkLineIterator(self.fd, self.start_offset, self.end_offset) + + def __exit__(self, exc_type, exc_val, exc_tb) -> None: + self.fd.close() diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/file_io.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/file_io.py new file mode 100644 index 000000000..dd4b0d747 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/file_io.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import os +import shutil +from typing import List, Optional + + +logger = logging.getLogger(__file__) + + +try: + from iopath.common.file_io import g_pathmgr as IOPathManager + + try: + # [FB only - for now] AWS PathHandler for PathManager + from .fb_pathhandlers import S3PathHandler + + IOPathManager.register_handler(S3PathHandler()) + except KeyError: + logging.warning("S3PathHandler already registered.") + except ImportError: + logging.debug( + "S3PathHandler couldn't be imported. Either missing fb-only files, or boto3 module." + ) + +except ImportError: + IOPathManager = None + + +class PathManager: + """ + Wrapper for insulating OSS I/O (using Python builtin operations) from + iopath's PathManager abstraction (for transparently handling various + internal backends). + """ + + @staticmethod + def open( + path: str, + mode: str = "r", + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + ): + if IOPathManager: + return IOPathManager.open( + path=path, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + ) + return open( + path, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + ) + + @staticmethod + def copy(src_path: str, dst_path: str, overwrite: bool = False) -> bool: + if IOPathManager: + return IOPathManager.copy( + src_path=src_path, dst_path=dst_path, overwrite=overwrite + ) + return shutil.copyfile(src_path, dst_path) + + @staticmethod + def get_local_path(path: str, **kwargs) -> str: + if IOPathManager: + return IOPathManager.get_local_path(path, **kwargs) + return path + + @staticmethod + def exists(path: str) -> bool: + if IOPathManager: + return IOPathManager.exists(path) + return os.path.exists(path) + + @staticmethod + def isfile(path: str) -> bool: + if IOPathManager: + return IOPathManager.isfile(path) + return os.path.isfile(path) + + @staticmethod + def ls(path: str) -> List[str]: + if IOPathManager: + return IOPathManager.ls(path) + return os.listdir(path) + + @staticmethod + def mkdirs(path: str) -> None: + if IOPathManager: + return IOPathManager.mkdirs(path) + os.makedirs(path, exist_ok=True) + + @staticmethod + def rm(path: str) -> None: + if IOPathManager: + return IOPathManager.rm(path) + os.remove(path) + + @staticmethod + def chmod(path: str, mode: int) -> None: + if not PathManager.path_requires_pathmanager(path): + os.chmod(path, mode) + + @staticmethod + def register_handler(handler) -> None: + if IOPathManager: + return IOPathManager.register_handler(handler=handler) + + @staticmethod + def copy_from_local( + local_path: str, dst_path: str, overwrite: bool = False, **kwargs + ) -> None: + if IOPathManager: + return IOPathManager.copy_from_local( + local_path=local_path, dst_path=dst_path, overwrite=overwrite, **kwargs + ) + return shutil.copyfile(local_path, dst_path) + + @staticmethod + def path_requires_pathmanager(path: str) -> bool: + """Do we require PathManager to access given path?""" + if IOPathManager: + for p in IOPathManager._path_handlers.keys(): + if path.startswith(p): + return True + return False + + @staticmethod + def supports_rename(path: str) -> bool: + # PathManager doesn't yet support renames + return not PathManager.path_requires_pathmanager(path) + + @staticmethod + def rename(src: str, dst: str): + os.rename(src, dst) + + """ + ioPath async PathManager methods: + """ + @staticmethod + def opena( + path: str, + mode: str = "r", + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + ): + """ + Return file descriptor with asynchronous write operations. + """ + global IOPathManager + if not IOPathManager: + logging.info("ioPath is initializing PathManager.") + try: + from iopath.common.file_io import PathManager + IOPathManager = PathManager() + except Exception: + logging.exception("Failed to initialize ioPath PathManager object.") + return IOPathManager.opena( + path=path, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + ) + + @staticmethod + def async_close() -> bool: + """ + Wait for files to be written and clean up asynchronous PathManager. + NOTE: `PathManager.async_close()` must be called at the end of any + script that uses `PathManager.opena(...)`. + """ + global IOPathManager + if IOPathManager: + return IOPathManager.async_close() + return False diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/incremental_decoding_utils.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/incremental_decoding_utils.py new file mode 100644 index 000000000..07e53cbbe --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/incremental_decoding_utils.py @@ -0,0 +1,65 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import uuid +from typing import Dict, Optional + +from torch import Tensor + + +class FairseqIncrementalState(object): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.init_incremental_state() + + def init_incremental_state(self): + self._incremental_state_id = str(uuid.uuid4()) + + def _get_full_incremental_state_key(self, key: str) -> str: + return "{}.{}".format(self._incremental_state_id, key) + + def get_incremental_state( + self, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]], + key: str, + ) -> Optional[Dict[str, Optional[Tensor]]]: + """Helper for getting incremental state for an nn.Module.""" + full_key = self._get_full_incremental_state_key(key) + if incremental_state is None or full_key not in incremental_state: + return None + return incremental_state[full_key] + + def set_incremental_state( + self, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]], + key: str, + value: Dict[str, Optional[Tensor]], + ) -> Optional[Dict[str, Dict[str, Optional[Tensor]]]]: + """Helper for setting incremental state for an nn.Module.""" + if incremental_state is not None: + full_key = self._get_full_incremental_state_key(key) + incremental_state[full_key] = value + return incremental_state + + +def with_incremental_state(cls): + cls.__bases__ = (FairseqIncrementalState,) + tuple( + b for b in cls.__bases__ if b != FairseqIncrementalState + ) + return cls diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/__init__.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/__init__.py new file mode 100644 index 000000000..f17bbdcbd --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/__init__.py @@ -0,0 +1,44 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""isort:skip_file""" + +from .fairseq_dropout import FairseqDropout +from .fp32_group_norm import Fp32GroupNorm, Fp32MaskedGroupNorm, MaskedGroupNorm +from .gelu import gelu, gelu_accurate +from .grad_multiply import GradMultiply +from .gumbel_vector_quantizer import GumbelVectorQuantizer +from .layer_norm import Fp32LayerNorm, LayerNorm +from .multihead_attention import MultiheadAttention +from .same_pad import SamePad +from .transpose_last import TransposeLast + +__all__ = [ + "Fp32GroupNorm", + "Fp32LayerNorm", + "Fp32MaskedGroupNorm", + "MaskedGroupNorm", + "gelu", + "gelu_accurate", + "GradMultiply", + "GumbelVectorQuantizer", + "LayerNorm", + "MultiheadAttention", + "SamePad", + "TransposeLast", +] diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/fairseq_dropout.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/fairseq_dropout.py new file mode 100644 index 000000000..9dae785a9 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/fairseq_dropout.py @@ -0,0 +1,65 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +from typing import List, Optional + +import torch.nn as nn +import torch.nn.functional as F + + +logger = logging.getLogger(__name__) + + +class FairseqDropout(nn.Module): + def __init__(self, p, module_name=None): + super().__init__() + self.p = p + self.module_name = module_name + self.apply_during_inference = False + + def forward(self, x, inplace: bool = False): + if self.p > 0 and (self.training or self.apply_during_inference): + return F.dropout(x, p=self.p, training=True, inplace=inplace) + else: + return x + + def make_generation_fast_( + self, + name: str, + retain_dropout: bool = False, + retain_dropout_modules: Optional[List[str]] = None, + **kwargs + ): + if retain_dropout: + if retain_dropout_modules is not None and self.module_name is None: + logger.warning( + "Cannot enable dropout during inference for module {} " + "because module_name was not set".format(name) + ) + elif ( + retain_dropout_modules is None # if None, apply to all modules + or self.module_name in retain_dropout_modules + ): + logger.info( + "Enabling dropout during inference for module: {}".format(name) + ) + self.apply_during_inference = True + else: + logger.info("Disabling dropout for module: {}".format(name)) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/fp32_group_norm.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/fp32_group_norm.py new file mode 100644 index 000000000..fef3b1eef --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/fp32_group_norm.py @@ -0,0 +1,122 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Layer norm done in fp32 (for fp16 training).""" + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class Fp32GroupNorm(nn.GroupNorm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def forward(self, input): + output = F.group_norm( + input.float(), + self.num_groups, + self.weight.float() if self.weight is not None else None, + self.bias.float() if self.bias is not None else None, + self.eps, + ) + return output.type_as(input) + + +class MaskedGroupNorm(nn.Module): + """GroupNorm layer which skips padding. + + In wav2vec 2.0 encoder where batch size is small and time dimensio huge, + this is nearly as fast as nn.GroupNorm. + + Ready for TorchScript, favors composition over inheritance. + """ + def __init__(self, num_groups, num_channels, eps=1e-05, affine=True, + device=None, dtype=None): + assert num_groups == num_channels, ( + "num_groups != num_channels not yet supported in MaskedGroupNorm") + super().__init__() + self._group_norm = nn.GroupNorm(num_groups, num_channels, eps=eps, + affine=affine, device=device, + dtype=dtype) + + def forward(self, x, x_lens): + var = torch.zeros_like(x[:, :, 0]) + mean = torch.zeros_like(x[:, :, 0]) + for i in range(x.size(0)): + mean[i] = torch.mean(x[i, :, :x_lens[i]], dim=1) + var[i] = torch.var(x[i, :, :x_lens[i]], dim=1, unbiased=False) + out = (x - mean[:, :, None]) / torch.sqrt(var[:, :, None] + self._group_norm.eps) + if self._group_norm.affine: + return out * self._group_norm.weight[None, :, None] + self._group_norm.bias[None, :, None] + else: + return out + + +class Fp32MaskedGroupNorm(nn.Module): + """GroupNorm layer which skips padding. + + In wav2vec 2.0 encoder where batch size is small and time dimensio huge, + this is nearly as fast as nn.GroupNorm. + + Ready for TorchScript, favors composition over inheritance. + """ + def __init__(self, num_groups, num_channels, eps=1e-05, affine=True, + device=None, dtype=None): + assert num_groups == num_channels, ( + "num_groups != num_channels not yet supported in MaskedGroupNorm") + super().__init__() + self._group_norm = nn.GroupNorm(num_groups, num_channels, eps=eps, + affine=affine, device=device, + dtype=dtype) + + def hook(state_dict, prefix, *args, **kwargs): + """Renames keys from layers which used inheritance.""" + new_sd = {} + for k, v in state_dict.items(): + if not k.startswith(prefix): + new_sd[k] = v + else: + *pref, param = k.split(".") + new_k = ".".join(pref + ["_group_norm", param]) + new_sd[new_k] = v + state_dict.clear() + state_dict.update(new_sd) + + self._register_load_state_dict_pre_hook(hook) + + def forward(self, x, x_lens): + return self._forward( + x.float(), + x_lens, + self._group_norm.weight.float() if self._group_norm.weight is not None else None, + self._group_norm.bias.float() if self._group_norm.bias is not None else None, + ).type_as(x) + + def _forward(self, x, x_lens, weight, bias): + var = torch.zeros_like(x[:, :, 0]) + mean = torch.zeros_like(x[:, :, 0]) + for i in range(x.size(0)): + mean[i] = torch.mean(x[i, :, :x_lens[i]], dim=1) + var[i] = torch.var(x[i, :, :x_lens[i]], dim=1, unbiased=False) + out = (x - mean[:, :, None]) / torch.sqrt(var[:, :, None] + self._group_norm.eps) + if self._group_norm.affine: + return out * weight[None, :, None] + bias[None, :, None] + else: + return out diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/gelu.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/gelu.py new file mode 100644 index 000000000..5d7e230d4 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/gelu.py @@ -0,0 +1,39 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +See "Gaussian Error Linear Units (GELUs)" by Dan Hendrycks and Kevin Gimpel with +the corresponding GitHub repo: https://github.com/hendrycks/GELUs +""" + +import math + +import torch +import torch.nn as nn + + +def gelu_accurate(x): + if not hasattr(gelu_accurate, "_a"): + gelu_accurate._a = math.sqrt(2 / math.pi) + return ( + 0.5 * x * (1 + torch.tanh(gelu_accurate._a * (x + 0.044715 * torch.pow(x, 3)))) + ) + + +def gelu(x: torch.Tensor) -> torch.Tensor: + return torch.nn.functional.gelu(x.float()).type_as(x) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/grad_multiply.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/grad_multiply.py new file mode 100644 index 000000000..4fdce1cce --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/grad_multiply.py @@ -0,0 +1,32 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch + + +class GradMultiply(torch.autograd.Function): + @staticmethod + def forward(ctx, x, scale): + ctx.scale = scale + res = x.new(x) + return res + + @staticmethod + def backward(ctx, grad): + return grad * ctx.scale, None diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/gumbel_vector_quantizer.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/gumbel_vector_quantizer.py new file mode 100644 index 000000000..a96111fb2 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/gumbel_vector_quantizer.py @@ -0,0 +1,216 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class GumbelVectorQuantizer(nn.Module): + def __init__( + self, + dim, + num_vars, + temp, + groups, + combine_groups, + vq_dim, + time_first, + activation=nn.GELU(), + weight_proj_depth=1, + weight_proj_factor=1, + ): + """Vector quantization using gumbel softmax + + Args: + dim: input dimension (channels) + num_vars: number of quantized vectors per group + temp: temperature for training. this should be a tuple of 3 elements: (start, stop, decay factor) + groups: number of groups for vector quantization + combine_groups: whether to use the vectors for all groups + vq_dim: dimensionality of the resulting quantized vector + time_first: if true, expect input in BxTxC format, otherwise in BxCxT + activation: what activation to use (should be a module). this is only used if weight_proj_depth is > 1 + weight_proj_depth: number of layers (with activation in between) to project input before computing logits + weight_proj_factor: this is used only if weight_proj_depth is > 1. scales the inner dimensionality of + projections by this factor + """ + super().__init__() + + self.groups = groups + self.combine_groups = combine_groups + self.input_dim = dim + self.num_vars = num_vars + self.time_first = time_first + + assert ( + vq_dim % groups == 0 + ), f"dim {vq_dim} must be divisible by groups {groups} for concatenation" + + var_dim = vq_dim // groups + num_groups = groups if not combine_groups else 1 + + self.vars = nn.Parameter(torch.FloatTensor(1, num_groups * num_vars, var_dim)) + nn.init.uniform_(self.vars) + + if weight_proj_depth > 1: + + def block(input_dim, output_dim): + return nn.Sequential(nn.Linear(input_dim, output_dim), activation) + + inner_dim = self.input_dim * weight_proj_factor + self.weight_proj = nn.Sequential( + *[ + block(self.input_dim if i == 0 else inner_dim, inner_dim) + for i in range(weight_proj_depth - 1) + ], + nn.Linear(inner_dim, groups * num_vars), + ) + else: + self.weight_proj = nn.Linear(self.input_dim, groups * num_vars) + nn.init.normal_(self.weight_proj.weight, mean=0, std=1) + nn.init.zeros_(self.weight_proj.bias) + + if isinstance(temp, str): + import ast + temp = ast.literal_eval(temp) + assert len(temp) == 3, f"{temp}, {len(temp)}" + + self.max_temp, self.min_temp, self.temp_decay = temp + self.curr_temp = self.max_temp + self.codebook_indices = None + + def set_num_updates(self, num_updates): + self.curr_temp = max( + self.max_temp * self.temp_decay ** num_updates, self.min_temp + ) + + def get_codebook_indices(self): + if self.codebook_indices is None: + from itertools import product + + p = [range(self.num_vars)] * self.groups + inds = list(product(*p)) + self.codebook_indices = torch.tensor( + inds, dtype=torch.long, device=self.vars.device + ).flatten() + + if not self.combine_groups: + self.codebook_indices = self.codebook_indices.view( + self.num_vars ** self.groups, -1 + ) + for b in range(1, self.groups): + self.codebook_indices[:, b] += self.num_vars * b + self.codebook_indices = self.codebook_indices.flatten() + return self.codebook_indices + + def codebook(self): + indices = self.get_codebook_indices() + return ( + self.vars.squeeze(0) + .index_select(0, indices) + .view(self.num_vars ** self.groups, -1) + ) + + def sample_from_codebook(self, b, n): + indices = self.get_codebook_indices() + indices = indices.view(-1, self.groups) + cb_size = indices.size(0) + assert ( + n < cb_size + ), f"sample size {n} is greater than size of codebook {cb_size}" + sample_idx = torch.randint(low=0, high=cb_size, size=(b * n,)) + indices = indices[sample_idx] + + z = self.vars.squeeze(0).index_select(0, indices.flatten()).view(b, n, -1) + return z + + def to_codebook_index(self, indices): + res = indices.new_full(indices.shape[:-1], 0) + for i in range(self.groups): + exponent = self.groups - i - 1 + res += indices[..., i] * (self.num_vars ** exponent) + return res + + def forward_idx(self, x): + res = self.forward(x, produce_targets=True) + return res["x"], res["targets"] + + def forward(self, x, produce_targets=False): + + result = {"num_vars": self.num_vars * self.groups} + + if not self.time_first: + x = x.transpose(1, 2) + + bsz, tsz, fsz = x.shape + x = x.reshape(-1, fsz) + x = self.weight_proj(x) + x = x.view(bsz * tsz * self.groups, -1) + + _, k = x.max(-1) + hard_x = ( + x.new_zeros(*x.shape) + .scatter_(-1, k.view(-1, 1), 1.0) + .view(bsz * tsz, self.groups, -1) + ) + hard_probs = torch.mean(hard_x.float(), dim=0) + result["code_perplexity"] = torch.exp( + -torch.sum(hard_probs * torch.log(hard_probs + 1e-7), dim=-1) + ).sum() + + avg_probs = torch.softmax( + x.view(bsz * tsz, self.groups, -1).float(), dim=-1 + ).mean(dim=0) + result["prob_perplexity"] = torch.exp( + -torch.sum(avg_probs * torch.log(avg_probs + 1e-7), dim=-1) + ).sum() + + result["temp"] = self.curr_temp + + if self.training: + x = F.gumbel_softmax(x.float(), tau=self.curr_temp, hard=True).type_as(x) + else: + x = hard_x + + x = x.view(bsz * tsz, -1) + + vars = self.vars + if self.combine_groups: + vars = vars.repeat(1, self.groups, 1) + + if produce_targets: + result["targets"] = ( + x.view(bsz * tsz * self.groups, -1) + .argmax(dim=-1) + .view(bsz, tsz, self.groups) + .detach() + ) + + x = x.unsqueeze(-1) * vars + x = x.view(bsz * tsz, self.groups, self.num_vars, -1) + x = x.sum(-2) + x = x.view(bsz, tsz, -1) + + if not self.time_first: + x = x.transpose(1, 2) # BTC -> BCT + + result["x"] = x + + return result diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/layer_norm.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/layer_norm.py new file mode 100644 index 000000000..29d532399 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/layer_norm.py @@ -0,0 +1,67 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +TORCHSCRIPT = False + + +try: + from apex.normalization import FusedLayerNorm as _FusedLayerNorm + + has_fused_layernorm = True + + class FusedLayerNorm(_FusedLayerNorm): + @torch.jit.unused + def forward(self, x): + if not x.is_cuda: + return super().forward(x) + else: + with torch.cuda.device(x.device): + return super().forward(x) + + +except ImportError: + has_fused_layernorm = False + + +def LayerNorm(normalized_shape, eps=1e-5, elementwise_affine=True, export=False): + if torch.jit.is_scripting() or TORCHSCRIPT: + export = True + if not export and torch.cuda.is_available() and has_fused_layernorm: + return FusedLayerNorm(normalized_shape, eps, elementwise_affine) + return torch.nn.LayerNorm(normalized_shape, eps, elementwise_affine) + + +class Fp32LayerNorm(nn.LayerNorm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def forward(self, input): + output = F.layer_norm( + input.float(), + self.normalized_shape, + self.weight.float() if self.weight is not None else None, + self.bias.float() if self.bias is not None else None, + self.eps, + ) + return output.type_as(input) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/multihead_attention.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/multihead_attention.py new file mode 100644 index 000000000..600d2b00a --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/multihead_attention.py @@ -0,0 +1,558 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +from typing import Dict, Optional, Tuple + +import torch +import torch.nn.functional as F +from torch import Tensor, nn +from torch.nn import Parameter + +from common.fairseq import utils +from common.fairseq.incremental_decoding_utils import with_incremental_state +from .fairseq_dropout import FairseqDropout +from .quant_noise import quant_noise + +class RotaryEmbedding(nn.Module): + def __init__(self, dim): + super().__init__() + inv_freq = 1. / (10000 ** (torch.arange(0, dim, 2).float() / dim)) + self.register_buffer('inv_freq', inv_freq) + self.seq_len_cached = None + self.cos_cached = None + self.sin_cached = None + + def forward(self, x, seq_dim=0): + seq_len = x.shape[seq_dim] + if seq_len != self.seq_len_cached: + self.seq_len_cached = seq_len + t = torch.arange(x.shape[seq_dim], device=x.device).type_as(self.inv_freq) + freqs = torch.einsum('i,j->ij', t, self.inv_freq) + emb = torch.cat((freqs, freqs), dim=-1).to(x.device) + self.cos_cached = emb.cos()[:, None, :] + self.sin_cached = emb.sin()[:, None, :] + return self.cos_cached, self.sin_cached + +def rotate_half(x): + x1, x2 = x[..., :x.shape[-1] // 2], x[..., x.shape[-1] // 2:] + return torch.cat((-x2, x1), dim=x1.ndim - 1) + +@torch.jit.script +def apply_rotary_pos_emb(x, cos, sin): + return (x * cos) + (rotate_half(x) * sin) + +@with_incremental_state +class MultiheadAttention(nn.Module): + """Multi-headed attention. + + See "Attention Is All You Need" for more details. + """ + + def __init__( + self, + embed_dim, + num_heads, + kdim=None, + vdim=None, + dropout=0.0, + bias=True, + add_bias_kv=False, + add_zero_attn=False, + self_attention=False, + encoder_decoder_attention=False, + q_noise=0.0, + qn_block_size=8, + rotary_embeddings=False, + ): + super().__init__() + self.embed_dim = embed_dim + self.kdim = kdim if kdim is not None else embed_dim + self.vdim = vdim if vdim is not None else embed_dim + self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim + + self.num_heads = num_heads + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + + self.rotary_embeddings = rotary_embeddings + + if self.rotary_embeddings: + self.rotary_freq = RotaryEmbedding(embed_dim) + else: + self.rotary_freq = None + + self.head_dim = embed_dim // num_heads + assert ( + self.head_dim * num_heads == self.embed_dim + ), "embed_dim must be divisible by num_heads" + self.scaling = self.head_dim ** -0.5 + + self.self_attention = self_attention + self.encoder_decoder_attention = encoder_decoder_attention + + assert not self.self_attention or self.qkv_same_dim, ( + "Self-attention requires query, key and " "value to be of the same size" + ) + + self.k_proj = quant_noise( + nn.Linear(self.kdim, embed_dim, bias=bias), q_noise, qn_block_size + ) + self.v_proj = quant_noise( + nn.Linear(self.vdim, embed_dim, bias=bias), q_noise, qn_block_size + ) + self.q_proj = quant_noise( + nn.Linear(embed_dim, embed_dim, bias=bias), q_noise, qn_block_size + ) + + self.out_proj = quant_noise( + nn.Linear(embed_dim, embed_dim, bias=bias), q_noise, qn_block_size + ) + + if add_bias_kv: + self.bias_k = Parameter(torch.Tensor(1, 1, embed_dim)) + self.bias_v = Parameter(torch.Tensor(1, 1, embed_dim)) + else: + self.bias_k = self.bias_v = None + + self.add_zero_attn = add_zero_attn + + self.reset_parameters() + + self.onnx_trace = False + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + def reset_parameters(self): + if self.qkv_same_dim: + # Empirically observed the convergence to be much better with + # the scaled initialization + nn.init.xavier_uniform_(self.k_proj.weight, gain=1 / math.sqrt(2)) + nn.init.xavier_uniform_(self.v_proj.weight, gain=1 / math.sqrt(2)) + nn.init.xavier_uniform_(self.q_proj.weight, gain=1 / math.sqrt(2)) + else: + nn.init.xavier_uniform_(self.k_proj.weight) + nn.init.xavier_uniform_(self.v_proj.weight) + nn.init.xavier_uniform_(self.q_proj.weight) + + nn.init.xavier_uniform_(self.out_proj.weight) + if self.out_proj.bias is not None: + nn.init.constant_(self.out_proj.bias, 0.0) + if self.bias_k is not None: + nn.init.xavier_normal_(self.bias_k) + if self.bias_v is not None: + nn.init.xavier_normal_(self.bias_v) + + def forward( + self, + query, + key: Optional[Tensor], + value: Optional[Tensor], + key_padding_mask: Optional[Tensor] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + need_weights: bool = True, + static_kv: bool = False, + attn_mask: Optional[Tensor] = None, + before_softmax: bool = False, + need_head_weights: bool = False, + ) -> Tuple[Tensor, Optional[Tensor]]: + """Input shape: Time x Batch x Channel + + Args: + key_padding_mask (ByteTensor, optional): mask to exclude + keys that are pads, of shape `(batch, src_len)`, where + padding elements are indicated by 1s. + need_weights (bool, optional): return the attention weights, + averaged over heads (default: False). + attn_mask (ByteTensor, optional): typically used to + implement causal attention, where the mask prevents the + attention from looking forward in time (default: None). + before_softmax (bool, optional): return the raw attention + weights and values before the attention softmax. + need_head_weights (bool, optional): return the attention + weights for each head. Implies *need_weights*. Default: + return the average attention weights over all heads. + """ + if need_head_weights: + need_weights = True + + is_tpu = query.device.type == "xla" + + tgt_len, bsz, embed_dim = query.size() + src_len = tgt_len + assert embed_dim == self.embed_dim, f"query dim {embed_dim} != {self.embed_dim}" + assert list(query.size()) == [tgt_len, bsz, embed_dim] + if key is not None: + src_len, key_bsz, _ = key.size() + if not torch.jit.is_scripting(): + assert key_bsz == bsz + assert value is not None + assert src_len, bsz == value.shape[:2] + + if ( + not self.rotary_embeddings + and not self.onnx_trace + and not is_tpu # don't use PyTorch version on TPUs + and incremental_state is None + and not static_kv + # A workaround for quantization to work. Otherwise JIT compilation + # treats bias in linear module as method. + and not torch.jit.is_scripting() + ): + assert key is not None and value is not None + return F.multi_head_attention_forward( + query, + key, + value, + self.embed_dim, + self.num_heads, + torch.empty([0]), + torch.cat((self.q_proj.bias, self.k_proj.bias, self.v_proj.bias)), + self.bias_k, + self.bias_v, + self.add_zero_attn, + self.dropout_module.p, + self.out_proj.weight, + self.out_proj.bias, + self.training or self.dropout_module.apply_during_inference, + key_padding_mask, + need_weights, + attn_mask, + use_separate_proj_weight=True, + q_proj_weight=self.q_proj.weight, + k_proj_weight=self.k_proj.weight, + v_proj_weight=self.v_proj.weight, + ) + + if incremental_state is not None: + saved_state = self._get_input_buffer(incremental_state) + if saved_state is not None and "prev_key" in saved_state: + # previous time steps are cached - no need to recompute + # key and value if they are static + if static_kv: + assert self.encoder_decoder_attention and not self.self_attention + key = value = None + else: + saved_state = None + + if self.self_attention: + # seq_len, batch_size, dim + q = self.q_proj(query) + k = self.k_proj(query) + v = self.v_proj(query) + + if self.rotary_freq is not None: + cos, sin = self.rotary_freq(q) + q = apply_rotary_pos_emb(q, cos, sin) + k = apply_rotary_pos_emb(k, cos, sin) + + elif self.encoder_decoder_attention: + # encoder-decoder attention + q = self.q_proj(query) + if key is None: + assert value is None + k = v = None + else: + k = self.k_proj(key) + v = self.v_proj(key) + + else: + assert key is not None and value is not None + q = self.q_proj(query) + k = self.k_proj(key) + v = self.v_proj(value) + q *= self.scaling + + if self.bias_k is not None: + assert self.bias_v is not None + k = torch.cat([k, self.bias_k.repeat(1, bsz, 1)]) + v = torch.cat([v, self.bias_v.repeat(1, bsz, 1)]) + if attn_mask is not None: + attn_mask = torch.cat( + [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1 + ) + if key_padding_mask is not None: + key_padding_mask = torch.cat( + [ + key_padding_mask, + key_padding_mask.new_zeros(key_padding_mask.size(0), 1), + ], + dim=1, + ) + + q = ( + q.contiguous() + .view(tgt_len, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + if k is not None: + k = ( + k.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + if v is not None: + v = ( + v.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + + if saved_state is not None: + # saved states are stored with shape (bsz, num_heads, seq_len, head_dim) + if "prev_key" in saved_state: + _prev_key = saved_state["prev_key"] + assert _prev_key is not None + prev_key = _prev_key.view(bsz * self.num_heads, -1, self.head_dim) + if static_kv: + k = prev_key + else: + assert k is not None + k = torch.cat([prev_key, k], dim=1) + src_len = k.size(1) + if "prev_value" in saved_state: + _prev_value = saved_state["prev_value"] + assert _prev_value is not None + prev_value = _prev_value.view(bsz * self.num_heads, -1, self.head_dim) + if static_kv: + v = prev_value + else: + assert v is not None + v = torch.cat([prev_value, v], dim=1) + prev_key_padding_mask: Optional[Tensor] = None + if "prev_key_padding_mask" in saved_state: + prev_key_padding_mask = saved_state["prev_key_padding_mask"] + assert k is not None and v is not None + key_padding_mask = MultiheadAttention._append_prev_key_padding_mask( + key_padding_mask=key_padding_mask, + prev_key_padding_mask=prev_key_padding_mask, + batch_size=bsz, + src_len=k.size(1), + static_kv=static_kv, + ) + + saved_state["prev_key"] = k.view(bsz, self.num_heads, -1, self.head_dim) + saved_state["prev_value"] = v.view(bsz, self.num_heads, -1, self.head_dim) + saved_state["prev_key_padding_mask"] = key_padding_mask + # In this branch incremental_state is never None + assert incremental_state is not None + incremental_state = self._set_input_buffer(incremental_state, saved_state) + assert k is not None + assert k.size(1) == src_len + + # This is part of a workaround to get around fork/join parallelism + # not supporting Optional types. + if key_padding_mask is not None and key_padding_mask.dim() == 0: + key_padding_mask = None + + if key_padding_mask is not None: + assert key_padding_mask.size(0) == bsz + assert key_padding_mask.size(1) == src_len + + if self.add_zero_attn: + assert v is not None + src_len += 1 + k = torch.cat([k, k.new_zeros((k.size(0), 1) + k.size()[2:])], dim=1) + v = torch.cat([v, v.new_zeros((v.size(0), 1) + v.size()[2:])], dim=1) + if attn_mask is not None: + attn_mask = torch.cat( + [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1 + ) + if key_padding_mask is not None: + key_padding_mask = torch.cat( + [ + key_padding_mask, + torch.zeros(key_padding_mask.size(0), 1).type_as( + key_padding_mask + ), + ], + dim=1, + ) + + attn_weights = torch.bmm(q, k.transpose(1, 2)) + attn_weights = self.apply_sparse_mask(attn_weights, tgt_len, src_len, bsz) + + assert list(attn_weights.size()) == [bsz * self.num_heads, tgt_len, src_len] + + if attn_mask is not None: + attn_mask = attn_mask.unsqueeze(0) + if self.onnx_trace: + attn_mask = attn_mask.repeat(attn_weights.size(0), 1, 1) + attn_weights += attn_mask + + if key_padding_mask is not None: + # don't attend to padding symbols + attn_weights = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) + if not is_tpu: + attn_weights = attn_weights.masked_fill( + key_padding_mask.unsqueeze(1).unsqueeze(2).to(torch.bool), + float("-inf"), + ) + else: + attn_weights = attn_weights.transpose(0, 2) + attn_weights = attn_weights.masked_fill(key_padding_mask, float("-inf")) + attn_weights = attn_weights.transpose(0, 2) + attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len) + + if before_softmax: + return attn_weights, v + + attn_weights_float = utils.softmax( + attn_weights, dim=-1, onnx_trace=self.onnx_trace + ) + attn_weights = attn_weights_float.type_as(attn_weights) + attn_probs = self.dropout_module(attn_weights) + + assert v is not None + attn = torch.bmm(attn_probs, v) + assert list(attn.size()) == [bsz * self.num_heads, tgt_len, self.head_dim] + if self.onnx_trace and attn.size(1) == 1: + # when ONNX tracing a single decoder step (sequence length == 1) + # the transpose is a no-op copy before view, thus unnecessary + attn = attn.contiguous().view(tgt_len, bsz, embed_dim) + else: + attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim) + attn = self.out_proj(attn) + attn_weights: Optional[Tensor] = None + if need_weights: + attn_weights = attn_weights_float.view( + bsz, self.num_heads, tgt_len, src_len + ).transpose(1, 0) + if not need_head_weights: + # average attention weights over heads + attn_weights = attn_weights.mean(dim=0) + + return attn, attn_weights + + @staticmethod + def _append_prev_key_padding_mask( + key_padding_mask: Optional[Tensor], + prev_key_padding_mask: Optional[Tensor], + batch_size: int, + src_len: int, + static_kv: bool, + ) -> Optional[Tensor]: + # saved key padding masks have shape (bsz, seq_len) + if prev_key_padding_mask is not None and static_kv: + new_key_padding_mask = prev_key_padding_mask + elif prev_key_padding_mask is not None and key_padding_mask is not None: + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), key_padding_mask.float()], dim=1 + ) + # During incremental decoding, as the padding token enters and + # leaves the frame, there will be a time when prev or current + # is None + elif prev_key_padding_mask is not None: + if src_len > prev_key_padding_mask.size(1): + filler = torch.zeros( + (batch_size, src_len - prev_key_padding_mask.size(1)), + device=prev_key_padding_mask.device, + ) + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), filler.float()], dim=1 + ) + else: + new_key_padding_mask = prev_key_padding_mask.float() + elif key_padding_mask is not None: + if src_len > key_padding_mask.size(1): + filler = torch.zeros( + (batch_size, src_len - key_padding_mask.size(1)), + device=key_padding_mask.device, + ) + new_key_padding_mask = torch.cat( + [filler.float(), key_padding_mask.float()], dim=1 + ) + else: + new_key_padding_mask = key_padding_mask.float() + else: + new_key_padding_mask = prev_key_padding_mask + return new_key_padding_mask + + @torch.jit.export + def reorder_incremental_state( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + new_order: Tensor, + ): + """Reorder buffered internal state (for incremental generation).""" + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + for k in input_buffer.keys(): + input_buffer_k = input_buffer[k] + if input_buffer_k is not None: + if self.encoder_decoder_attention and input_buffer_k.size( + 0 + ) == new_order.size(0): + break + input_buffer[k] = input_buffer_k.index_select(0, new_order) + incremental_state = self._set_input_buffer(incremental_state, input_buffer) + return incremental_state + + def _get_input_buffer( + self, incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] + ) -> Dict[str, Optional[Tensor]]: + result = self.get_incremental_state(incremental_state, "attn_state") + if result is not None: + return result + else: + empty_result: Dict[str, Optional[Tensor]] = {} + return empty_result + + def _set_input_buffer( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + buffer: Dict[str, Optional[Tensor]], + ): + return self.set_incremental_state(incremental_state, "attn_state", buffer) + + def apply_sparse_mask(self, attn_weights, tgt_len: int, src_len: int, bsz: int): + return attn_weights + + def upgrade_state_dict_named(self, state_dict, name): + prefix = name + "." if name != "" else "" + items_to_add = {} + keys_to_remove = [] + for k in state_dict.keys(): + if k.endswith(prefix + "in_proj_weight"): + # in_proj_weight used to be q + k + v with same dimensions + dim = int(state_dict[k].shape[0] / 3) + items_to_add[prefix + "q_proj.weight"] = state_dict[k][:dim] + items_to_add[prefix + "k_proj.weight"] = state_dict[k][dim : 2 * dim] + items_to_add[prefix + "v_proj.weight"] = state_dict[k][2 * dim :] + + keys_to_remove.append(k) + + k_bias = prefix + "in_proj_bias" + if k_bias in state_dict.keys(): + dim = int(state_dict[k].shape[0] / 3) + items_to_add[prefix + "q_proj.bias"] = state_dict[k_bias][:dim] + items_to_add[prefix + "k_proj.bias"] = state_dict[k_bias][ + dim : 2 * dim + ] + items_to_add[prefix + "v_proj.bias"] = state_dict[k_bias][2 * dim :] + + keys_to_remove.append(prefix + "in_proj_bias") + + for k in keys_to_remove: + del state_dict[k] + + for key, value in items_to_add.items(): + state_dict[key] = value diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/quant_noise.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/quant_noise.py new file mode 100644 index 000000000..42065d4dd --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/quant_noise.py @@ -0,0 +1,121 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn + + +def quant_noise(module, p, block_size): + """ + Wraps modules and applies quantization noise to the weights for + subsequent quantization with Iterative Product Quantization as + described in "Training with Quantization Noise for Extreme Model Compression" + + Args: + - module: nn.Module + - p: amount of Quantization Noise + - block_size: size of the blocks for subsequent quantization with iPQ + + Remarks: + - Module weights must have the right sizes wrt the block size + - Only Linear, Embedding and Conv2d modules are supported for the moment + - For more detail on how to quantize by blocks with convolutional weights, + see "And the Bit Goes Down: Revisiting the Quantization of Neural Networks" + - We implement the simplest form of noise here as stated in the paper + which consists in randomly dropping blocks + """ + + # if no quantization noise, don't register hook + if p <= 0: + return module + + # supported modules + assert isinstance(module, (nn.Linear, nn.Embedding, nn.Conv2d)) + + # test whether module.weight has the right sizes wrt block_size + is_conv = module.weight.ndim == 4 + + # 2D matrix + if not is_conv: + assert ( + module.weight.size(1) % block_size == 0 + ), "Input features must be a multiple of block sizes" + + # 4D matrix + else: + # 1x1 convolutions + if module.kernel_size == (1, 1): + assert ( + module.in_channels % block_size == 0 + ), "Input channels must be a multiple of block sizes" + # regular convolutions + else: + k = module.kernel_size[0] * module.kernel_size[1] + assert k % block_size == 0, "Kernel size must be a multiple of block size" + + def _forward_pre_hook(mod, input): + # no noise for evaluation + if mod.training: + if not is_conv: + # gather weight and sizes + weight = mod.weight + in_features = weight.size(1) + out_features = weight.size(0) + + # split weight matrix into blocks and randomly drop selected blocks + mask = torch.zeros( + in_features // block_size * out_features, device=weight.device + ) + mask.bernoulli_(p) + mask = mask.repeat_interleave(block_size, -1).view(-1, in_features) + + else: + # gather weight and sizes + weight = mod.weight + in_channels = mod.in_channels + out_channels = mod.out_channels + + # split weight matrix into blocks and randomly drop selected blocks + if mod.kernel_size == (1, 1): + mask = torch.zeros( + int(in_channels // block_size * out_channels), + device=weight.device, + ) + mask.bernoulli_(p) + mask = mask.repeat_interleave(block_size, -1).view(-1, in_channels) + else: + mask = torch.zeros( + weight.size(0), weight.size(1), device=weight.device + ) + mask.bernoulli_(p) + mask = ( + mask.unsqueeze(2) + .unsqueeze(3) + .repeat(1, 1, mod.kernel_size[0], mod.kernel_size[1]) + ) + + # scale weights and apply mask + mask = mask.to( + torch.bool + ) # x.bool() is not currently supported in TorchScript + s = 1 / (1 - p) + mod.weight.data = s * weight.masked_fill(mask, 0) + + module.register_forward_pre_hook(_forward_pre_hook) + return module diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/same_pad.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/same_pad.py new file mode 100644 index 000000000..381312dda --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/same_pad.py @@ -0,0 +1,34 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from torch import nn + + +class SamePad(nn.Module): + def __init__(self, kernel_size, causal=False): + super().__init__() + if causal: + self.remove = kernel_size - 1 + else: + self.remove = 1 if kernel_size % 2 == 0 else 0 + + def forward(self, x): + if self.remove > 0: + x = x[:, :, : -self.remove] + return x diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/transpose_last.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/transpose_last.py new file mode 100644 index 000000000..53d196360 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/modules/transpose_last.py @@ -0,0 +1,34 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +transpose last 2 dimensions of the input +""" + +import torch.nn as nn + + +class TransposeLast(nn.Module): + def __init__(self, deconstruct_idx=None): + super().__init__() + self.deconstruct_idx = deconstruct_idx + + def forward(self, x): + if self.deconstruct_idx is not None: + x = x[self.deconstruct_idx] + return x.transpose(-2, -1) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/adam.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/adam.py new file mode 100644 index 000000000..8b9918caf --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/adam.py @@ -0,0 +1,211 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +from collections.abc import Collection + +import torch +import torch.distributed as dist +import torch.optim +from common.fairseq.optim.fp16_optimizer import FairseqOptimizer +from common.fairseq.optim.fused_adam import get_fused_adam_class + + +class FairseqAdam(FairseqOptimizer): + """Adam optimizer for fairseq. + + Important note: this optimizer corresponds to the "AdamW" variant of + Adam in its weight decay behavior. As such, it is most closely + analogous to torch.optim.AdamW from PyTorch. + """ + + def __init__(self, cfg, params): + super().__init__(cfg) + fused_adam_cls = get_fused_adam_class() + use_fused_adam = ( + not getattr(cfg, "use_old_adam", False) + and fused_adam_cls is not None + and torch.cuda.is_available() + ) + if use_fused_adam: + self._optimizer = fused_adam_cls(params, **self.optimizer_config) + else: + self._optimizer = Adam(params, **self.optimizer_config) + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.cfg.lr[0] + if isinstance(self.cfg.lr, Collection) + else self.cfg.lr, + "betas": eval(self.cfg.adam_betas) + if isinstance(self.cfg.adam_betas, str) + else self.cfg.adam_betas, + "eps": self.cfg.adam_eps, + "weight_decay": self.cfg.weight_decay, + } + + def average_params(self): + """Reduce Params is only used during BMUF distributed training.""" + state_dict = self.optimizer.state_dict() + total_gpus = float(dist.get_world_size()) + + for _, value in state_dict["state"].items(): + value["exp_avg"] /= total_gpus + value["exp_avg_sq"] /= total_gpus + dist.all_reduce(value["exp_avg"], op=dist.ReduceOp.SUM) + dist.all_reduce(value["exp_avg_sq"], op=dist.ReduceOp.SUM) + + +class Adam(torch.optim.Optimizer): + r"""Implements Adam algorithm. + + This implementation is modified from torch.optim.Adam based on: + `Fixed Weight Decay Regularization in Adam` + (see https://arxiv.org/abs/1711.05101) + + It has been proposed in `Adam: A Method for Stochastic Optimization`_. + + Args: + params (iterable): iterable of parameters to optimize or dicts defining + parameter groups + lr (float, optional): learning rate (default: 1e-3) + betas (Tuple[float, float], optional): coefficients used for computing + running averages of gradient and its square (default: (0.9, 0.999)) + eps (float, optional): term added to the denominator to improve + numerical stability (default: 1e-8) + weight_decay (float, optional): weight decay (L2 penalty) (default: 0) + amsgrad (boolean, optional): whether to use the AMSGrad variant of this + algorithm from the paper `On the Convergence of Adam and Beyond`_ + + .. _Adam\: A Method for Stochastic Optimization: + https://arxiv.org/abs/1412.6980 + .. _On the Convergence of Adam and Beyond: + https://openreview.net/forum?id=ryQu7f-RZ + """ + + def __init__( + self, + params, + lr=1e-3, + betas=(0.9, 0.999), + eps=1e-8, + weight_decay=0, + amsgrad=False, + ): + defaults = dict( + lr=lr, betas=betas, eps=eps, weight_decay=weight_decay, amsgrad=amsgrad + ) + super(Adam, self).__init__(params, defaults) + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + def step(self, closure=None): + """Performs a single optimization step. + + Args: + closure (callable, optional): A closure that reevaluates the model + and returns the loss. + """ + loss = None + if closure is not None: + loss = closure() + + for group in self.param_groups: + for p in group["params"]: + if p.grad is None: + continue + grad = p.grad.data + if grad.dtype in {torch.float16, torch.bfloat16}: + grad = grad.float() + if grad.is_sparse: + raise RuntimeError( + "Adam does not support sparse gradients, please consider SparseAdam instead" + ) + amsgrad = group.get("amsgrad", False) + + p_data_fp32 = p.data + if p.data.dtype in {torch.float16, torch.bfloat16}: + p_data_fp32 = p_data_fp32.float() + + state = self.state[p] + + # State initialization + if len(state) == 0: + state["step"] = 0 + # Exponential moving average of gradient values + state["exp_avg"] = torch.zeros_like(p_data_fp32) + # Exponential moving average of squared gradient values + state["exp_avg_sq"] = torch.zeros_like(p_data_fp32) + if amsgrad: + # Maintains max of all exp. moving avg. of sq. grad. values + state["max_exp_avg_sq"] = torch.zeros_like(p_data_fp32) + else: + state["exp_avg"] = state["exp_avg"].to(p_data_fp32) + state["exp_avg_sq"] = state["exp_avg_sq"].to(p_data_fp32) + if amsgrad: + state["max_exp_avg_sq"] = state["max_exp_avg_sq"].to( + p_data_fp32 + ) + + exp_avg, exp_avg_sq = state["exp_avg"], state["exp_avg_sq"] + if amsgrad: + max_exp_avg_sq = state["max_exp_avg_sq"] + beta1, beta2 = group["betas"] + + state["step"] += 1 + + # Decay the first and second moment running average coefficient + exp_avg.mul_(beta1).add_(grad, alpha=1 - beta1) + exp_avg_sq.mul_(beta2).addcmul_(grad, grad, value=1 - beta2) + if amsgrad: + # Maintains the maximum of all 2nd moment running avg. till now + torch.max(max_exp_avg_sq, exp_avg_sq, out=max_exp_avg_sq) + # Use the max. for normalizing running avg. of gradient + denom = max_exp_avg_sq.sqrt().add_(group["eps"]) + else: + denom = exp_avg_sq.sqrt().add_(group["eps"]) + + bias_correction1 = 1 - beta1 ** state["step"] + bias_correction2 = 1 - beta2 ** state["step"] + step_size = group["lr"] * math.sqrt(bias_correction2) / bias_correction1 + + if group["weight_decay"] != 0: + p_data_fp32.add_( + p_data_fp32, alpha=-group["weight_decay"] * group["lr"] + ) + + p_data_fp32.addcdiv_(exp_avg, denom, value=-step_size) + + if p.data.dtype in {torch.float16, torch.bfloat16}: + p.data.copy_(p_data_fp32) + + return loss diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/dynamic_loss_scaler.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/dynamic_loss_scaler.py new file mode 100644 index 000000000..bef688919 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/dynamic_loss_scaler.py @@ -0,0 +1,83 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +class DynamicLossScaler(object): + def __init__( + self, + init_scale=2.0**15, + scale_factor=2.0, + scale_window=2000, + tolerance=0.0, + threshold=None, + min_loss_scale=1e-4, + ): + self.loss_scale = init_scale + self.scale_factor = scale_factor + self.scale_window = scale_window + self.tolerance = tolerance + self.threshold = threshold + self._iter = 0 + self._last_overflow_iter = -1 + self._last_rescale_iter = -1 + self._overflows_since_rescale = 0 + self.min_loss_scale = min_loss_scale + + def scale(self, outputs): + return self.loss_scale * outputs + + def update(self): + if (self._iter - self._last_overflow_iter) % self.scale_window == 0: + self.loss_scale *= self.scale_factor + self._last_rescale_iter = self._iter + self._iter += 1 + + def _decrease_loss_scale(self): + self.loss_scale /= self.scale_factor + if self.threshold is not None: + self.loss_scale = max(self.loss_scale, self.threshold) + + def check_overflow(self, grad_norm): + # detect inf and nan + if grad_norm == float("inf") or grad_norm != grad_norm: + # overflow has occured + prev_scale = self.loss_scale + iter_since_rescale = self._iter - self._last_rescale_iter + + self._last_overflow_iter = self._iter + self._overflows_since_rescale += 1 + pct_overflow = self._overflows_since_rescale / float(iter_since_rescale) + if pct_overflow >= self.tolerance: + self._decrease_loss_scale() + self._last_rescale_iter = self._iter + self._overflows_since_rescale = 0 + + if self.loss_scale <= self.min_loss_scale: + # Use FloatingPointError as an uncommon error that parent + # functions can safely catch to stop training. + self.loss_scale = prev_scale + raise FloatingPointError( + ( + "Minimum loss scale reached ({}). Your loss is probably exploding. " + "Try lowering the learning rate, using gradient clipping or " + "increasing the batch size." + ).format(self.min_loss_scale) + ) + + self._iter += 1 + raise OverflowError("setting loss scale to: " + str(self.loss_scale)) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fp16_optimizer.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fp16_optimizer.py new file mode 100644 index 000000000..70a764918 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fp16_optimizer.py @@ -0,0 +1,525 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import warnings +from collections import defaultdict + +import torch + +from common.fairseq.optim.dynamic_loss_scaler import DynamicLossScaler + + +@torch.no_grad() +def clip_grad_norm_(params, max_norm, aggregate_norm_fn=None) -> torch.Tensor: + def grad_exists(p): + return p is not None and getattr(p, "grad", None) is not None + + if isinstance(params, torch.Tensor): + params = [params] + params = list(params) + grads = [ + p.grad.detach() for p in params if grad_exists(p) and not hasattr(p, "expert") + ] + expert_grads = [ + p.grad.detach() for p in params if grad_exists(p) and hasattr(p, "expert") + ] + + if len(grads) == 0: + if len(params) > 0: + return params[0].new_tensor(0.0) + else: + return torch.tensor(0.0) + + if len(grads) == 1: + total_norm = torch.norm(grads[0], p=2, dtype=torch.float32) + else: + # XXX Missing imports + if multi_tensor_l2norm_available: + total_norm = multi_tensor_total_norm(grads) + else: + if torch.cuda.is_available(): + warnings.warn( + "amp_C fused kernels unavailable, disabling multi_tensor_l2norm; " + "you may get better performance by installing NVIDIA's apex library" + ) + device = torch.cuda.current_device() + elif grads[0].device.type == "xla": + device = grads[0].device + else: + device = torch.device("cpu") + total_norm = torch.norm( + torch.stack( + [torch.norm(g, p=2, dtype=torch.float32).to(device) for g in grads] + ) + ) + + if aggregate_norm_fn is not None: + total_norm = aggregate_norm_fn(total_norm) + + if max_norm > 0: + max_norm = float(max_norm) + clip_coef = (max_norm / (total_norm + 1e-6)).clamp_(max=1) + for g in grads + expert_grads: + g.mul_(clip_coef) + return total_norm + + +class FairseqOptimizer(object): + def __init__(self, cfg): + super().__init__() + self.cfg = cfg + + @classmethod + def add_args(cls, parser): + """Add optimizer-specific arguments to the parser.""" + dc = getattr(cls, "__dataclass", None) + if dc is not None: + gen_parser_from_dataclass(parser, dc()) + + @property + def optimizer(self): + """Return a torch.optim.optimizer.Optimizer instance.""" + if not hasattr(self, "_optimizer"): + raise NotImplementedError + if not isinstance(self._optimizer, torch.optim.Optimizer): + raise ValueError("_optimizer must be an instance of torch.optim.Optimizer") + return self._optimizer + + @optimizer.setter + def optimizer(self, optimizer): + """Reset optimizer instance.""" + if not hasattr(self, "_optimizer"): + raise NotImplementedError + if not isinstance(self._optimizer, torch.optim.Optimizer): + raise ValueError("_optimizer must be an instance of torch.optim.Optimizer") + self._optimizer = optimizer + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + raise NotImplementedError + + @property + def params(self): + """Return an iterable of the parameters held by the optimizer.""" + for param_group in self.param_groups: + for p in param_group["params"]: + yield p + + @property + def param_groups(self): + return self.optimizer.param_groups + + def __getstate__(self): + return self._optimizer.__getstate__() + + def get_lr(self): + """Return the current learning rate.""" + return self.param_groups[0]["lr"] + + def set_lr(self, lr): + """Set the learning rate.""" + for param_group in self.param_groups: + param_group["lr"] = lr + + def state_dict(self): + """Return the optimizer's state dict.""" + return self.optimizer.state_dict() + + def load_state_dict(self, state_dict, optimizer_overrides=None): + """Load an optimizer state dict. + + In general we should prefer the configuration of the existing optimizer + instance (e.g., learning rate) over that found in the state_dict. This + allows us to resume training from a checkpoint using a new set of + optimizer args. + """ + self.optimizer.load_state_dict(state_dict) + + if optimizer_overrides is not None and len(optimizer_overrides) > 0: + # override learning rate, momentum, etc. with latest values + for group in self.param_groups: + group.update(optimizer_overrides) + + def backward(self, loss): + """Computes the sum of gradients of the given tensor w.r.t. graph leaves.""" + loss.backward() + + def all_reduce_grads(self, module): + """Manually all-reduce gradients (if required).""" + if hasattr(module, "all_reduce_grads"): + module.all_reduce_grads() + + def multiply_grads(self, c): + """Multiplies grads by a constant *c*.""" + for p in self.params: + if p.grad is not None: + if torch.is_tensor(c): + c = c.to(p.grad.device) + p.grad.data.mul_(c) + + def clip_grad_norm(self, max_norm, aggregate_norm_fn=None): + """Clips gradient norm.""" + return clip_grad_norm_(self.params, max_norm, aggregate_norm_fn) + + def step(self, closure=None, scale=1.0, groups=None): + """Performs a single optimization step.""" + if self.supports_step_with_scale: + if self.supports_groups: + self.optimizer.step(closure, scale=scale, groups=groups) + else: + self.optimizer.step(closure, scale=scale) + else: + if scale != 1.0: + self.multiply_grads(1.0 / scale) + if self.supports_groups: + self.optimizer.step(closure, groups=groups) + else: + self.optimizer.step(closure) + + def zero_grad(self): + """Clears the gradients of all optimized parameters.""" + for p in self.params: + p.grad = None + self.optimizer.zero_grad() + + @property + def supports_memory_efficient_fp16(self): + if hasattr(self.optimizer, "supports_memory_efficient_fp16"): + return self.optimizer.supports_memory_efficient_fp16 + return False + + @property + def supports_step_with_scale(self): + if hasattr(self.optimizer, "supports_step_with_scale"): + return self.optimizer.supports_step_with_scale + return False + + @property + def supports_groups(self): + if hasattr(self.optimizer, "supports_groups"): + return self.optimizer.supports_groups + return False + + @property + def supports_flat_params(self): + """ + Whether the optimizer supports collapsing of the model + parameters/gradients into a single contiguous Tensor. + """ + if hasattr(self.optimizer, "supports_flat_params"): + return self.optimizer.supports_flat_params + return False + + def broadcast_global_state_dict(self, state_dict): + """ + Broadcasts a global state dict to all ranks. + Useful for optimizers that shard state between ranks. + """ + if hasattr(self.optimizer, "broadcast_global_state_dict"): + return self.optimizer.broadcast_global_state_dict(state_dict) + else: + return state_dict + + +class _FP16OptimizerMixin(object): + def __init__(self, *args, **kwargs): + # forward __init__ call to the next class in mro(method resolution order) + super().__init__(*args, **kwargs) + self._multiply_factor = 1.0 + + @property + def has_flat_params(self): + return torch.is_tensor(self.fp32_params) or ( + isinstance(self.fp32_params, dict) + and all(torch.is_tensor(t) for t in self.fp32_params.values()) + ) + + @classmethod + def build_fp32_params(cls, args, params, flatten=True): + # create FP32 copy of parameters and grads + if flatten: + is_pipeline_parallel = getattr( + args, "pipeline_model_parallel", False + ) and getattr(args, "distributed_no_spawn", False) + total_param_size = sum(p.data.numel() for p in params) + devices = [torch.cuda.current_device()] + if is_pipeline_parallel: + devices = list(set(args.pipeline_devices)) + fp32_params = {} + for device in devices: + if is_pipeline_parallel: + device_param_size = sum( + p.data.numel() for p in params if p.device.index == device + ) + device_params = [p for p in params if p.device.index == device] + else: + device_param_size = total_param_size + device_params = params + fp32_params[device] = ( + device_params[0].new(0).float().new(device_param_size) + ) + offset = 0 + for p in device_params: + numel = p.data.numel() + fp32_params[device][offset : offset + numel].copy_(p.data.view(-1)) + offset += numel + fp32_params[device] = torch.nn.Parameter(fp32_params[device]) + fp32_params[device].grad = fp32_params[device].data.new( + device_param_size + ) + return fp32_params + else: + fp32_params = [] + for p in params: + p32 = torch.nn.Parameter(p.data.float()) + if hasattr(p, 'expert'): + p32.expert = True + p32.grad = torch.zeros_like(p32.data) + if hasattr(p, "param_group"): + p32.param_group = p.param_group + fp32_params.append(p32) + return fp32_params + + def state_dict(self): + """Return the optimizer's state dict.""" + state_dict = self.fp32_optimizer.state_dict() + if self.scaler is not None: + state_dict["loss_scale"] = self.scaler.loss_scale + return state_dict + + def load_state_dict(self, state_dict, optimizer_overrides=None): + """Load an optimizer state dict. + + In general we should prefer the configuration of the existing optimizer + instance (e.g., learning rate) over that found in the state_dict. This + allows us to resume training from a checkpoint using a new set of + optimizer args. + """ + if "loss_scale" in state_dict and self.scaler is not None: + self.scaler.loss_scale = state_dict["loss_scale"] + self.fp32_optimizer.load_state_dict(state_dict, optimizer_overrides) + + def backward(self, loss): + """Computes the sum of gradients of the given tensor w.r.t. graph leaves. + + Compared to :func:`fairseq.optim.FairseqOptimizer.backward`, this + function additionally dynamically scales the loss to avoid gradient + underflow. + """ + if self.scaler is not None: + loss = self.scaler.scale(loss) + loss.backward() + self._needs_sync = True + + def _sync_fp16_grads_to_fp32(self): + if self._needs_sync: + # copy FP16 grads to FP32 + if self.has_flat_params: + devices = list(self.fp32_params.keys()) + device_params_dict = defaultdict(list) + for p in self.fp16_params: + if p.requires_grad: + device_params_dict[p.device.index].append(p) + for device in devices: + device_params = device_params_dict[device] + offset = 0 + for p in device_params: + grad_data = ( + p.grad.data + if p.grad is not None + else p.data.new_zeros(p.data.shape) + ) + numel = grad_data.numel() + self.fp32_params[device].grad.data[ + offset : offset + numel + ].copy_(grad_data.view(-1)) + offset += numel + else: + for p, p32 in zip(self.fp16_params, self.fp32_params): + if not p.requires_grad: + continue + if p.grad is not None: + if p32.grad is None: + p32.grad = p.grad.data.float() + else: + p32.grad.data.copy_(p.grad.data) + else: + p32.grad = torch.zeros_like(p.data, dtype=torch.float) + + self._needs_sync = False + + def _sync_fp32_params_to_fp16(self): + # copy FP32 params back into FP16 model + if self.has_flat_params: + devices = list(self.fp32_params.keys()) + device_params_dict = defaultdict(list) + for p in self.fp16_params: + device_params_dict[p.device.index].append(p) + for device in devices: + device_params = device_params_dict[device] + offset = 0 + for p in device_params: + numel = p.data.numel() + p.data.copy_( + self.fp32_params[device] + .data[offset : offset + numel] + .view_as(p.data) + ) + offset += numel + else: + for p, p32 in zip(self.fp16_params, self.fp32_params): + if not p.requires_grad: + continue + p.data.copy_(p32.data) + + def _unscale_grads(self): + self._sync_fp16_grads_to_fp32() + if ( + # Skip the multiplication if it's a no-op (i.e., if _multiply_factor + # is 1.0). At the same time, we want to avoid the device-to-host + # transfer by comparing it to 1.0. Since _multiply_factor starts as + # a Python float, we roughly assume that if it's a tensor then it's + # probably not =1.0 anymore and we do the multiplication. Otherwise + # we can safely check the value without a D2H transfer. + torch.is_tensor(self._multiply_factor) + or self._multiply_factor != 1.0 + ): + self.fp32_optimizer.multiply_grads(self._multiply_factor) + self._multiply_factor = 1.0 + + def multiply_grads(self, c): + """Multiplies grads by a constant ``c``.""" + self._multiply_factor *= c + + def clip_grad_norm(self, max_norm, aggregate_norm_fn=None): + """Clips gradient norm and updates dynamic loss scaler.""" + self._sync_fp16_grads_to_fp32() + + grad_norm = self._multiply_factor * self.fp32_optimizer.clip_grad_norm( + 0, aggregate_norm_fn + ) + + if self.scaler is not None: + if grad_norm > max_norm > 0.0: + self._multiply_factor *= max_norm / grad_norm + + self.scaler.check_overflow(grad_norm) + elif max_norm > 0.0: + clip_coef = (max_norm / (grad_norm + 1e-6)).clamp_(max=1) + self._multiply_factor *= clip_coef + + return grad_norm + + def step(self, closure=None, groups=None): + """Performs a single optimization step.""" + self._sync_fp16_grads_to_fp32() + + if getattr(self, "supports_step_with_scale", False): + self.fp32_optimizer.step(closure, scale=(1.0 / self._multiply_factor), groups=groups) + else: + self._unscale_grads() + self.fp32_optimizer.step(closure, groups=groups) + + if self.scaler is not None: + self.scaler.update() + + self._sync_fp32_params_to_fp16() + + def zero_grad(self): + """Clears the gradients of all optimized parameters.""" + for p in self.fp16_params: + p.grad = None + if self.has_flat_params: + if torch.is_tensor(self.fp32_params): + self.fp32_params.grad.zero_() + elif isinstance(self.fp32_params, dict): + for fp32_params in self.fp32_params.values(): + fp32_params.grad.zero_() + else: + raise RuntimeError("self.fp32_params must be a tensor or dict") + else: + for p32 in self.fp32_params: + if p32.grad is not None: + p32.grad.zero_() + self._needs_sync = False + + if self.scaler is not None: + self._multiply_factor = 1.0 / float(self.scaler.loss_scale) + + +class FP16Optimizer(_FP16OptimizerMixin, FairseqOptimizer): + """ + Wrap an *optimizer* to support FP16 (mixed precision) training. + """ + + def __init__(self, cfg, params, fp32_optimizer, fp32_params, **kwargs): + super().__init__(cfg.optimizer) + self.fp16_params = params + self.fp32_optimizer = fp32_optimizer + self.fp32_params = fp32_params + + scale_window = int(2 ** 14 / cfg.world_size / cfg.update_freq) + + if not (cfg.bf16 and cfg.bf16_disable_loss_scaler): + self.scaler = DynamicLossScaler( + init_scale=cfg.fp16_init_scale, + scale_window=scale_window, + tolerance=0.0, + threshold=None, + min_loss_scale=cfg.min_loss_scale, + ) + else: + print('Disabled loss scaler.') + # disable loss scaling for bfloat16 + self.scaler = None + + @property + def optimizer(self): + return self.fp32_optimizer.optimizer + + @optimizer.setter + def optimizer(self, optimizer): + self.fp32_optimizer.optimizer = optimizer + + @property + def lr_scheduler(self): + return getattr(self.fp32_optimizer, "lr_scheduler", None) + + @property + def optimizer_config(self): + return self.fp32_optimizer.optimizer_config + + def get_lr(self): + return self.fp32_optimizer.get_lr() + + def set_lr(self, lr): + self.fp32_optimizer.set_lr(lr) + + def all_reduce_grads(self, module): + self.fp32_optimizer.all_reduce_grads(module) + + @property + def supports_flat_params(self): + return self.fp32_optimizer.supports_flat_params diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fused_adam.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fused_adam.py new file mode 100644 index 000000000..c8686e126 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fused_adam.py @@ -0,0 +1,362 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import types + +import torch + + +def get_fused_adam_class(): + """ + Look for the FusedAdam optimizer from apex. We first try to load the + "contrib" interface, which is a bit faster than the main interface, + but is technically deprecated. + """ + try: + # The "deprecated" interface in recent versions of apex is a bit + # faster than the main interface, since we don't use the apex + # optimizer. This can be installed by passing the + # `--deprecated_fused_adam` option when building apex. + global fused_adam_cuda + import importlib + + fused_adam_cuda = importlib.import_module("fused_adam_cuda") + return FusedAdamV1 + except ImportError: + try: + # fallback to the newer interface + from apex.optimizers import FusedAdam as _FusedAdam # noqa + from apex.multi_tensor_apply import multi_tensor_applier + + if multi_tensor_applier.available: + return FusedAdamV2 + except ImportError: + pass + return None + + +class FusedAdamV1(torch.optim.Optimizer): + """ + Implements Adam algorithm. Currently GPU-only. Requires Apex to be installed via + ``python setup.py install --cuda_ext --cpp_ext``. + + It has been proposed in `Adam: A Method for Stochastic Optimization`_. + + Compared to the original version in Apex, the fairseq version casts grads + and params to FP32 internally to support ``--memory-efficient-fp16``. + + Args: + params (iterable): iterable of parameters to optimize or dicts defining + parameter groups. + lr (float, optional): learning rate. (default: 1e-3) + betas (Tuple[float, float], optional): coefficients used for computing + running averages of gradient and its square. (default: (0.9, 0.999)) + eps (float, optional): term added to the denominator to improve + numerical stability. (default: 1e-8) + weight_decay (float, optional): weight decay (L2 penalty) (default: 0) + amsgrad (boolean, optional): whether to use the AMSGrad variant of this + algorithm from the paper `On the Convergence of Adam and Beyond`_ + (default: False) NOT SUPPORTED in FusedAdam! + eps_inside_sqrt (boolean, optional): in the 'update parameters' step, + adds eps to the bias-corrected second moment estimate before + evaluating square root instead of adding it to the square root of + second moment estimate as in the original paper. (default: False) + .. _Adam: A Method for Stochastic Optimization: + https://arxiv.org/abs/1412.6980 + .. _On the Convergence of Adam and Beyond: + https://openreview.net/forum?id=ryQu7f-RZ + """ + + def __init__( + self, + params, + lr=1e-3, + bias_correction=True, + betas=(0.9, 0.999), + eps=1e-8, + eps_inside_sqrt=False, + weight_decay=0.0, + max_grad_norm=0.0, + amsgrad=False, + ): + global fused_adam_cuda + import importlib + + fused_adam_cuda = importlib.import_module("fused_adam_cuda") + + if amsgrad: + raise RuntimeError("FusedAdam does not support the AMSGrad variant.") + defaults = { + "lr": lr, + "bias_correction": bias_correction, + "betas": betas, + "eps": eps, + "weight_decay": weight_decay, + "max_grad_norm": max_grad_norm, + } + super().__init__(params, defaults) + self.eps_mode = 0 if eps_inside_sqrt else 1 + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + @property + def supports_step_with_scale(self): + return True + + def step(self, closure=None, grads=None, scale=1.0, grad_norms=None): + """Performs a single optimization step. + Args: + closure (callable, optional): A closure that reevaluates the model + and returns the loss. + grads (list of tensors, optional): weight gradient to use for the + optimizer update. If gradients have type torch.half, parameters + are expected to be in type torch.float. (default: None) + output params (list of tensors, optional): A reduced precision copy + of the updated weights written out in addition to the regular + updated weights. Have to be of same type as gradients. (default: None) + scale (float, optional): factor to divide gradient tensor values + by before applying to weights. (default: 1) + """ + loss = None + if closure is not None: + loss = closure() + + if grads is None: + grads_group = [None] * len(self.param_groups) + # backward compatibility + # assuming a list/generator of parameter means single group + elif isinstance(grads, types.GeneratorType): + grads_group = [grads] + elif type(grads[0]) != list: + grads_group = [grads] + else: + grads_group = grads + + if grad_norms is None: + grad_norms = [None] * len(self.param_groups) + + for group, grads_this_group, grad_norm in zip( + self.param_groups, grads_group, grad_norms + ): + if grads_this_group is None: + grads_this_group = [None] * len(group["params"]) + + # compute combined scale factor for this group + combined_scale = scale + if group.get("max_grad_norm", 0) > 0: + # norm is in fact norm*scale + clip = ((grad_norm / scale) + 1e-6) / group["max_grad_norm"] + if clip > 1: + combined_scale = clip * scale + + bias_correction = 1 if group.get("bias_correction", 1) else 0 + + for p, grad in zip(group["params"], grads_this_group): + # note: p.grad should not ever be set for correct + # operation of mixed precision optimizer that sometimes + # sends None gradients + if p.grad is None and grad is None: + continue + if grad is None: + grad = p.grad.data + if grad.is_sparse: + raise RuntimeError( + "FusedAdam does not support sparse gradients, " + "please consider SparseAdam instead" + ) + + p_data_fp32 = p.data.float() + + state = self.state[p] + + # State initialization + if len(state) == 0: + state["step"] = 0 + # Exponential moving average of gradient values + state["exp_avg"] = torch.zeros_like(p_data_fp32) + # Exponential moving average of squared gradient values + state["exp_avg_sq"] = torch.zeros_like(p_data_fp32) + else: + state["exp_avg"] = state["exp_avg"].to(p_data_fp32) + state["exp_avg_sq"] = state["exp_avg_sq"].to(p_data_fp32) + + exp_avg = state["exp_avg"] + exp_avg_sq = state["exp_avg_sq"] + beta1, beta2 = group["betas"] + + state["step"] += 1 + + out_p = p.data + with torch.cuda.device(p.device): + fused_adam_cuda.adam( + p_data_fp32, + out_p, + exp_avg, + exp_avg_sq, + grad, + group["lr"], + beta1, + beta2, + group["eps"], + combined_scale, + state["step"], + self.eps_mode, + bias_correction, + group["weight_decay"], + ) + + return loss + + +try: + from apex.optimizers import FusedAdam + from apex.multi_tensor_apply import multi_tensor_applier + + class FusedAdamV2(FusedAdam): + """ + Compared to the original version in Apex, the fairseq version casts grads + and params to FP32 internally to support ``--memory-efficient-fp16``. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not hasattr(self, "multi_tensor_adam"): + raise Exception( + "Apex installation is outdated. Please install an updated version of apex." + ) + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + def step( + self, + closure=None, + grads=None, + output_params=None, + scale=None, + grad_norms=None, + ): + """Performs a single optimization step.""" + loss = None + if closure is not None: + loss = closure() + + for group in self.param_groups: + bias_correction = 1 if group["bias_correction"] else 0 + beta1, beta2 = group["betas"] + + # assume same step across group now to simplify things + # per parameter step can be easily support by making it tensor, or pass list into kernel + if "step" in group: + group["step"] += 1 + else: + group["step"] = 1 + + # create lists for multi-tensor apply + g_16, p_16, orig_p_16, m_16, v_16 = [], [], [], [], [] + g_32, p_32, m_32, v_32 = [], [], [], [] + + for p in group["params"]: + if p.grad is None: + continue + if p.grad.data.is_sparse: + raise RuntimeError( + "FusedAdam does not support sparse gradients, " + "please consider SparseAdam instead" + ) + + state = self.state[p] + # State initialization + if len(state) == 0: + # Exponential moving average of gradient values + state["exp_avg"] = torch.zeros_like(p.data, dtype=torch.float) + # Exponential moving average of squared gradient values + state["exp_avg_sq"] = torch.zeros_like( + p.data, dtype=torch.float + ) + else: + state["exp_avg"] = state["exp_avg"].to( + device=p.data.device, dtype=torch.float + ) + state["exp_avg_sq"] = state["exp_avg_sq"].to( + device=p.data.device, dtype=torch.float + ) + + if p.dtype == torch.float16: + g_16.append(p.grad.data.float()) + p_16.append(p.data.float()) + orig_p_16.append(p.data) + m_16.append(state["exp_avg"]) + v_16.append(state["exp_avg_sq"]) + elif p.dtype == torch.float32: + g_32.append(p.grad.data) + p_32.append(p.data) + m_32.append(state["exp_avg"]) + v_32.append(state["exp_avg_sq"]) + else: + raise RuntimeError("FusedAdam only support fp16 and fp32.") + + with torch.cuda.device(p.device): + if len(g_16) > 0: + multi_tensor_applier( + self.multi_tensor_adam, + self._dummy_overflow_buf, + [g_16, p_16, m_16, v_16], + group["lr"], + beta1, + beta2, + group["eps"], + group["step"], + self.adam_w_mode, + bias_correction, + group["weight_decay"], + ) + for orig_p, p in zip(orig_p_16, p_16): + orig_p.copy_(p.data) + if len(g_32) > 0: + multi_tensor_applier( + self.multi_tensor_adam, + self._dummy_overflow_buf, + [g_32, p_32, m_32, v_32], + group["lr"], + beta1, + beta2, + group["eps"], + group["step"], + self.adam_w_mode, + bias_correction, + group["weight_decay"], + ) + + return loss + + +except ImportError: + pass diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fused_lamb.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fused_lamb.py new file mode 100644 index 000000000..ca2d8b851 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/optim/fused_lamb.py @@ -0,0 +1,71 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from dataclasses import dataclass, field +from typing import Any, List + +from collections.abc import Collection +from fairseq.dataclass import FairseqDataclass +from fairseq.optim import FairseqOptimizer, register_optimizer +from omegaconf import II, OmegaConf + +@dataclass +class FairseqLambConfig(FairseqDataclass): + lamb_betas: Any = field( + default=(0.9, 0.999), metadata={"help": "betas for lamb optimizer"} + ) + lamb_eps: float = field( + default=1e-8, metadata={"help": "epsilon for lamb optimizer"} + ) + weight_decay: float = field(default=0.0, metadata={"help": "weight decay"}) + lr: List[float] = II("optimization.lr") + + +@register_optimizer("lamb", dataclass=FairseqLambConfig) +class FairseqLAMB(FairseqOptimizer): + """LAMB optimizer.""" + + def __init__(self, cfg: FairseqLambConfig, params): + super().__init__(cfg) + try: + from apex.optimizers import FusedLAMB + + self._optimizer = FusedLAMB(params, **self.optimizer_config) + except ImportError: + raise ImportError("Please install apex to use LAMB optimizer") + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.cfg.lr[0] if isinstance(self.cfg.lr, Collection) else self.cfg.lr, + "betas": eval(self.cfg.lamb_betas) if isinstance(self.cfg.lamb_betas, str) + else OmegaConf.to_container(self.cfg.lamb_betas), + "eps": self.cfg.lamb_eps, + "weight_decay": self.cfg.weight_decay, + } + + @property + def supports_flat_params(self): + return False diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/tokenizer.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/tokenizer.py new file mode 100644 index 000000000..3fcb42b10 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/tokenizer.py @@ -0,0 +1,29 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re + + +SPACE_NORMALIZER = re.compile(r"\s+") + + +def tokenize_line(line): + line = SPACE_NORMALIZER.sub(" ", line) + line = line.strip() + return line.split() diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/utils.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/utils.py new file mode 100644 index 000000000..f1fc0903f --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq/utils.py @@ -0,0 +1,119 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import warnings +from typing import Callable, List + +import torch +import torch.nn.functional as F + + +MANIFOLD_PATH_SEP = "|" + + +def split_paths(paths: str, separator=os.pathsep) -> List[str]: + return ( + paths.split(separator) if "://" not in paths else paths.split(MANIFOLD_PATH_SEP) + ) + + +def get_activation_fn(activation: str) -> Callable: + """Returns the activation function corresponding to `activation`""" + from .modules import gelu, gelu_accurate + + if activation == "relu": + return F.relu + elif activation == "gelu": + return gelu + elif activation == "gelu_fast": + warnings.warn( + "--activation-fn=gelu_fast has been renamed to gelu_accurate" + ) + return gelu_accurate + elif activation == "gelu_accurate": + return gelu_accurate + elif activation == "tanh": + return torch.tanh + elif activation == "linear": + return lambda x: x + else: + raise RuntimeError("--activation-fn {} not supported".format(activation)) + + +def index_put(tensor, indices, value): + tensor[indices] = value + return tensor + + +def item(tensor): + if hasattr(tensor, "item"): + return tensor.item() + if hasattr(tensor, "__getitem__"): + return tensor[0] + return tensor + + +def softmax(x, dim: int, onnx_trace: bool = False): + if onnx_trace: + return F.softmax(x.float(), dim=dim) + else: + return F.softmax(x, dim=dim, dtype=torch.float32) + + +def multiply_grads(optimizer, c): + """Multiplies grads by a constant *c*.""" + for param_group in optimizer.param_groups: + for p in param_group["params"]: + if p.grad is not None: + if torch.is_tensor(c): + c = c.to(p.grad.device) + p.grad.data.mul_(c) + + +def apply_to_sample(f, sample): + if hasattr(sample, "__len__") and len(sample) == 0: + return {} + + def _apply(x): + if torch.is_tensor(x): + return f(x) + elif isinstance(x, dict): + return {key: _apply(value) for key, value in x.items()} + elif isinstance(x, list): + return [_apply(x) for x in x] + elif isinstance(x, tuple): + return tuple(_apply(x) for x in x) + elif isinstance(x, set): + return {_apply(x) for x in x} + else: + return x + + return _apply(sample) + + +def move_to_cuda(sample, device=None): + device = device or torch.cuda.current_device() + + def _move_to_cuda(tensor): + # non_blocking is ignored if tensor is not pinned, so we can always set + # to True (see github.com/PyTorchLightning/pytorch-lightning/issues/620) + return tensor.to(device=device, non_blocking=True) + + return apply_to_sample(_move_to_cuda, sample) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/fairseq_fake_modules.py b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq_fake_modules.py new file mode 100644 index 000000000..f91a4c88b --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/fairseq_fake_modules.py @@ -0,0 +1,33 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +'''Fake fairseq.* modules allowing to torch.load fairseq checkpoints.''' + +import sys + + +class Dummy: + pass + + +class FakeModule: + def __init__(self, classes=["AverageMeter", "TimeMeter", "StopwatchMeter"]): + [setattr(self, cls, Dummy) for cls in classes] + + +sys.modules["fairseq"] = Dummy() +sys.modules["fairseq.data"] = Dummy() +sys.modules["fairseq.data.dictionary"] = FakeModule(["Dictionary"]) +sys.modules["fairseq.logging.meters"] = FakeModule() +sys.modules["fairseq.meters"] = FakeModule() diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/features.py b/PyTorch/SpeechRecognition/wav2vec2/common/features.py new file mode 100644 index 000000000..be89d2598 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/features.py @@ -0,0 +1,316 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +import random + +import librosa +import torch +import torch.nn as nn + + +class BaseFeatures(nn.Module): + """Base class for GPU accelerated audio preprocessing.""" + __constants__ = ["pad_align", "pad_to_max_duration", "max_len"] + + def __init__(self, pad_align, pad_to_max_duration, max_duration, + sample_rate, window_size, window_stride, spec_augment=None, + cutout_augment=None): + super(BaseFeatures, self).__init__() + + self.pad_align = pad_align + self.pad_to_max_duration = pad_to_max_duration + self.win_length = int(sample_rate * window_size) # frame size + self.hop_length = int(sample_rate * window_stride) + + # Calculate maximum sequence length (# frames) + if pad_to_max_duration: + self.max_len = 1 + math.ceil( + (max_duration * sample_rate - self.win_length) / self.hop_length + ) + + if spec_augment is not None: + self.spec_augment = SpecAugment(**spec_augment) + else: + self.spec_augment = None + + if cutout_augment is not None: + self.cutout_augment = CutoutAugment(**cutout_augment) + else: + self.cutout_augment = None + + @torch.no_grad() + def calculate_features(self, audio, audio_lens): + return audio, audio_lens + + def __call__(self, audio, audio_lens): + dtype = audio.dtype + audio = audio.float() + feat, feat_lens = self.calculate_features(audio, audio_lens) + feat = self.apply_padding(feat) + + if self.cutout_augment is not None: + feat = self.cutout_augment(feat) + + if self.spec_augment is not None: + feat = self.spec_augment(feat) + + feat = feat.to(dtype) + return feat, feat_lens + + def apply_padding(self, x): + if self.pad_to_max_duration: + x_size = max(x.size(-1), self.max_len) + else: + x_size = x.size(-1) + + if self.pad_align > 0: + pad_amt = x_size % self.pad_align + else: + pad_amt = 0 + + padded_len = x_size + (self.pad_align - pad_amt if pad_amt > 0 else 0) + return nn.functional.pad(x, (0, padded_len - x.size(-1))) + + +class SpecAugment(nn.Module): + """Spec augment. refer to https://arxiv.org/abs/1904.08779 + """ + def __init__(self, freq_masks=0, min_freq=0, max_freq=10, time_masks=0, + min_time=0, max_time=10): + super(SpecAugment, self).__init__() + assert 0 <= min_freq <= max_freq + assert 0 <= min_time <= max_time + + self.freq_masks = freq_masks + self.min_freq = min_freq + self.max_freq = max_freq + + self.time_masks = time_masks + self.min_time = min_time + self.max_time = max_time + + @torch.no_grad() + def forward(self, x): + sh = x.shape + mask = torch.zeros(x.shape, dtype=torch.bool, device=x.device) + + for idx in range(sh[0]): + for _ in range(self.freq_masks): + w = torch.randint(self.min_freq, self.max_freq + 1, size=(1,)).item() + f0 = torch.randint(0, max(1, sh[1] - w), size=(1,)) + mask[idx, f0:f0+w] = 1 + + for _ in range(self.time_masks): + w = torch.randint(self.min_time, self.max_time + 1, size=(1,)).item() + t0 = torch.randint(0, max(1, sh[2] - w), size=(1,)) + mask[idx, :, t0:t0+w] = 1 + + return x.masked_fill(mask, 0) + + +class CutoutAugment(nn.Module): + """Cutout. refer to https://arxiv.org/pdf/1708.04552.pdf + """ + def __init__(self, masks=0, min_freq=20, max_freq=20, min_time=5, max_time=5): + super(CutoutAugment, self).__init__() + assert 0 <= min_freq <= max_freq + assert 0 <= min_time <= max_time + + self.masks = masks + self.min_freq = min_freq + self.max_freq = max_freq + self.min_time = min_time + self.max_time = max_time + + @torch.no_grad() + def forward(self, x): + sh = x.shape + mask = torch.zeros(x.shape, dtype=torch.bool, device=x.device) + + for idx in range(sh[0]): + for i in range(self.masks): + + w = torch.randint(self.min_freq, self.max_freq + 1, size=(1,)).item() + h = torch.randint(self.min_time, self.max_time + 1, size=(1,)).item() + + f0 = int(random.uniform(0, sh[1] - w)) + t0 = int(random.uniform(0, sh[2] - h)) + + mask[idx, f0:f0+w, t0:t0+h] = 1 + + return x.masked_fill(mask, 0) + + +@torch.jit.script +def normalize_batch(x, seq_len, normalize_type: str): + if normalize_type == "per_feature": + x_mean = torch.zeros((seq_len.shape[0], x.shape[1]), dtype=x.dtype, + device=x.device) + x_std = torch.zeros((seq_len.shape[0], x.shape[1]), dtype=x.dtype, + device=x.device) + for i in range(x.shape[0]): + x_mean[i, :] = x[i, :, :seq_len[i]].mean(dim=1) + x_std[i, :] = x[i, :, :seq_len[i]].std(dim=1) + # make sure x_std is not zero + x_std += 1e-5 + return (x - x_mean.unsqueeze(2)) / x_std.unsqueeze(2) + + elif normalize_type == "all_features": + x_mean = torch.zeros(seq_len.shape, dtype=x.dtype, device=x.device) + x_std = torch.zeros(seq_len.shape, dtype=x.dtype, device=x.device) + for i in range(x.shape[0]): + x_mean[i] = x[i, :, :int(seq_len[i])].mean() + x_std[i] = x[i, :, :int(seq_len[i])].std() + # make sure x_std is not zero + x_std += 1e-5 + return (x - x_mean.view(-1, 1, 1)) / x_std.view(-1, 1, 1) + else: + return x + + +@torch.jit.script +def stack_subsample_frames(x, x_lens, stacking: int = 1, subsampling: int = 1): + """ Stacks frames together across feature dim, and then subsamples + + input is batch_size, feature_dim, num_frames + output is batch_size, feature_dim * stacking, num_frames / subsampling + + """ + seq = [x] + for n in range(1, stacking): + tmp = torch.zeros_like(x) + tmp[:, :, :-n] = x[:, :, n:] + seq.append(tmp) + x = torch.cat(seq, dim=1)[:, :, ::subsampling] + + if subsampling > 1: + x_lens = torch.ceil(x_lens.float() / subsampling).int() + + if x.size(2) > x_lens.max().item(): + assert abs(x.size(2) - x_lens.max().item()) <= 1 + x = x[:,:,:x_lens.max().item()] + + return x, x_lens + + +class FilterbankFeatures(BaseFeatures): + # For JIT, https://pytorch.org/docs/stable/jit.html#python-defined-constants + __constants__ = ["dither", "preemph", "n_fft", "hop_length", "win_length", + "log", "frame_stacking", "frame_subsampling", "normalize"] + # torchscript: "center" removed due to a bug + + def __init__(self, spec_augment=None, cutout_augment=None, + sample_rate=16000, window_size=0.02, window_stride=0.01, + window="hann", normalize="per_feature", n_fft=512, + preemph=0.97, n_filt=80, lowfreq=0, highfreq=None, log=True, + dither=1e-5, pad_align=16, pad_to_max_duration=False, + max_duration=float('inf'), frame_stacking=1, + frame_subsampling=1): + super(FilterbankFeatures, self).__init__( + pad_align=pad_align, pad_to_max_duration=pad_to_max_duration, + max_duration=max_duration, sample_rate=sample_rate, + window_size=window_size, window_stride=window_stride, + spec_augment=spec_augment, cutout_augment=cutout_augment) + + torch_windows = { + 'hann': torch.hann_window, + 'hamming': torch.hamming_window, + 'blackman': torch.blackman_window, + 'bartlett': torch.bartlett_window, + 'none': None, + } + + self.n_fft = n_fft or 2 ** math.ceil(math.log2(self.win_length)) + + self.normalize = normalize + self.log = log + #TORCHSCRIPT: Check whether or not we need this + self.dither = dither + self.frame_stacking = frame_stacking + self.frame_subsampling = frame_subsampling + self.n_filt = n_filt + self.preemph = preemph + highfreq = highfreq or sample_rate / 2 + window_fn = torch_windows.get(window, None) + window_tensor = window_fn(self.win_length, + periodic=False) if window_fn else None + filterbanks = torch.tensor( + librosa.filters.mel(sample_rate, self.n_fft, n_mels=n_filt, + fmin=lowfreq, fmax=highfreq), + dtype=torch.float).unsqueeze(0) + # torchscript + self.register_buffer("fb", filterbanks) + self.register_buffer("window", window_tensor) + + def output_dim(self): + return self.n_filt * self.frame_stacking + + def get_seq_len(self, seq_len): + return torch.ceil(seq_len.to(dtype=torch.float) / self.hop_length).to( + dtype=torch.int) + + # TORCHSCRIPT: center removed due to bug + def stft(self, x): + spec = torch.stft(x, n_fft=self.n_fft, hop_length=self.hop_length, + win_length=self.win_length, + window=self.window.to(dtype=torch.float), + return_complex=True) + return torch.view_as_real(spec) + + @torch.no_grad() + def calculate_features(self, x, x_lens): + dtype = x.dtype + + x_lens = self.get_seq_len(x_lens) + + # dither + if self.dither > 0: + x += self.dither * torch.randn_like(x) + + # do preemphasis + if self.preemph is not None: + x = torch.cat( + x[:, 0].unsqueeze(1), x[:, 1:] - self.preemph * x[:, :-1], + dim=1) + x = self.stft(x) + + # get power spectrum + x = x.pow(2).sum(-1) + + # dot with filterbank energies + x = torch.matmul(self.fb.to(x.dtype), x) + + # log features if required + if self.log: + x = torch.log(x + 1e-20) + + # normalize if required + x = normalize_batch(x, x_lens, normalize_type=self.normalize) + + if self.frame_stacking > 1 or self.frame_subsampling > 1: + x, x_lens = stack_subsample_frames(x, x_lens, self.frame_stacking, + self.frame_subsampling) + + # mask to zero any values beyond x_lens in batch, + # pad to multiple of `pad_align` (for efficiency) + max_len = x.size(-1) + mask = torch.arange(max_len, dtype=x_lens.dtype, device=x.device) + mask = mask.expand(x.size(0), max_len) >= x_lens.unsqueeze(1) + x = x.masked_fill(mask.unsqueeze(1), 0) + + # TORCHSCRIPT: Is this del important? It breaks scripting + # del mask + + return x.to(dtype), x_lens diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/filter_warnings.py b/PyTorch/SpeechRecognition/wav2vec2/common/filter_warnings.py new file mode 100644 index 000000000..399c72b9f --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/filter_warnings.py @@ -0,0 +1,31 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import warnings + + +# NGC 22.04-py3 container (PyTorch 1.12.0a0+bd13bc6) +warnings.filterwarnings( + "ignore", + message='positional arguments and argument "destination" are deprecated.' + ' nn.Module.state_dict will not accept them in the future.') + +# NGC ~22.05-py3 +warnings.filterwarnings( + "ignore", message="pyprof will be removed by the end of June, 2022") + +# 22.08-py3 RC +warnings.filterwarnings( + "ignore", + message="is_namedtuple is deprecated, please use the python checks") diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/helpers.py b/PyTorch/SpeechRecognition/wav2vec2/common/helpers.py new file mode 100644 index 000000000..e1c0807f0 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/helpers.py @@ -0,0 +1,407 @@ +# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import re +from collections import OrderedDict +from pathlib import Path + +import amp_C +import numpy as np +import torch +import torch.distributed as dist + +from .metrics import word_error_rate +from common.utils import print_once + + +def to_gpu(batch, fp16=False, bf16=False): + assert not (fp16 and bf16) + for k, v in batch['net_input'].items(): + if fp16 and v.dtype is torch.float: + batch['net_input'][k] = v.cuda(non_blocking=True).half() + elif bf16 and v.dtype is torch.float: + batch['net_input'][k] = v.cuda(non_blocking=True).to(dtype=torch.bfloat16) + else: + batch['net_input'][k] = v.cuda(non_blocking=True) + + +def init_multi_tensor_ema(model, ema_model): + model_weights = list(model.state_dict().values()) + ema_model_weights = list(ema_model.state_dict().values()) + ema_overflow_buf = torch.cuda.IntTensor([0]) + return model_weights, ema_model_weights, ema_overflow_buf + + +def apply_multi_tensor_ema(decay, model_weights, ema_model_weights, + overflow_buf): + amp_C.multi_tensor_axpby( + 65536, overflow_buf, + [ema_model_weights, model_weights, ema_model_weights], + decay, 1-decay, -1) + + +def apply_ema(model, ema_model, decay, patch_conv_wn=False): + if not decay: + return + + if patch_conv_wn: + torch.nn.utils.remove_weight_norm(model.encoder.pos_conv[0]) + + sd = getattr(model, 'module', model).state_dict() + + for k, v in ema_model.state_dict().items(): + v.copy_(decay * v + (1 - decay) * sd[k]) + + if patch_conv_wn: + torch.nn.utils.weight_norm( + model.encoder.pos_conv[0], name="weight", dim=2) + + +def add_ctc_blank(symbols): + return symbols + [''] + + +def ctc_decoder_predictions_tensor(tensor, labels, blank_id=None): + """ + Takes output of greedy ctc decoder and performs ctc decoding algorithm to + remove duplicates and special symbol. Returns prediction + Args: + tensor: model output tensor + label: A list of labels + Returns: + prediction + """ + if blank_id is None: + blank_id = len(labels) - 1 + hypotheses = [] + labels_map = {i: labels[i] for i in range(len(labels))} + prediction_cpu_tensor = tensor.long().cpu() + # iterate over batch + for prediction in prediction_cpu_tensor: + prediction = prediction.numpy().tolist() + # CTC decoding procedure + decoded_prediction = [] + previous = blank_id + for p in prediction: + if (p != previous or previous == blank_id) and p != blank_id: + decoded_prediction.append(p) + previous = p + hypothesis = ''.join([labels_map[c] for c in decoded_prediction]) + hypotheses.append(hypothesis) + return hypotheses + + +def greedy_wer(preds, tgt, tgt_lens, labels): + """ + Takes output of greedy ctc decoder and performs ctc decoding algorithm to + remove duplicates and special symbol. Prints wer and prediction examples + to screen. + Args: + tensors: A list of 3 tensors (predictions, targets, target_lengths) + labels: A list of labels + + Returns: + word error rate + """ + with torch.no_grad(): + references = gather_transcripts([tgt], [tgt_lens], labels) + hypotheses = ctc_decoder_predictions_tensor(preds, labels) + + wer, _, _ = word_error_rate(hypotheses, references) + return wer, hypotheses[0], references[0] + + +def gather_losses(losses_list): + return [torch.mean(torch.stack(losses_list))] + + +def gather_predictions(predictions_list, labels, blank_id=None): + results = [] + for prediction in predictions_list: + results += ctc_decoder_predictions_tensor(prediction, labels=labels, + blank_id=blank_id) + return results + + +def gather_transcripts(transcript_list, transcript_len_list, labels): + results = [] + labels_map = {i: labels[i] for i in range(len(labels))} + # iterate over workers + for txt, lens in zip(transcript_list, transcript_len_list): + for t, l in zip(txt.long().cpu(), lens.long().cpu()): + t = list(t.numpy()) + results.append(''.join([labels_map[c] for c in t[:l]])) + return results + + +def process_evaluation_batch(tensors, global_vars, labels): + """ + Processes results of an iteration and saves it in global_vars + Args: + tensors: dictionary with results of an evaluation iteration, + e.g., loss, predictions, transcript, and output + global_vars: dictionary where processes results of iteration are saved + labels: A list of labels + """ + for kv, v in tensors.items(): + if kv.startswith('loss'): + global_vars['EvalLoss'] += gather_losses(v) + elif kv.startswith('predictions'): + global_vars['preds'] += gather_predictions(v, labels) + elif kv.startswith('transcript_length'): + transcript_len_list = v + elif kv.startswith('transcript'): + transcript_list = v + elif kv.startswith('output'): + global_vars['logits'] += v + + global_vars['txts'] += gather_transcripts( + transcript_list, transcript_len_list, labels) + + +def process_evaluation_epoch(aggregates): + """ + Processes results from each worker and combine to final result. + Args: + aggregates: dictionary containing information of entire evaluation + Return: + wer: final word error rate + loss: final loss + """ + if 'losses' in aggregates: + eloss = torch.mean(torch.stack(aggregates['losses'])).item() + else: + eloss = None + hypotheses = aggregates['preds'] + references = aggregates['txts'] + ids = aggregates['ids'] + + wer, scores, num_words = word_error_rate(hypotheses, references) + multi_gpu = dist.is_initialized() + if multi_gpu: + if eloss is not None: + eloss /= dist.get_world_size() + eloss_tensor = torch.tensor(eloss).cuda() + dist.all_reduce(eloss_tensor) + eloss = eloss_tensor.item() + + scores_tensor = torch.tensor(scores).cuda().unsqueeze(-1) + num_words_tensor = torch.tensor(num_words).cuda().unsqueeze(-1) + ids_tensor = torch.tensor(ids).cuda().unsqueeze(-1) + + result_tensor = torch.cat( + [scores_tensor, num_words_tensor, ids_tensor], dim=-1) + result_tensor_list = [torch.zeros_like(result_tensor) + for i in range(dist.get_world_size())] + dist.all_gather(result_tensor_list, result_tensor) + if dist.get_rank() == 0: + agg_results = torch.cat(result_tensor_list, dim=0) + agg_ids = set() + agg_score, agg_num_words = 0, 0 + for x in agg_results.cpu().numpy(): + score, num_words, sample_id = x + if sample_id in agg_ids: + continue + else: + agg_ids.add(sample_id) + agg_score += score + agg_num_words += num_words + wer = 1.0 * agg_score / agg_num_words + return wer, eloss + + +def num_weights(module): + return sum(p.numel() for p in module.parameters() if p.requires_grad) + + +def load_wrapped_state(model, state_dict, strict=True): + if model is None: + return + + unwrap_ddp = lambda model: getattr(model, 'module', model) + state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()} + unwrap_ddp(unwrap_ddp(model)).load_state_dict(state_dict, strict=strict) + + +class Checkpointer: + + def __init__(self, args, model_name): + self.no_save = args.no_save + self.save_dir = args.output_dir + self.keep_milestones = args.keep_milestones + self.model_name = model_name + self.output_labels = None # for supervised training + + pattern = f'{self.model_name}_update*.pt' + tracked = [(int(re.search('update(\d+)\.pt', str(f)).group(1)), f) + for f in Path(args.output_dir).rglob(pattern)] + self.tracked = OrderedDict(sorted(tracked, key=lambda t: t[0])) + + fpath = (self.last_checkpoint() if args.resume else None) or args.ckpt + + if fpath is not None: + print_once(f'Loading model from {fpath}') + self.last_state = torch.load(fpath, map_location="cpu") + else: + self.last_state = None + + def maybe_save(self, model, ema_model, optimizer, scaler, train_state, + step, epoch, val_losses, val_wer, args): + """Saves model checkpoint for inference/resuming training. + + Args: + model: the model, optionally wrapped by DistributedDataParallel + ema_model: model with averaged weights, can be None + optimizer: optimizer + epoch (int): epoch during which the model is saved + step (int): number of steps since beginning of training + best_wer (float): lowest recorded WER on the dev set + is_best (bool, optional): set name of checkpoint to 'best' + and overwrite the previous one + """ + + if epoch == 0 or args.no_save: + return + if args.local_rank != 0 or int(os.environ.get('RANK', 0)) != 0: + return + + if args.mode == "finetune": + is_best_ckpt = val_wer[0] < train_state["best_val_wer"] + elif args.mode == "pretrain": + is_best_ckpt = val_losses[0] < train_state["best_val_loss"] + + if not is_best_ckpt and epoch % args.save_frequency != 0: + return + + unwrap_ = lambda model: getattr(model, 'module', model) + unwrap_ddp = lambda model: unwrap_(unwrap_(model)) + state_dict = lambda m: m.state_dict() if m is not None else None + type_name = lambda m: None if m is None else type(m).__name__ + + val_wer = val_wer or [float("inf")] # wer absent in pretraining + train_state.update({ + 'optimizer_type': type_name(optimizer), + 'scaler_type': type_name(scaler), + 'step': step, + 'epoch': epoch + 1, # fairseq compat; restart at the next epoch + 'best_val_wer': min(val_wer[0], train_state["best_val_wer"]), + 'best_val_loss': min(val_losses[0], train_state['best_val_loss']), + }) + + state = { + 'args': args.__dict__, + 'model': state_dict(unwrap_ddp(model)), + 'ema_model': state_dict(unwrap_ddp(ema_model)), + 'optimizer': state_dict(optimizer), + 'scaler': state_dict(scaler), + 'train_state': train_state, + **({'output_labels': self.output_labels} if self.output_labels else {}), + } + + if is_best_ckpt: + fpath = Path(self.save_dir, f"{self.model_name}_best.pt") + print_once(f"Saving {fpath}...") + torch.save(state, fpath) + + fpath = Path(self.save_dir, f"{self.model_name}_update{step}.pt") + print_once(f"Saving {fpath}...") + torch.save(state, fpath) + + # keep checkpoints with steps closest to milestones + for_keeps = set() + if len(self.tracked) > 0: + tracked = np.array(list(self.tracked.keys())) + for milestone in self.keep_milestones: + st = tracked[np.argmin(np.abs(tracked - milestone))] + for_keeps.add(st) + + # remove old checkpoints; keep milestones and the last two + self.tracked[step] = fpath + for epoch in set(list(self.tracked)[:-2]) - for_keeps: + try: + os.remove(self.tracked[epoch]) + except: + pass + del self.tracked[epoch] + + def maybe_load_state(self, model=None, ema_model=None, optimizer=None, + scaler=None, train_state=None, train_loader=None): + + if self.last_state is None: + return + + if model is not None: + load_wrapped_state(model, self.last_state['model']) + + if ema_model is not None: + if checkpoint.get('ema_model', None) is not None: + load_wrapped_state(ema_model, self.last_state['ema_model']) + else: + print_once('WARNING: EMA weights not found in the ckpt.') + print_once('WARNING: Initializing EMA model with main model.') + + # https://github.com/pytorch/pytorch/issues/28594 + model.remove_conv_wn() + load_wrapped_state(ema_model, model.state_dict()) + model.apply_conv_wn() + + if optimizer is not None: + if 'last_optimizer_state' in self.last_state: + optimizer.load_state_dict( + self.last_state['last_optimizer_state']) + + elif 'optimizer' in self.last_state: + optimizer.load_state_dict(self.last_state['optimizer']) + else: + raise ValueError('Optimizer state not found') + + if scaler is not None: + if 'scaler' in self.last_state: + scaler.load_state_dict(self.last_state['scaler']) + elif 'amp' in self.last_state: + scaler.load_state_dict(self.last_state['amp']) + else: + raise ValueError('Scaler state not found') + + if train_state is not None: + + if 'train_state' in self.last_state: + train_state.update(self.last_state['train_state']) + + if 'extra_state' in self.last_state: + extra_state = self.last_state['extra_state'] + train_state.update({ + 'epoch': extra_state['train_iterator']['epoch'], + 'best_val_loss': extra_state['best'] + }) + + if 'optimizer_history' in extra_state: + train_state['step'] = (extra_state['optimizer_history'] + [-1]['num_updates']), + + if train_loader is not None and 'extra_state' in self.last_state: + state = self.last_state['extra_state']['train_iterator'] + train_loader.load_state_dict(state) + + def last_checkpoint(self): + tracked = list(self.tracked.values()) + for fpath in reversed(tracked): + try: + torch.load(fpath, map_location='cpu') + return fpath + except: + print_once(f'Checkpoint {fpath} appears corrupted.') + + return None diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/metrics.py b/PyTorch/SpeechRecognition/wav2vec2/common/metrics.py new file mode 100644 index 000000000..e1746e23a --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/metrics.py @@ -0,0 +1,288 @@ +# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +from collections import defaultdict +from copy import copy + +import numpy as np +import torch + +from common.utils import all_reduce_cpu_scalars, print_once + + +def __levenshtein(a, b): + """Calculates the Levenshtein distance between two sequences.""" + + n, m = len(a), len(b) + if n > m: + # Make sure n <= m, to use O(min(n,m)) space + a, b = b, a + n, m = m, n + + current = list(range(n + 1)) + for i in range(1, m + 1): + previous, current = current, [i] + [0] * n + for j in range(1, n + 1): + add, delete = previous[j] + 1, current[j - 1] + 1 + change = previous[j - 1] + if a[j - 1] != b[i - 1]: + change = change + 1 + current[j] = min(add, delete, change) + + return current[n] + + +def word_error_rate(hypotheses, references): + """Computes average Word Error Rate (WER) between two text lists.""" + + scores = 0 + words = 0 + len_diff = len(references) - len(hypotheses) + if len_diff > 0: + raise ValueError("Uneqal number of hypthoses and references: " + "{0} and {1}".format(len(hypotheses), len(references))) + elif len_diff < 0: + hypotheses = hypotheses[:len_diff] + + for h, r in zip(hypotheses, references): + h_list = h.split() + r_list = r.split() + words += len(r_list) + scores += __levenshtein(h_list, r_list) + if words != 0: + wer = 1.0*scores/words + else: + wer = float('inf') + return wer, scores, words + + +class MetricsAggregator: + def __init__(self, scopes=('train', 'train_avg'), + dllogger_keys=(), + benchmark_keys=(), + benchmark_epochs=0, + reduce_mean=(), + reduce_last=(), + group_tb_entries=False, + cuda=True): + """ + Args: + scopes: possible scopes of metrics accumulation + dll_keys: metrics to log with dllogger + benchmark_keys: metrics to log as benchmark metrics + benchmark_epochs: num of last epochs to benchmark + """ + super().__init__() + + self.dll_keys = dllogger_keys + self.partials = defaultdict(float) + self.partial_counts = defaultdict(int) + self.accum_reductions = defaultdict(lambda: 'sum') + self.accum_reductions.update({k: 'mean' for k in reduce_mean}) + self.accum_reductions.update({k: 'last' for k in reduce_last}) + self.metrics = {scope: defaultdict(float) for scope in scopes} + self.metric_counts = {scope: defaultdict(int) for scope in scopes} + self.start_time = {scope: None for scope in scopes} + self.done_accumulating = {scope: True for scope in scopes} + self.benchmark_epochs = benchmark_epochs + self.metrics['train_benchmark'] = defaultdict(list) + self.benchmark_keys = benchmark_keys + self.scopes = scopes + self.group_tb_entries = group_tb_entries + self.cuda = cuda + + def log_scalar(self, key, val, accum_reduction=None): + """Main primitive for logging partial metrics from single batch. + + NOTE: Assumption: `log_scalar` cannot be called with different + `accum_reduction` for the same `key`. This results in undefined behavior + + Args: + key: metric key + val: metric value + accum_reduction: defines how to accumulate given metric: + - 'sum': sums metrics across grad acc and devices batches + - 'mean': same as 'sum' but with averaging + - 'last': overwrites previous accumulated values. Useful for + logging metric once in a grad acc batch, e.g. learning rate. + If None, a default value is fetched from self.accum_reductions. + If not None, overwrites defaults in self.accum_reductions + """ + if accum_reduction is None: + accum_reduction = self.accum_reductions[key] + else: + self.accum_reductions[key] = accum_reduction + + if accum_reduction == 'sum': + self.partials[key] += val + self.partial_counts[key] = 1 + elif accum_reduction == 'mean': + self.partials[key] += val + self.partial_counts[key] += 1 + elif accum_reduction == 'last': + self.partials[key] = val # overwrite accumulation + self.partial_counts[key] = 1 + else: + raise ValueError(accum_reduction) + + def log_scalars(self, scalars_dict, accum_reduction=None): + """ Log whole dict of metrics at once """ + for k, v in scalars_dict.items(): + self.log_scalar(k, v, accum_reduction) + + def __setitem__(self, key, val): + """ Convenience logging method. Use sparingly (see NOTE below). + + Uses 'last' aggregation and extracts tensors. + + Example: + >>> metrics['lr'] = optim.param_groups[0]['lr'] + + NOTE: `metrics['lr'] = ...` is very different + from `metrics.partial['lr'] = ...` + """ + extract = lambda t: t.item() if type(t) is torch.Tensor else t + + if type(val) is dict: + for k, v in val.items(): + self.log_scalar(k, extract(v), 'last') + else: + self.log_scalar(key, extract(val), 'last') + + def accumulate(self, scopes=None): + """ Accumulates partial metrics in metrics for given scopes. + + Defines boundaries of accum_reduction in `log_scalar` method. + Intended to run after each gradient accumulation adjusted iteration. + """ + scopes = scopes if scopes is not None else self.scopes + for scope in scopes: + for k, v in self.partials.items(): + self.metrics[scope][k] += v + self.metric_counts[scope][k] += self.partial_counts.get(k, 1) + + self.partials.clear() + self.partial_counts.clear() + + def all_reduce(self, world_size): + """ Reduce metrics across devices. + + Currently assumes that all metrics are float scalars. + + After reducing, `log_scalar` method with accumulation other than 'last' + shouldn't be called prior to calling `accumulate`. + """ + if world_size == 1: + return + self.partials = defaultdict(float, + all_reduce_cpu_scalars(self.partials)) + for k, v in self.partials.items(): + if self.accum_reductions[k] in ('mean', 'last'): + self.partial_counts[k] *= (world_size - self.partials.get('ignore', 0)) + if self.partials.get('ignore', 0) > 0: + assert self.accum_reductions[k] == 'mean' + print_once(f'reducing with world size {world_size - self.partials.get("ignore", 0)}') + + def start_iter(self, iter): + self._start_accumulating(iter, True, 'train') + + def start_epoch(self, epoch): + if self.cuda: + torch.cuda.synchronize() + self._start_accumulating(epoch, True, 'train_avg') + + def start_val(self): + if self.cuda: + torch.cuda.synchronize() + self._start_accumulating(None, True, 'val') + + def finish_iter(self): + self._accumulate_time('train') + + def finish_logging_interval(self): + self._finish_accumulating('train') + + def finish_epoch(self): + if self.cuda: + torch.cuda.synchronize() + self._accumulate_time('train_avg') + self._finish_accumulating('train_avg') + + metr = self.metrics['train_benchmark'] + for k in self.benchmark_keys: + metr[k].append(self.metrics['train_avg'][k]) + + if len(metr[k]) > self.benchmark_epochs: + metr[k].pop(0) + + def finish_val(self, scope='val'): + if self.cuda: + torch.cuda.synchronize() + self._accumulate_time(scope) + self._finish_accumulating(scope) + + def get_metrics(self, scope='train', target='dll'): + if scope == 'train_benchmark': + metr = self.metrics[scope] + ret = {'train_avg_' + k: np.mean(v) for k, v in metr.items()} + ret['benchmark_epochs_num'] = len(list(metr.values())[0]) + return ret + + assert self.done_accumulating[scope] + + ret = copy(self.metrics[scope]) + + if target == 'dll': + ret = {f'{scope}_{k}': v + for k, v in ret.items() if k in self.dll_keys} + + elif target == 'tb' and self.group_tb_entries: + # Rename keys so they would group nicely inside TensorBoard + + def split_key(k): + pos = k.rfind('_') + return k[:pos] + '/' + k[pos+1:] if pos >= 0 else k + + ret = {split_key(k): v for k, v in ret.items()} + + return ret + + def _start_accumulating(self, step, start_timer=True, scope='train'): + del step # unused + assert not self.partials, 'metrics.accumulate call missed' + assert not self.partial_counts, 'metrics.accumulate call missed' + if self.done_accumulating[scope]: + self.metrics[scope].clear() + self.metric_counts[scope].clear() + if start_timer: + self.start_time[scope] = time.time() + self.done_accumulating[scope] = False + + def _finish_accumulating(self, scope='train'): + assert not self.done_accumulating[scope] + metr = self.metrics[scope] + counts = self.metric_counts[scope] + + for k, v in metr.items(): + metr[k] = v / counts[k] + + self.done_accumulating[scope] = True + + def _accumulate_time(self, scope='train'): + assert not self.done_accumulating[scope] + took = time.time() - self.start_time[scope] + self.start_time[scope] = None + self.metrics[scope]['took'] += took + self.metric_counts[scope]['took'] = 1 # not += diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/optimizers.py b/PyTorch/SpeechRecognition/wav2vec2/common/optimizers.py new file mode 100644 index 000000000..460a54f1c --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/optimizers.py @@ -0,0 +1,132 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math + +from common.fairseq.optim.adam import FairseqAdam +from common.fairseq.optim.fp16_optimizer import FP16Optimizer +from common.fairseq.optim.fused_adam import get_fused_adam_class +from common.utils import print_once + + +def lr_poly_policy(step, optimizer, lr, initial_lr_scale=0.0, + final_lr_scale=0.0, warmup_steps=1000, hold_steps=0, + num_steps=None, power=1.0): + """Polynomial decay LR policy with an optional hold period.""" + assert step >= 1 + assert num_steps is not None + assert power is not None + + start_lr = initial_lr_scale * lr + end_lr = final_lr_scale * lr + + if step <= warmup_steps: + new_lr = start_lr + (step) / warmup_steps * (lr - start_lr) + elif step <= warmup_steps + hold_steps: + new_lr = lr + elif warmup_steps + hold_steps < step <= num_steps: + remain = 1 - (step - warmup_steps) / (num_steps - warmup_steps) + new_lr = (lr - end_lr) * remain ** power + end_lr + else: + new_lr = end_lr + + for param_group in optimizer.param_groups: + param_group['lr'] = new_lr + + +def lr_exp_policy(step, optimizer, initial_lr_scale, lr, final_lr_scale=0.0, + warmup_steps=1000, hold_steps=0, num_steps=float('inf'), + decay=None): + """Exponential LR policy with an optional hold period. + + If `decay` factor is not supplied, it is calculated to reach `end_lr` + on `num_steps` steps. + + Args: + num_steps (int): Limits the number of decay steps. + end_lr (float): The lowest possible LR. + decay (float or None): Decay factor; if None, the it will be derived + from `num_steps` and `end_lr`. + """ + assert step >= 1 + + start_lr = initial_lr_scale * lr + end_lr = final_lr_scale * lr + + if decay is None: + assert not math.isinf(num_steps) and end_lr > 0.0 + decay_steps = num_steps - warmup_steps - hold_steps + decay = math.log(end_lr / lr) / decay_steps + else: + decay = math.log(decay) + + if step <= warmup_steps: + new_lr = start_lr + (step) / warmup_steps * (lr - start_lr) + elif step <= warmup_steps + hold_steps: + new_lr = lr + else: + a = math.exp(decay * (min(step, num_steps) - warmup_steps - hold_steps)) + new_lr = max(a * lr, end_lr) + + for param_group in optimizer.param_groups: + param_group['lr'] = new_lr + + +def get_optimizer(model, args): + + kw = {'lr': args.lr, 'weight_decay': args.weight_decay} + if args.optimizer == 'adam' and (args.fp16 or args.bf16): + + print_once('WARNING: Using Fairseq FP16Optimizer') + + # based on fairseq.optim.FP16Optimizer.build_optimizer + flatten = True # not args.fp16_no_flatten_grads + args.betas = args.adam_betas + args.eps = args.adam_eps + + params = list(filter(lambda p: p.requires_grad, model.parameters())) + + fp32_params = FP16Optimizer.build_fp32_params(args, params, + flatten=flatten) + + # based on fairseq.optim.build_optimizer + def build_optimizer(cfg, params, *extra_args, **extra_kwargs): + if all(isinstance(p, dict) for p in params): + params = [t for p in params for t in p.values()] + params = list(filter(lambda p: p.requires_grad, params)) + return FairseqAdam(cfg, params, *extra_args, **extra_kwargs) + + if flatten: + fp32_optimizer = build_optimizer(args, [fp32_params]) + else: + fp32_optimizer = build_optimizer(args, fp32_params) + + if flatten and not fp32_optimizer.supports_flat_params: + raise RuntimeError( + f"chosen optimizer {fp32_optimizer.__class__.__name__} does " + "not support flat params, please set --fp16-no-flatten-grads" + ) + kwargs = {} + optimizer = FP16Optimizer(args, params, fp32_optimizer, fp32_params, + **kwargs) + + elif args.optimizer == 'adam' and not (args.fp16 or args.bf16): + print_once('WARNING: Using FusedAdam instead of Adam') + kw.update({'betas': args.adam_betas, 'eps': args.adam_eps}) + fused_adam_cls = get_fused_adam_class() + optimizer = fused_adam_cls(model.parameters(), **kw) + else: + raise ValueError(f'Invalid optimizer "{args.optimizer}"') + + return optimizer diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/pyt_mha.py b/PyTorch/SpeechRecognition/wav2vec2/common/pyt_mha.py new file mode 100644 index 000000000..481a948a2 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/pyt_mha.py @@ -0,0 +1,280 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from collections import defaultdict + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from common.fairseq.modules.multihead_attention import RotaryEmbedding + + +def mha_state_dict_to_fairseq(sd): + """Concatenate q, k, v matrices and load as usual.""" + new_sd = {} + qkv = defaultdict(dict) + + for key, val in sd.items(): + fields = key.split('.') + if len(fields) < 2: + continue + prefix = '.'.join(fields[:-2] + [""]) + module, param = fields[-2:] + + if module in ['q_proj', 'k_proj', 'v_proj']: + qkv[prefix][module + '.' + param] = val + else: + new_sd[key] = val + + for prefix, param_dict in qkv.items(): + # Stitch qkv params together + assert len(param_dict) == 6 + new_sd[f"{prefix}qkv.weight"] = torch.cat( + [param_dict[f"{k}_proj.weight"] for k in ["q", "k", "v"]], dim=0) + new_sd[f"{prefix}qkv.bias"] = torch.cat( + [param_dict[f"{k}_proj.bias"] for k in ["q", "k", "v"]], dim=0) + + return new_sd + + +class PytMultiheadAttention(nn.Module): + """Drop-in replacement for Fairseq MHA. + + Calls torch.nn.functional with combined qkv. + """ + def __init__( + self, + embed_dim, + num_heads, + dropout=0.0, + bias=True, + self_attention=True, + rotary_embeddings=False, + ): + super().__init__() + + assert self_attention + assert not rotary_embeddings, "Not yet supported" + + self.embed_dim = embed_dim + self.num_heads = num_heads + self.rotary_embeddings = rotary_embeddings + + if self.rotary_embeddings: + self.rotary_freq = RotaryEmbedding(embed_dim) + + self.head_dim = embed_dim // num_heads + assert ( + self.head_dim * num_heads == self.embed_dim + ), "embed_dim must be divisible by num_heads" + + self.qkv = nn.Linear(embed_dim, 3 * num_heads * self.head_dim, + bias=bias) + self.dropatt = nn.Dropout(dropout) + self.out_proj = nn.Linear(num_heads * self.head_dim, embed_dim, + bias=bias) + self.reset_parameters() + + def hook(state_dict, prefix, *args, **kwargs): + this_keys = {k for k in state_dict.keys() if k.startswith(prefix)} + new_sd = {k: v for k, v in state_dict.items() if k in this_keys} + for k in this_keys: + del state_dict[k] + state_dict.update(mha_state_dict_to_fairseq(new_sd)) + + self._register_load_state_dict_pre_hook(hook) + + def forward(self, query, key=None, value=None, key_padding_mask=None, + attn_mask=None): + + return F.multi_head_attention_forward( + query, + key, + value, + self.embed_dim, + self.num_heads, + self.qkv.weight, + self.qkv.bias, + None, + None, + False, + self.dropatt.p, + self.out_proj.weight, + self.out_proj.bias, + training=self.training, + key_padding_mask=key_padding_mask, + need_weights=False, + attn_mask=attn_mask, + average_attn_weights=False, + ) + + def state_dict(self, *args, destination=None, prefix='', keep_vars=False): + """Split q, k, v matrices for bwd compatibility with Fairseq.""" + sd = super().state_dict(*args, destination, prefix, keep_vars) + for key in list(sd.keys()): + if not (key.endswith(".qkv.weight") or key.endswith(".qkv.bias")): + continue + *pref, qkv, param = key.split(".") + pref = ".".join(pref) + assert qkv == "qkv" + q, k, v = torch.chunk(sd.pop(key), 3, dim=0) + sd[f"{pref}.q_proj.{param}"] = q + sd[f"{pref}.k_proj.{param}"] = k + sd[f"{pref}.v_proj.{param}"] = v + + return sd + + def reset_parameters(self): + # Init as in Fairseq with qkv_same_dim=True and separate qkv projs + t = self.qkv.weight.size(0) // 3 + nn.init.xavier_uniform_(self.qkv.weight[0*t:1*t], gain=1 / (2 ** 0.5)) + nn.init.xavier_uniform_(self.qkv.weight[1*t:2*t], gain=1 / (2 ** 0.5)) + nn.init.xavier_uniform_(self.qkv.weight[2*t:3*t], gain=1 / (2 ** 0.5)) + + nn.init.xavier_uniform_(self.out_proj.weight) + if self.out_proj.bias is not None: + nn.init.constant_(self.out_proj.bias, 0.0) + + +class Fp32Softmax(nn.Softmax): + def forward(self, x): + return F.softmax(x.float(), dim=self.dim).type_as(x) + + +class SlowMultiHeadAttention(nn.Module): + """Drop-in replacement for Fairseq MHA.""" + def __init__(self, + embed_dim, + num_heads, + dropout=0.0, + bias=True, + self_attention=True, + rotary_embeddings=None, + fp32_softmax=False, + ): + super().__init__() + + n_head = num_heads + d_model = embed_dim + d_head = embed_dim // n_head + dropatt = dropout + pre_lnorm = False + assert self_attention + assert rotary_embeddings is None, "Rotary embs not yet supported" + + self.embed_dim = embed_dim + self.num_heads = num_heads + + self.n_head = n_head + self.d_model = d_model + self.d_head = d_head + self.scale = 1 / (d_head ** 0.5) + self.pre_lnorm = pre_lnorm + + self.qkv = nn.Linear(d_model, 3 * n_head * d_head, bias=bias) + self.dropatt = nn.Dropout(dropatt) + self.proj = nn.Linear(n_head * d_head, d_model, bias=bias) + self.layer_norm = nn.LayerNorm(d_model, elementwise_affine=False) + self.softmax = Fp32Softmax(dim=2) if fp32_softmax else nn.Softmax(dim=2) + + def state_dict(self): + """Convert QKV to be compatible with Fairseq""" + sd = super().state_dict() + + ret = {} + for key, val in sd.items(): + fields = key.split('.') + if len(fields) < 2: + continue + prefix = '.'.join(fields[:-2] + [""]) + module, param = fields[-2:] + + if module == 'qkv': + q, k, v = torch.chunk(val, 3, dim=0) + ret[f"{prefix}q_proj.{param}"] = q + ret[f"{prefix}k_proj.{param}"] = k + ret[f"{prefix}v_proj.{param}"] = v + else: + ret[key] = val + return ret + + def load_state_dict(self, sd): + + from collections import defaultdict + + ret = {} + qkv = defaultdict(dict) + + for key, val in sd.items(): + fields = key.split('.') + if len(fields) < 2: + continue + prefix = '.'.join(fields[:-2] + [""]) + module, param = fields[-2:] + + if module in ['q_proj', 'k_proj', 'v_proj']: + qkv[prefix][module + '.' + param] = val + else: + ret[key] = val + + for prefix, param_dict in qkv.items(): + # Stitch qkv params together + assert len(param_dict) == 6 + ret[f"{prefix}qkv.weight"] = torch.cat( + [param_dict[f"{k}_proj.weight"] for k in ["q", "k", "v"]], + dim=0) + ret[f"{prefix}qkv.bias"] = torch.cat( + [param_dict[f"{k}_proj.bias"] for k in ["q", "k", "v"]], + dim=0) + + super().load_state_dict(ret) + + def forward(self, inp, attn_mask=None): + inp = inp.permute(1, 0, 2) # (T, B, H) -> (B, T, H) + + if self.pre_lnorm: + inp = self.layer_norm(inp) + + n_head, d_head = self.n_head, self.d_head + + head_q, head_k, head_v = torch.chunk(self.qkv(inp), 3, dim=2) + + head_q = head_q.view(inp.size(0), inp.size(1), n_head, d_head) + head_k = head_k.view(inp.size(0), inp.size(1), n_head, d_head) + head_v = head_v.view(inp.size(0), inp.size(1), n_head, d_head) + + q = head_q.permute(2, 0, 1, 3).reshape(-1, inp.size(1), d_head) + k = head_k.permute(2, 0, 1, 3).reshape(-1, inp.size(1), d_head) + v = head_v.permute(2, 0, 1, 3).reshape(-1, inp.size(1), d_head) + + attn_score = torch.bmm(q, k.transpose(1, 2)) + attn_score.mul_(self.scale) + + if attn_mask is not None: + attn_mask = attn_mask.unsqueeze(1).to(attn_score.dtype) + attn_mask = attn_mask.repeat(n_head, attn_mask.size(2), 1) + attn_score.masked_fill_(attn_mask.to(torch.bool), -float('inf')) + + attn_prob = self.softmax(attn_score) + attn_prob = self.dropatt(attn_prob) + attn_vec = torch.bmm(attn_prob, v) + + attn_vec = attn_vec.view(n_head, inp.size(0), inp.size(1), d_head) + attn_vec = attn_vec.permute(1, 2, 0, 3).contiguous().view( + inp.size(0), inp.size(1), n_head * d_head) + + output = self.proj(attn_vec) + + return output.permute(1, 0, 2) # (B, T, H) -> (T, B, H) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/sampler.py b/PyTorch/SpeechRecognition/wav2vec2/common/sampler.py new file mode 100644 index 000000000..3a83aa076 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/sampler.py @@ -0,0 +1,230 @@ +# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import TypeVar, List + +import torch +import numpy as np +from torch.utils.data import (RandomSampler, Sampler, + DistributedSampler as TorchDistributedSampler) + +from common.fairseq.data import data_utils + +T = TypeVar('T') + + +class DistributedSampler(Sampler): + def __init__(self, dataset, batch_size, world_size, rank): + """ + Constructor for the DistributedSampler. + :param dataset: dataset + :param batch_size: local batch size + :param world_size: number of distributed workers + :param rank: rank of the current process + """ + self.dataset = dataset + self.world_size = world_size + self.rank = rank + self.epoch = 0 + + self.batch_size = batch_size + self.global_batch_size = batch_size * world_size + + self.data_len = len(self.dataset) + + self.num_samples = self.data_len // self.global_batch_size \ + * self.global_batch_size + + def distribute_batches(self, indices): + """ + Assigns batches to workers. + Consecutive ranks are getting consecutive batches. + :param indices: torch.tensor with batch indices + """ + assert len(indices) == self.num_samples + + indices = indices.view(-1, self.batch_size) + indices = indices[self.rank::self.world_size].contiguous() + indices = indices.view(-1) + indices = indices.tolist() + + assert len(indices) == self.num_samples // self.world_size + return indices + + def reshuffle_batches(self, indices, rng): + """ + Permutes global batches + :param indices: torch.tensor with batch indices + :param rng: instance of torch.Generator + """ + indices = indices.view(-1, self.global_batch_size) + num_batches = indices.shape[0] + order = torch.randperm(num_batches, generator=rng) + indices = indices[order, :] + indices = indices.view(-1) + return indices + + def __iter__(self): + g = torch.Generator() + g.manual_seed(self.epoch) + # generate permutation + indices = torch.randperm(self.data_len, generator=g) + + # make indices evenly divisible by (batch_size * world_size) + indices = indices[:self.num_samples] + + # assign batches to workers + indices = self.distribute_batches(indices) + return iter(indices) + + def set_epoch(self, epoch): + """ + Sets current epoch index. + Epoch index is used to seed RNG in __iter__() function. + :param epoch: index of current epoch + """ + self.epoch = epoch + + def __len__(self): + return self.num_samples // self.world_size + + +class BucketingSampler(DistributedSampler): + def __init__(self, dataset, batch_size, num_buckets, world_size, rank): + """ + Bucketing sampler with approx. equally-sized buckets. + :param dataset: dataset + :param batch_size: local batch size + :param seeds: list of seeds, one seed for each training epoch + :param num_buckets: number of buckets + :param world_size: number of distributed workers + :param rank: rank of the current process + """ + super().__init__(dataset, batch_size, world_size, rank) + + self.num_buckets = num_buckets + len_ids = np.argsort([sample['duration'] + for sample in dataset.samples]) + self.buckets = [torch.from_numpy(t) + for t in np.array_split(len_ids, num_buckets)] + + def __iter__(self): + g = torch.Generator() + g.manual_seed(self.epoch) + global_bsz = self.global_batch_size + + indices = [] + for bid in range(self.num_buckets): + # random shuffle within current bucket + perm = torch.randperm(len(self.buckets[bid]), generator=g) + bucket_indices = self.buckets[bid][perm] + + # add samples from current bucket to indices for current epoch + indices.append(bucket_indices) + + indices = torch.cat(indices) + + # make indices evenly divisible by global batch size + length = len(indices) // global_bsz * global_bsz + indices = indices[:length] + + assert len(indices) % self.global_batch_size == 0 + + # perform global reshuffle of all global batches + indices = self.reshuffle_batches(indices, g) + # distribute batches to individual workers + indices = self.distribute_batches(indices) + return iter(indices) + + +class DistributedIndicesSampler(TorchDistributedSampler): + """ DistributedSampler operating on indices. + + Differences wrt. DistributedSampler: + 1) use Numpy RNG instead of PyTorch RNG + 2) treat `self.dataset` as indices - DistributedSampler assumes indices + are determined with `range(len(self.dataset))` + 3) if `drop_last` is False, pad indices with `fillvalue` + or don't pad at all if `fillvalue` is None (useful for validation) + """ + def __init__(self, *args, fillvalue=None, **kwargs): + super().__init__(*args, **kwargs) + self.fillvalue = fillvalue + if not self.drop_last and self.fillvalue is None: + self.total_size = len(self.dataset) + # possibly different num_samples for each device, + # this will work with DDP only for validation + self.num_samples = len(range(self.rank, self.total_size, + self.num_replicas)) + + def __iter__(self): + indices = list(self.dataset) + if self.shuffle: + # deterministically shuffle based on epoch and seed + with data_utils.numpy_seed(self.seed + self.epoch): + np.random.shuffle(indices) + + if not self.drop_last: + if self.fillvalue is not None: + # add extra samples to make it evenly divisible + padding_size = self.total_size - len(indices) + indices += [self.fillvalue] * padding_size + else: + # remove tail of data to make it evenly divisible. + indices = indices[:self.total_size] + assert len(indices) == self.total_size + + # subsample + indices = indices[self.rank:self.total_size:self.num_replicas] + assert len(indices) == self.num_samples + + return iter(indices) + + +class RandomSeedableSampler(RandomSampler): + def __init__(self, *args, generator=None, seed=0, **kwargs): + if generator is None: + generator = torch.Generator() + if seed is not None: + generator.manual_seed(seed) + super().__init__(*args, generator=generator, **kwargs) + self.epoch = 0 + self.seed = seed + + def __iter__(self): + self.generator.manual_seed(self.seed + self.epoch) + return super().__iter__() + + def set_epoch(self, epoch: int) -> None: + """ Allows reproducibility after resuming training. """ + self.epoch = epoch + + +class IndexMappingSampler(Sampler[T]): + """ Transforms index-based sampler to arbitrary one, e.g. batch-based. """ + def __init__(self, indices_map: List[T], base_sampler: Sampler[int]): + super().__init__(indices_map) + self.base_sampler = base_sampler + self.indices_map = indices_map + assert len(self.base_sampler) <= len(indices_map) + + def __iter__(self): + return map(lambda ind: self.indices_map[ind], iter(self.base_sampler)) + + def __len__(self): + return len(self.base_sampler) + + def set_epoch(self, epoch: int) -> None: + """ Allows reproducibility after resuming training. """ + self.base_sampler.set_epoch(epoch) diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/tb_dllogger.py b/PyTorch/SpeechRecognition/wav2vec2/common/tb_dllogger.py new file mode 100644 index 000000000..9a0e6d3e7 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/tb_dllogger.py @@ -0,0 +1,131 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import atexit +import glob +import os +import re +from pathlib import Path + +import numpy as np +import torch +from torch.utils.tensorboard import SummaryWriter + +import dllogger + + +tb_loggers = {} + + +class TBLogger: + """ + xyz_dummies: stretch the screen with empty plots so the legend would + always fit for other plots + """ + def __init__(self, enabled, log_dir, name, interval=1, dummies=True): + self.enabled = enabled + self.interval = interval + self.cache = {} + if self.enabled: + self.summary_writer = SummaryWriter( + log_dir=os.path.join(log_dir, name), + flush_secs=120, max_queue=200) + atexit.register(self.summary_writer.close) + if dummies: + for key in ('_', '✕'): + self.summary_writer.add_scalar(key, 0.0, 1) + + def log(self, step, data): + for k, v in data.items(): + self.log_value(step, k, v.item() if type(v) is torch.Tensor else v) + + def log_value(self, step, key, val, stat='mean'): + if self.enabled: + if key not in self.cache: + self.cache[key] = [] + self.cache[key].append(val) + if len(self.cache[key]) == self.interval: + agg_val = getattr(np, stat)(self.cache[key]) + self.summary_writer.add_scalar(key, agg_val, step) + del self.cache[key] + + def log_grads(self, step, model): + if self.enabled: + norms = [p.grad.norm().item() for p in model.parameters() + if p.grad is not None] + for stat in ('max', 'min', 'mean'): + self.log_value(step, f'grad_{stat}', getattr(np, stat)(norms), + stat=stat) + + +def unique_log_fpath(fpath): + """Have a unique log filename for every separate run""" + log_num = max([0] + [int(re.search("\.(\d+)", Path(f).suffix).group(1)) + for f in glob.glob(f"{fpath}.*")]) + return f"{fpath}.{log_num + 1}" + + +def stdout_step_format(step): + if isinstance(step, str): + return step + fields = [] + if len(step) > 0: + fields.append("epoch {:>4}".format(step[0])) + if len(step) > 1: + fields.append("iter {:>3}".format(step[1])) + if len(step) > 2: + fields[-1] += "/{}".format(step[2]) + return " | ".join(fields) + + +def stdout_metric_format(metric, metadata, value): + name = metadata.get("name", metric + " : ") + unit = metadata.get("unit", None) + fmt = f'{{{metadata.get("format", "")}}}' + fields = [name, fmt.format(value) if value is not None else value, unit] + fields = [f for f in fields if f is not None] + return "| " + " ".join(fields) + + +def log(when, metrics={}, scope='train', flush_log=False, tb_iter=None): + + dllogger.log(when, data=metrics.get_metrics(scope, 'dll')) + + if tb_iter is not None: + tb_loggers[scope].log(tb_iter, metrics.get_metrics(scope, 'tb')) + + if flush_log: + flush() + + +def log_grads_tb(tb_total_steps, grads, tb_subset='train'): + tb_loggers[tb_subset].log_grads(tb_total_steps, grads) + + +def log_parameters(data, verbosity=0, tb_subset=None): + for k, v in data.items(): + v = str(v) if isinstance(v, Path) else v + dllogger.log(step="PARAMETER", data={k: v}, verbosity=verbosity) + + if tb_subset is not None and tb_loggers[tb_subset].enabled: + tb_data = {k: v for k, v in data.items() + if type(v) in (str, bool, int, float)} + tb_loggers[tb_subset].summary_writer.add_hparams(tb_data, {}) + + +def flush(): + dllogger.flush() + for tbl in tb_loggers.values(): + if tbl.enabled: + tbl.summary_writer.flush() diff --git a/PyTorch/SpeechRecognition/wav2vec2/common/utils.py b/PyTorch/SpeechRecognition/wav2vec2/common/utils.py new file mode 100644 index 000000000..1e50818c4 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/common/utils.py @@ -0,0 +1,73 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +import torch +import torch.distributed as dist + + +def print_once(*msg, local_rank=0): + """Single stdout print with multiple processes.""" + if dist.is_initialized(): + if dist.get_rank() == 0: + print(*msg) + elif int(os.environ.get('WORLD_SIZE', 1)) == 1: + print(*msg) + elif int(os.environ.get('RANK', 0)) == 0 and local_rank == 0: + print(*msg) + + +class AttrDict(dict): + def __init__(self, *args, **kwargs): + super(AttrDict, self).__init__(*args, **kwargs) + self.__dict__ = self + + +def set_torch_seed(seed): + torch.manual_seed(seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed(seed) + + +def reduce_tensor(tensor, world_size, mean=True): + if world_size == 1: + return tensor + rt = tensor.clone() + dist.all_reduce(rt, op=dist.ReduceOp.SUM) + if mean: + rt = rt.true_divide(world_size) + return rt + + +def all_reduce_cpu_scalars(data, device=torch.device('cuda')): + data_keys = list(data.keys()) + data_vals = list(data.values()) + tensor_vals = torch.tensor(data_vals, dtype=torch.double, device=device) + dist.all_reduce(tensor_vals, op=dist.ReduceOp.SUM) + data_vals = tensor_vals.cpu().numpy() + return dict(zip(data_keys, data_vals)) + + +def setup_distributed(local_rank): + multi_gpu = int(os.environ.get('WORLD_SIZE', 1)) > 1 + if multi_gpu: + torch.cuda.set_device(local_rank) + dist.init_process_group(backend='nccl', init_method='env://') + world_size = dist.get_world_size() + print_once(f'Distributed training with {world_size} GPUs\n') + else: + world_size = 1 + + return world_size diff --git a/PyTorch/SpeechRecognition/wav2vec2/img/finetuning_wer.png b/PyTorch/SpeechRecognition/wav2vec2/img/finetuning_wer.png new file mode 100644 index 000000000..7338cbce2 Binary files /dev/null and b/PyTorch/SpeechRecognition/wav2vec2/img/finetuning_wer.png differ diff --git a/PyTorch/SpeechRecognition/wav2vec2/img/hourglass.jpg b/PyTorch/SpeechRecognition/wav2vec2/img/hourglass.jpg new file mode 100644 index 000000000..69dffab44 Binary files /dev/null and b/PyTorch/SpeechRecognition/wav2vec2/img/hourglass.jpg differ diff --git a/PyTorch/SpeechRecognition/wav2vec2/img/model.jpg b/PyTorch/SpeechRecognition/wav2vec2/img/model.jpg new file mode 100644 index 000000000..1ef478050 Binary files /dev/null and b/PyTorch/SpeechRecognition/wav2vec2/img/model.jpg differ diff --git a/PyTorch/SpeechRecognition/wav2vec2/img/pretraining_acc.png b/PyTorch/SpeechRecognition/wav2vec2/img/pretraining_acc.png new file mode 100644 index 000000000..c6838889b Binary files /dev/null and b/PyTorch/SpeechRecognition/wav2vec2/img/pretraining_acc.png differ diff --git a/PyTorch/SpeechRecognition/wav2vec2/inference.py b/PyTorch/SpeechRecognition/wav2vec2/inference.py new file mode 100644 index 000000000..0efc07aac --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/inference.py @@ -0,0 +1,334 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import io +import math +import os +import random +import time +import warnings +from argparse import ArgumentParser +from heapq import nlargest +from itertools import chain, repeat +from pathlib import Path +from tqdm import tqdm + +import dllogger +import numpy as np +import torch +import torch.distributed as distrib +from dllogger import JSONStreamBackend, StdOutBackend, Verbosity + +import wav2vec2.arg_parser +import wav2vec2.utils +import common.fairseq.utils as utils +from common.fairseq.data import Dictionary +from common.helpers import (gather_predictions, gather_transcripts, + load_wrapped_state, process_evaluation_epoch) +from common.tb_dllogger import stdout_metric_format, unique_log_fpath +from common.utils import print_once +from torch.utils.data import DataLoader, DistributedSampler +from wav2vec2.logging import init_infer_metadata + + +def durs_to_percentiles(durations, ratios): + durations = np.asarray(durations) * 1000 # in ms + latency = durations + + latency = latency[5:] + mean_latency = np.mean(latency) + + latency_worst = nlargest(math.ceil((1 - min(ratios)) * len(latency)), + latency) + latency_ranges = get_percentile(ratios, latency_worst, len(latency)) + latency_ranges[0.5] = mean_latency + return latency_ranges + + +def get_percentile(ratios, arr, nsamples): + res = {} + for a in ratios: + idx = max(int(nsamples * (1 - a)), 0) + res[a] = arr[idx] + return res + + +def fp_convert_batch(batch, precision): + + dt = {'fp32': torch.float32, 'fp16': torch.half, + 'bf16': torch.bfloat16}[precision] + + def maybe_cast(t): + if t.dtype is torch.float32: + return t.to(dtype=dt) + return t + + return utils.apply_to_sample(maybe_cast, batch) + + +def main(): + parser = ArgumentParser(description='wav2vec2.0 inference') + wav2vec2.arg_parser.populate_infer(parser) + args = parser.parse_args() + + ckpt = torch.load(args.w2v_path, map_location=torch.device("cpu")) + train_args = wav2vec2.utils.get_ckpt_args(ckpt) + is_nv_ckpt = "mode" in train_args + + if is_nv_ckpt: + print("Loaded a model trained with NVIDIA DLE") + args.fp32_pos_conv = train_args.get("fp32_pos_conv", + args.fp16 or args.bf16) + args.fp32_conv_norms = train_args.get("fp32_conv_norms", args.fp16) + else: + args.fp32_pos_conv = args.fp16 + args.fp32_conv_norms = args.fp16 + + args.fp32_pos_conv = True + args.fp32_conv_norms = True + + log_fpath = args.log_file or str(Path(args.output_dir, 'nvlog_infer.json')) + dllogger.init(backends=[ + JSONStreamBackend(Verbosity.DEFAULT, log_fpath, append=True), + JSONStreamBackend(Verbosity.DEFAULT, unique_log_fpath(log_fpath)), + StdOutBackend(Verbosity.VERBOSE, metric_format=stdout_metric_format) + ]) + [dllogger.log("PARAMETER", {k: v}) for k, v in vars(args).items()] + init_infer_metadata() + + if ((train_args.get("fp16", False) or train_args.get("amp", False)) + and args.bf16): + warnings.warn('Using FP16 ckpts in BF16 precision.') + if train_args.get("bf16", False) and args.fp16: + warnings.warn('Using BF16 ckpts in FP16 precision.') + + # load output labels - either from a file, or stored inside an nv ckpt + assert args.labels_path is not None or is_nv_ckpt + if args.labels_path is None: + f = io.StringIO(ckpt["output_labels"]) + else: + f = open(args.labels_path) + target_dictionary = Dictionary.load(f) + f.close() + + w2v_path_for_args = args.w2v_path_for_args or args.w2v_path + wav2vec2.utils.update_args_for_finetuning(args, w2v_path_for_args) + + # "default" GroupNorm might leak padding + args.masked_feature_extractor = True + + if args.torchscript: + from common.fairseq.modules import layer_norm + layer_norm.TORCHSCRIPT = True + + model, *_ = wav2vec2.utils.build_model(args, "infer", target_dictionary) + + load_wrapped_state(model, ckpt["model"]) + + model.w2v_encoder.w2v_model.remove_conv_wn() + model.w2v_encoder.w2v_model.feature_extractor.forward = \ + model.w2v_encoder.w2v_model.feature_extractor.masked_forward + model.w2v_encoder.forward = model.w2v_encoder.infer + model.w2v_encoder.w2v_model.forward = model.w2v_encoder.w2v_model.infer + + if args.cpu: + device = torch.device('cpu') + else: + assert torch.cuda.is_available() + device = torch.device('cuda') + torch.backends.cudnn.benchmark = args.cudnn_benchmark + + if args.seed is not None: + torch.manual_seed(args.seed + args.local_rank) + np.random.seed(args.seed + args.local_rank) + random.seed(args.seed + args.local_rank) + + # set up distributed training + multi_gpu = not args.cpu and int(os.environ.get('WORLD_SIZE', 1)) > 1 + if multi_gpu: + torch.cuda.set_device(args.local_rank) + distrib.init_process_group(backend='nccl', init_method='env://') + print_once(f'Inference with {distrib.get_world_size()} GPUs') + + measure_perf = args.steps > 0 + + # Compliance with fairseq dataloader + assert args.batch_size is not None + args.min_sample_size = None + args.max_sample_size = None + + if args.transcribe_wav or args.transcribe_filelist: + assert args.max_duration is None and not measure_perf + assert not (args.transcribe_wav and args.transcribe_filelist) + assert args.labels is None, "Labels won't be used during trainscribing" + assert not multi_gpu, ( + "multigpu is currently supported only for WER/perf measurements") + + if args.transcribe_wav: + dataset = wav2vec2.utils.single_audio_dataset(args.transcribe_wav, + args) + else: + dataset = wav2vec2.utils.load_dataset(args.transcribe_filelist, + args, target_dictionary) + data_loader = DataLoader( + dataset=dataset, + batch_size=args.batch_size, + shuffle=False, + collate_fn=dataset.collater, + num_workers=args.num_workers, + pin_memory=True, + persistent_workers=args.num_workers > 0, + drop_last=False, + ) + + else: # compute WER or measure perf + assert args.labels is not None or measure_perf + + dataset = wav2vec2.utils.load_dataset(args.valid_subset, args, + target_dictionary, + with_labels=True) + sampler = DistributedSampler( + dataset, + shuffle=False, + drop_last=False + ) if multi_gpu else None + + data_loader = DataLoader( + dataset=dataset, + batch_size=args.batch_size, + sampler=sampler, + shuffle=False, + collate_fn=dataset.collater, + num_workers=args.num_workers, + pin_memory=True, + persistent_workers=args.num_workers > 0, + drop_last=(True if measure_perf else False), + ) + + model.to(device) + model.eval() + + assert args.amp == args.fp16, 'During inference these are equivalent' + if args.fp16: + model = model.half() + if args.bf16: + model = model.to(dtype=torch.bfloat16) + + if (args.fp16 or args.bf16) and args.fp32_pos_conv: + model.w2v_encoder.w2v_model.encoder.pos_conv.to(dtype=torch.float32) + + if args.torchscript: + print("Attempting TorchScript export...") + model = torch.jit.script(model) + + agg = {'txts': [], 'preds': [], 'logits': [], 'ids': []} + dur = {'data': [], 'dnn': [], 'data+dnn': []} + + looped_loader = chain.from_iterable(repeat(data_loader)) + + sync = lambda: torch.cuda.synchronize() if device.type == 'cuda' else None + steps = args.steps + args.warmup_steps or len(data_loader) + + desc = 'warmup' if args.warmup_steps > 0 else 'inference' + pbar = tqdm(looped_loader, initial=1, total=steps, desc=desc) + for it, batch in enumerate(pbar): + if it == args.warmup_steps: + pbar.set_description('inference') + + batch = utils.move_to_cuda(batch) + + sync() + t1 = time.time() + + if args.fp16: + batch = fp_convert_batch(batch, 'fp16') + if args.bf16: + batch = fp_convert_batch(batch, 'bf16') + + with torch.no_grad(): + enc_out, padding_mask = model(batch["net_input"]["source"], + batch["net_input"]["padding_mask"]) + logp = model.get_normalized_probs(enc_out, + padding_mask, + log_probs=True).contiguous() + # greedy decoding + preds = logp.argmax(dim=-1, keepdim=False).int() + + sync() + t2 = time.time() + + # burn-in period; wait for a new loader due to num_workers + if it >= 1 and (args.steps == 0 or it >= args.warmup_steps): + dur['data'].append(t1 - t0) + dur['dnn'].append(t2 - t1) + dur['data+dnn'].append(t2 - t0) + + preds = preds.transpose(0, 1) + agg['preds'] += gather_predictions([preds], + target_dictionary, + blank_id=0) + agg['logits'].append(logp) + + if 'target' in batch: + agg['txts'] += gather_transcripts([batch['target']], + [batch['target_lengths']], + target_dictionary) + if multi_gpu: + # ids are needed to remove duplicates in multi_gpu inference + agg['ids'] += batch['id'].tolist() + + if it + 1 == steps: + break + + sync() + t0 = time.time() + + tdict = target_dictionary + agg['preds'] = [pred.replace(tdict[tdict.nspecial], ' ') + for pred in agg['preds']] + agg['txts'] = [txt.replace(tdict[tdict.nspecial], ' ') + for txt in agg['txts']] + + # communicate the results + if args.transcribe_wav or args.transcribe_filelist: + for idx, p in enumerate(agg['preds']): + print_once(f'Prediction {idx + 1: >3}: {p}') + + elif args.valid_subset and not measure_perf: + wer, _ = process_evaluation_epoch(agg) + if not multi_gpu or distrib.get_rank() == 0: + dllogger.log(step=(), data={'eval_wer': 100 * wer}) + + if args.save_predictions and (not multi_gpu or distrib.get_rank() == 0): + with open(args.save_predictions, 'w') as f: + f.write('\n'.join(agg['preds'])) + + if args.save_logits and (not multi_gpu or distrib.get_rank() == 0): + logits = torch.cat(agg['logits'], dim=0).cpu() + torch.save(logits, args.save_logits) + + # report timings + if len(dur['data']) >= 20 and (not multi_gpu or distrib.get_rank() == 0): + ratios = [0.9, 0.95, 0.99] + for stage in dur: + lat = durs_to_percentiles(dur[stage], ratios) + for k in [0.99, 0.95, 0.9, 0.5]: + k_ = str(k).replace('.', '_') + dllogger.log(step=(), data={f'{stage}_latency_{k_}': lat[k]}) + else: + print_once('Not enough samples to measure latencies.') + + +if __name__ == "__main__": + main() diff --git a/PyTorch/SpeechRecognition/wav2vec2/requirements.txt b/PyTorch/SpeechRecognition/wav2vec2/requirements.txt new file mode 100644 index 000000000..d8091ebbe --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/requirements.txt @@ -0,0 +1,8 @@ +editdistance==0.6.0 +librosa==0.10.1 +omegaconf==2.0.6 # optional for handling certain Fairseq ckpts +pyarrow==6.0.1 +soundfile==0.12.1 +sox==1.4.1 +tqdm==4.53.0 +git+https://github.com/NVIDIA/dllogger@v1.0.0#egg=dllogger diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/build.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/docker/build.sh old mode 100644 new mode 100755 similarity index 77% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/build.sh rename to PyTorch/SpeechRecognition/wav2vec2/scripts/docker/build.sh index 0cb32459d..790c5251c --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/build.sh +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/docker/build.sh @@ -1,11 +1,12 @@ #!/usr/bin/env bash -# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -13,4 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -docker build -t tft . -f Dockerfile + +docker build . --rm -t wav2vec2 diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/docker/run.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/docker/run.sh new file mode 100755 index 000000000..130b01f07 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/docker/run.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +SCRIPT_DIR=$(cd $(dirname $0); pwd) + +: ${DATASET_DIR:=$SCRIPT_DIR/../../datasets} + +set -eux + +docker run -it --rm \ + --gpus all \ + --env PYTHONDONTWRITEBYTECODE=1 \ + --ipc=host \ + -v "$DATASET_DIR:/datasets" \ + -v "$SCRIPT_DIR/../..:/workspace/wav2vec2" \ + wav2vec2:latest bash diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/prepare_datasets.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/download_data.sh old mode 100644 new mode 100755 similarity index 67% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/prepare_datasets.sh rename to PyTorch/SpeechRecognition/wav2vec2/scripts/download_data.sh index 7850b11ad..bab7405b3 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/prepare_datasets.sh +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/download_data.sh @@ -1,4 +1,6 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,11 +13,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -#!/usr/bin/env bash +set -e -echo "Please provide download operation for electricity provided in Pipeline from NGC: 94133" -exit 1 +: ${DATASET_DIR:=/datasets/} +: ${SUBSETS:="train-clean-100 train-clean-360 train-other-500 dev-clean dev-other test-clean test-other"} -echo "Please provide download operation for traffic provided in Pipeline from NGC: 84300" -exit 1 +python3 utils/download_librispeech.py $DATASET_DIR --subsets $SUBSETS diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_100h.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_100h.sh new file mode 100755 index 000000000..ab93db487 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_100h.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +# A100 80GiB FP16: UPDATE_FREQ=1 +# A100 80GiB TF32: UPDATE_FREQ=1 + +# IO +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${TRAIN_SUBSET:="train-clean-100"} +: ${OUTPUT_DIR:="results/finetune_base_100h"} +: ${PRETRAINED_MODEL:=results/finetune_base/wav2vec2_update400000.pt} +# Batching +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=3200000} +: ${NUM_CONCAT_BATCHES:=1} +: ${UPDATE_FREQ:=1} +# Training +: ${LEARNING_RATE:=0.00003} +: ${FREEZE_FINETUNE_UPDATES:=0} +: ${MAX_UPDATE:=80000} +: ${MASK_CHANNEL_PROB:=0.5} +: ${MASK_PROB:=0.65} + +bash scripts/finetune_vox_960h.sh "$@" diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_10h.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_10h.sh new file mode 100755 index 000000000..c29778fbb --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_10h.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +# A100 80GiB FP16: UPDATE_FREQ=1 +# A100 80GiB TF32: UPDATE_FREQ=1 + +# IO +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${TRAIN_SUBSET:="train-10h"} +: ${OUTPUT_DIR:="results/finetune_base_10h"} +: ${PRETRAINED_MODEL:=results/pretrain_base/wav2vec2_update400000.pt} +# Batching +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=3200000} +: ${NUM_CONCAT_BATCHES:=1} +: ${UPDATE_FREQ:=1} +# Training +: ${LEARNING_RATE:=0.00005} +: ${FREEZE_FINETUNE_UPDATES:=10000} +: ${MAX_UPDATE:=20000} +: ${MASK_CHANNEL_PROB:=0.5} +: ${MASK_PROB:=0.65} +: ${LAYERDROP:=0.05} + +bash scripts/finetune_vox_960h.sh "$@" diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_1h.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_1h.sh new file mode 100755 index 000000000..2be3797f9 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_1h.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +# A100 80GiB FP16: UPDATE_FREQ=1 +# A100 80GiB TF32: UPDATE_FREQ=1 + +# IO +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${TRAIN_SUBSET:="train-1h"} +: ${OUTPUT_DIR:="results/finetune_base_1h"} +: ${PRETRAINED_MODEL:=results/pretrain_base/wav2vec2_update400000.pt} +# Batching +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=3200000} +: ${NUM_CONCAT_BATCHES:=1} +: ${UPDATE_FREQ:=1} +# Training +: ${LEARNING_RATE:=0.00005} +: ${FREEZE_FINETUNE_UPDATES:=10000} +: ${MAX_UPDATE:=13000} +: ${MASK_CHANNEL_PROB:=0.25} +: ${MASK_PROB:=0.65} + +bash scripts/finetune_vox_960h.sh "$@" diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_960h.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_960h.sh new file mode 100755 index 000000000..707e0f910 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_960h.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +# A100 80GiB BF16: NUM_CONCAT_BATCHES=1 +# A100 80GiB TF32: NUM_CONCAT_BATCHES=1 + +# IO +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${TRAIN_SUBSET:="train-full-960"} +: ${OUTPUT_DIR:="results/finetune_base_960h"} +: ${PRETRAINED_MODEL:=results/pretrain_base/wav2vec2_update400000.pt} +# Batching +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=3200000} +: ${NUM_CONCAT_BATCHES:=1} +: ${UPDATE_FREQ:=1} +# Training +: ${LEARNING_RATE:=0.0001} +: ${FREEZE_FINETUNE_UPDATES:=0} +: ${MAX_UPDATE:=320000} +: ${MASK_CHANNEL_PROB:=0.1} +: ${MASK_PROB:=0.5} + +bash scripts/finetune_vox_960h.sh "$@" diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_benchmark.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_benchmark.sh new file mode 100755 index 000000000..ed5327f4f --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_base_benchmark.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +: ${NUM_WARMUP_EPOCHS:=2} # Number of warmup epochs +: ${NUM_EPOCHS:=5} # Number of epochs for collecting perf measurements +: ${PRETRAINED_MODEL:="results/pretrain_base/wav2vec2_update400000.pt"} +: ${TRAIN_SUBSET:="train-full-960"} + +: ${FP16:=false} +: ${BF16:=false} +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=3200000} +: ${NUM_CONCAT_BATCHES:=1} +: ${UPDATE_FREQ:=1} + +if [ "$FP16" = true ]; then PREC=fp16; elif [ "$BF16" = true ]; then PREC=bf16; else PREC=fp32; fi +: ${OUTPUT_DIR:="results/finetune_base_benchmark_${NUM_GPUS}x${MAX_TOKENS}x${NUM_CONCAT_BATCHES}x${UPDATE_FREQ}_${PREC}"} + +NO_SAVE=true +EPOCHS_THIS_JOB=$(($NUM_EPOCHS + $NUM_WARMUP_EPOCHS)) +ARGS+=" --benchmark_epochs_num $NUM_EPOCHS" + +bash scripts/finetune_base_960h.sh diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_100h.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_100h.sh new file mode 100755 index 000000000..060c891bf --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_100h.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +# A100 80GiB FP16: UPDATE_FREQ=1 +# A100 80GiB TF32: UPDATE_FREQ=1 + +# IO +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${TRAIN_SUBSET:="train-clean-100"} +: ${OUTPUT_DIR:="results/finetune_large_100h"} +# Batching +# We train with effective world_size=16; the reference sets for world_size=20 +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=1280000} +: ${NUM_CONCAT_BATCHES:=2} +: ${UPDATE_FREQ:=1} +# Training +: ${MAX_UPDATE:=80000} +: ${MASK_CHANNEL_PROB:=0.5} +: ${MASK_PROB:=0.5} + +bash scripts/finetune_vox_960h.sh "$@" diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_960h.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_960h.sh new file mode 100755 index 000000000..88acc7588 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_960h.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +export OMP_NUM_THREADS=1 +export CUDNN_V8_API_ENABLED=1 # For older containers (~22.01) +export TORCH_CUDNN_V8_API_ENABLED=1 + +# IO +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${TRAIN_SUBSET:="train-full-960"} +: ${VALID_SUBSET:="dev-other"} +: ${OUTPUT_DIR:="results/finetune_large_960h"} +# Batching +# To best utilize hw, increase batch size by increasing NUM_CONCAT_BATCHES, and lowering UPDATE_FREQ. +# Keep NUM_NODES x $NUM_GPUS x $NUM_CONCAT_BATCHES x $UPDATE_FREQ = 24. +# Note that this script does not control NUM_NODES. +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=1280000} +: ${NUM_CONCAT_BATCHES:=3} +: ${UPDATE_FREQ:=1} +# Training +: ${MAX_UPDATE:=320000} +: ${WARMUP_UPDATES:=$(($MAX_UPDATE / 10 * 1))} +: ${HOLD_UPDATES:=$(($MAX_UPDATE / 10 * 4))} +: ${FREEZE_FINETUNE_UPDATES:=10000} +: ${BATCH_SIZE:=} +: ${LEARNING_RATE:=0.00003} +: ${FP16:=false} +: ${BF16:=false} +: ${EMA:=0.0} # XXX +: ${SEED:=1} # XXX +: ${CUDNN_BENCHMARK:=false} +# Model +: ${PRETRAINED_MODEL:=pretrained_models/libri960_big.pt} +: ${MASK_PROB:=0.5} +: ${MASK_CHANNEL_PROB:=0.25} +: ${ENCODER_LAYERDROP:=0.1} +# Misc +: ${NO_SAVE:=false} +: ${SAVE_FREQUENCY:=10} +: ${DISTRIBUTED="-m torch.distributed.launch --nproc_per_node=$NUM_GPUS"} + +mkdir -p "$OUTPUT_DIR" + +# ARGS+=" --no_epoch_checkpoints" +ARGS+=" --resume" +ARGS+=" --save_frequency $SAVE_FREQUENCY" + +ARGS+=" --labels ltr" +ARGS+=" --w2v_path $PRETRAINED_MODEL" + +ARGS+=" --data $DATASET_DIR" +ARGS+=" --train_subset $TRAIN_SUBSET" +ARGS+=" --valid_subset $VALID_SUBSET" +ARGS+=" --output_dir $OUTPUT_DIR" +ARGS+=" --ema $EMA" +ARGS+=" --adam_eps 1e-8" +ARGS+=" --lr $LEARNING_RATE" +ARGS+=" --lr_policy exp" +ARGS+=" --initial_lr_scale 0.01" +ARGS+=" --final_lr_scale 0.05" +ARGS+=" --warmup_updates $WARMUP_UPDATES" +ARGS+=" --hold_updates $HOLD_UPDATES" +ARGS+=" --max_update $MAX_UPDATE" +ARGS+=" --num_concat_batches $NUM_CONCAT_BATCHES" +ARGS+=" --update_freq $UPDATE_FREQ " +ARGS+=" --max_tokens $MAX_TOKENS" +ARGS+=" --max_tokens_valid $MAX_TOKENS" +ARGS+=" --freeze_finetune_updates $FREEZE_FINETUNE_UPDATES" +# Overrides +ARGS+=" --apply_mask" +ARGS+=" --mask_prob $MASK_PROB" +ARGS+=" --mask_channel_prob $MASK_CHANNEL_PROB" +ARGS+=" --mask_channel_length 64" +ARGS+=" --encoder_layerdrop $ENCODER_LAYERDROP" # NOTE This is called `layerdrop` in fairseq finetuning yamls +ARGS+=" --activation_dropout 0.1" +ARGS+=" --feature_grad_mult 0.0" +ARGS+=" --dropout_input 0.0" +ARGS+=" --dropout 0.0" +ARGS+=" --weight_decay 0.0" +ARGS+=" --mha pyt" + +# float16 +[ "$FP16" = true ] && ARGS+=" --fp16" +[ "$FP16" = true ] && ARGS+=" --fp32_cosine_sim" +[ "$FP16" = true ] && ARGS+=" --fp32_conv_norms" +[ "$FP16" = true ] && ARGS+=" --fp32_pos_conv" +# bfloat16 +[ "$BF16" = true ] && ARGS+=" --bf16" +[ "$BF16" = true ] && ARGS+=" --fp32_pos_conv" +# Misc +[ -n "$SEED" ] && ARGS+=" --seed $SEED" +[ -n "$EPOCHS_THIS_JOB" ] && ARGS+=" --epochs_this_job $EPOCHS_THIS_JOB" +[ -n "$BATCH_SIZE" ] && ARGS+=" --batch_size $BATCH_SIZE" +[ "$CUDNN_BENCHMARK" = true ] && ARGS+=" --cudnn_benchmark" +[ "$FP32_TRANSFORMER_LAYERNORM" = true ] && ARGS+=" --fp32_transformer_layernorm" +[ "$FP32_MHA_SOFTMAX" = true ] && ARGS+=" --fp32_mha_softmax" +[ "$FP32_COSINE_SIM" = true ] && ARGS+=" --fp32_cosine_sim" +[ "$FP32_POS_CONV" = true ] && ARGS+=" --fp32_pos_conv" +[ "$FP32_CONV_NORMS" = true ] && ARGS+=" --fp32_conv_norms" +[ "$NO_SAVE" = true ] && ARGS+=" --no_save" + +echo -e "\nFP16=$FP16, BP16=$BF16, ${NUM_GPUS}x(${MAX_TOKENS}x${NUM_CONCAT_BATCHES})x${UPDATE_FREQ}\n" + +set -x +python3 $DISTRIBUTED train.py finetune $ARGS "$@" + diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_960h_cv.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_960h_cv.sh new file mode 100755 index 000000000..2bedd4c40 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/finetune_vox_960h_cv.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +# The model `Wav2Vec 2.0 Large (LV-60 + CV + SWBD + FSH)` fine-tuned on LS960 +# has these changes wrt `wav2vec2_large_librivox.yaml` + +: ${MAX_UPDATE:=80000} +: ${FREEZE_FINETUNE_UPDATES:=0} +: ${LEARNING_RATE:=0.00002} +: ${MASK_PROB:=0.25} +: ${MASK_CHANNEL_PROB:=0.5} + +# Other changes (minor) +# --clip_norm=0 # =25 +# --required_seq_len_multiple=1 # =2 + +bash scripts/finetune_vox_960h.sh diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/generate_filelists.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/generate_filelists.sh new file mode 100755 index 000000000..3f353014c --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/generate_filelists.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eu + +: ${DATASET_DIR:=/datasets/LibriSpeech} +: ${FILELISTS_DIR:=$DATASET_DIR} +: ${EXT:=flac} # or wav + +mkdir -p $DATASET_DIR +mkdir -p $FILELISTS_DIR + +for SUBSET in train-clean-100 train-clean-360 train-other-500 \ + dev-clean dev-other test-clean test-other \ +; do + TSV=$FILELISTS_DIR/$SUBSET.tsv + + if [ ! -d $DATASET_DIR/$SUBSET ]; then + echo "ERROR: $DATASET_DIR/$SUBSET does not exist; skipping." + continue + fi + + python3 utils/generate_filelist.py --extension $EXT $DATASET_DIR/$SUBSET $TSV + python3 utils/libri_labels.py $TSV --output-dir $FILELISTS_DIR --output-name $SUBSET +done + +# Combine +python3 utils/combine_filelists.py $FILELISTS_DIR/train-{clean-100,clean-360,other-500}.tsv > $FILELISTS_DIR/train-full-960.tsv + +cat $FILELISTS_DIR/train-clean-100.wrd > $FILELISTS_DIR/train-full-960.wrd +cat $FILELISTS_DIR/train-clean-360.wrd >> $FILELISTS_DIR/train-full-960.wrd +cat $FILELISTS_DIR/train-other-500.wrd >> $FILELISTS_DIR/train-full-960.wrd + +cat $FILELISTS_DIR/train-clean-100.ltr > $FILELISTS_DIR/train-full-960.ltr +cat $FILELISTS_DIR/train-clean-360.ltr >> $FILELISTS_DIR/train-full-960.ltr +cat $FILELISTS_DIR/train-other-500.ltr >> $FILELISTS_DIR/train-full-960.ltr + +python3 utils/generate_dictionary.py $FILELISTS_DIR/train-full-960.ltr $FILELISTS_DIR/dict.ltr.txt diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/inference.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/inference.sh new file mode 100755 index 000000000..fcdab89ee --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/inference.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${VALID_SUBSET:="test-other"} +: ${OUTPUT_DIR:="results/inference"} +: ${NUM_GPUS:=1} +: ${BATCH_SIZE:=8} +: ${AMP:=false} +: ${BF16:=false} +: ${FP16:=false} +: ${EMA:=0.0} +: ${SEED:=1} +: ${FINETUNED_MODEL:=results/finetune_base_960h/wav2vec2_update320000.pt} +: ${MASK_PROB:=0.5} +: ${MASK_CHANNEL_PROB:=0.25} +: ${DISTRIBUTED:="-m torch.distributed.launch --nproc_per_node=$NUM_GPUS"} +# inference +: ${MAX_DURATION:=""} +: ${NUM_STEPS:=0} +: ${NUM_WARMUP_STEPS:=0} +: ${CPU:=false} +: ${LOGITS_FILE:=} +: ${PREDICTION_FILE:="${OUTPUT_DIR}/${DATASET}.predictions"} +: ${TORCHSCRIPT:=false} +: ${TORCHSCRIPT_SAVE:=false} +: ${LOG_FILE:=$OUTPUT_DIR/nvlog.json} + +mkdir -p "$OUTPUT_DIR" + +ARGS+=" --w2v_path $FINETUNED_MODEL" +ARGS+=" --data $DATASET_DIR" +ARGS+=" --valid_subset $VALID_SUBSET" +ARGS+=" --output_dir $OUTPUT_DIR" +ARGS+=" --ema $EMA" +ARGS+=" --seed $SEED" +ARGS+=" --skip_invalid_size_inputs_valid_test" +ARGS+=" --apply_mask" +ARGS+=" --mask_prob $MASK_PROB" +ARGS+=" --mask_channel_prob $MASK_CHANNEL_PROB" +ARGS+=" --mask_channel_length 64" +ARGS+=" --encoder_layerdrop 0.1" # NOTE This is called `layerdrop` in fairseq finetuning yamls +ARGS+=" --activation_dropout 0.1" +ARGS+=" --feature_grad_mult 0.0" +ARGS+=" --batch_size=$BATCH_SIZE" +ARGS+=" --steps $NUM_STEPS" +ARGS+=" --warmup_steps $NUM_WARMUP_STEPS" + +[ "$AMP" = true ] && ARGS+=" --amp --fp16" +[ "$BF16" = true ] && ARGS+=" --bf16" +[ "$TORCHSCRIPT" = true ] && ARGS+=" --torchscript" +[ "$TORCHSCRIPT_SAVE" = true ] && ARGS+=" --torchscript_export" +[ -n "$LOG_FILE" ] && ARGS+=" --log_file $LOG_FILE" +[ "$CPU" == "true" ] && ARGS+=" --cpu" +[ -n "$MAX_DURATION" ] && ARGS+=" --max_duration ${MAX_DURATION}" + +set -x +if [ $NUM_GPUS -gt 1 ]; then + python3 -m torch.distributed.launch --nproc_per_node=$NUM_GPUS inference.py $ARGS $@ +else + python3 inference.py $ARGS $@ +fi diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/inference_benchmark.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/inference_benchmark.sh new file mode 100755 index 000000000..59e4e6750 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/inference_benchmark.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${VALID_SUBSET:="test-other"} + +: ${BF16:=false} +: ${FP16:=false} +: ${NUM_GPUS:=1} +: ${BATCH_SIZE:=1} +: ${NUM_REPEATS:=10} +: ${NUM_WARMUP_REPEATS:=2} + +if [ "$FP16" = true ]; then PREC=fp16; elif [ "$BF16" = true ]; then PREC=bf16; else PREC=fp32; fi +: ${OUTPUT_DIR:="results/base_inference_benchmark_bs${BATCH_SIZE}_${PREC}"} + +NUM_SAMPLES=$(cat $DATASET_DIR/$VALID_SUBSET.ltr | wc -l) +NUM_BATCHES=$(((NUM_SAMPLES + BATCH_SIZE - 1) / BATCH_SIZE)) + +NUM_STEPS=$(($NUM_BATCHES * $NUM_REPEATS)) +NUM_WARMUP_STEPS=$(($NUM_BATCHES * $NUM_WARMUP_REPEATS)) + +bash scripts/inference.sh diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_base.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_base.sh new file mode 100755 index 000000000..afb05e672 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_base.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Pre-trains a BASE model on LibriSpeech + +set -a + +# IO +: ${OUTPUT_DIR:="results/pretrain_base"} +# Batching +# To best utilize hw, increase batch size by increasing NUM_CONCAT_BATCHES, and lowering UPDATE_FREQ. +# Keep NUM_NODES x $NUM_GPUS x $NUM_CONCAT_BATCHES x $UPDATE_FREQ = 64. +# Note that this script does not control NUM_NODES. +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=1400000} +: ${NUM_CONCAT_BATCHES:=8} +: ${UPDATE_FREQ:=1} +: ${MAX_SAMPLE_SIZE:=250000} +# Training +: ${MAX_UPDATE:=400000} +: ${LOSS_WEIGHTS:="0.1 10.0"} +: ${LEARNING_RATE:=0.0005} +# Model +: ${NORMALIZE:=false} +: ${MASK_PROB:=0.65} +: ${EXTRACTOR_MODE:="default"} +: ${LAYER_NORM_FIRST:=false} +: ${FINAL_DIM:=256} +: ${LATENT_TEMP:="2.0 0.5 0.999995"} +: ${ENCODER_LAYERDROP:=0.05} +: ${DROPOUT_INPUT:=0.1} +: ${DROPOUT_FEATURES:=0.1} +: ${DROPOUT:=0.1} +: ${ATTENTION_DROPOUT:=0.1} +: ${CONV_BIAS:=false} +: ${ENCODER_LAYERS:=12} +: ${ENCODER_EMBED_DIM:=768} +: ${ENCODER_FFN_EMBED_DIM:=3072} +: ${ENCODER_ATTENTION_HEADS:=12} +: ${FEATURE_GRAD_MULT:=0.1} +: ${HOURGLASS_CONFIG="[2,(8,4),2]"} + +bash scripts/pretrain_large.sh "$@" diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_base_benchmark.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_base_benchmark.sh new file mode 100755 index 000000000..5ab5aca87 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_base_benchmark.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -a + +: ${NUM_WARMUP_EPOCHS:=2} # Number of warmup epochs +: ${NUM_EPOCHS:=5} # Number of epochs for collecting perf measurements +: ${TRAIN_SUBSET:="train-full-960"} + +: ${FP16:=false} +: ${BF16:=false} +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=1400000} +: ${NUM_CONCAT_BATCHES:=8} +: ${UPDATE_FREQ:=1} + +if [ "$FP16" = true ]; then PREC=fp16; elif [ "$BF16" = true ]; then PREC=bf16; else PREC=fp32; fi +: ${OUTPUT_DIR:="results/pretrain_base_benchmark_${NUM_GPUS}x${MAX_TOKENS}x${NUM_CONCAT_BATCHES}x${UPDATE_FREQ}_${PREC}"} + +NO_SAVE=true +EPOCHS_THIS_JOB=$(($NUM_EPOCHS + $NUM_WARMUP_EPOCHS)) +ARGS+=" --benchmark_epochs_num $NUM_EPOCHS" + +bash scripts/pretrain_base.sh diff --git a/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_large.sh b/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_large.sh new file mode 100755 index 000000000..2067b98cb --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/scripts/pretrain_large.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Pre-trains a LARGE model on LibriSpeech + +set -e + +export OMP_NUM_THREADS=1 +export CUDNN_V8_API_ENABLED=1 # For older containers (~22.01) +export TORCH_CUDNN_V8_API_ENABLED=1 + +# IO +: ${DATASET_DIR:="/datasets/LibriSpeech"} +: ${TRAIN_SUBSET:="train-full-960"} +: ${VALID_SUBSET:="dev-other"} +: ${OUTPUT_DIR:="results/pretrain_large"} +# Batching +# To best utilize hw, increase batch size by increasing NUM_CONCAT_BATCHES, and lowering UPDATE_FREQ. +# Keep NUM_NODES x $NUM_GPUS x $NUM_CONCAT_BATCHES x $UPDATE_FREQ = 128. +# Note that this script does not control NUM_NODES. +: ${NUM_GPUS:=8} +: ${MAX_TOKENS:=1200000} +: ${NUM_CONCAT_BATCHES:=1} +: ${UPDATE_FREQ:=16} +: ${MIN_SAMPLE_SIZE:=32000} +: ${MAX_SAMPLE_SIZE:=320000} +# Training +# Fairseq 'Wav2Vec 2.0 Large (LV-60 + CV + SWBD + FSH)' model has been trained +# for 800k steps with 25.6k warmup (wav2vec2_large_librivox.yaml sets 1M/32k) +: ${MAX_UPDATE:=800000} +: ${WARMUP_UPDATES:=32000} +: ${OPTIMIZER:=adam} +: ${LEARNING_RATE:=0.005} +: ${LOSS_WEIGHTS:="0.1 0.0"} +: ${FP16:=false} +: ${BF16:=false} +: ${EMA:=0.0} +: ${SEED=""} # Disable seed - TODO check if it is working +: ${CUDNN_BENCHMARK:=false} +# Model +: ${NORMALIZE:=true} +: ${MASK_PROB:=0.65} +: ${EXTRACTOR_MODE:="layer_norm"} +: ${LAYER_NORM_FIRST:=true} # enabled in the `large` model +: ${FINAL_DIM:=768} +: ${LATENT_TEMP:="2.0 0.1 0.999995"} +: ${ENCODER_LAYERDROP:=0.0} +: ${DROPOUT_INPUT:=0.0} +: ${DROPOUT_FEATURES:=0.0} +: ${DROPOUT:=0.0} +: ${ATTENTION_DROPOUT:=0.0} +: ${CONV_BIAS:=true} +: ${ENCODER_LAYERS:=24} +: ${ENCODER_EMBED_DIM:=1024} +: ${ENCODER_FFN_EMBED_DIM:=4096} +: ${ENCODER_ATTENTION_HEADS:=16} +: ${FEATURE_GRAD_MULT:=1.0} +# Misc +: ${NO_SAVE:=false} +: ${SAVE_FREQUENCY=1} +: ${DISTRIBUTED="-m torch.distributed.launch --nproc_per_node=$NUM_GPUS"} + +mkdir -p "$OUTPUT_DIR" + +ARGS+=" --resume" +ARGS+=" --save_frequency $SAVE_FREQUENCY" +ARGS+=" --data $DATASET_DIR" +ARGS+=" --train_subset $TRAIN_SUBSET" +ARGS+=" --valid_subset $VALID_SUBSET" +ARGS+=" --output_dir $OUTPUT_DIR" +ARGS+=" --ema $EMA" +ARGS+=" --optimizer $OPTIMIZER" +ARGS+=" --lr $LEARNING_RATE" +ARGS+=" --clip_norm 25" +ARGS+=" --weight_decay 0.01" +ARGS+=" --lr_policy poly" +ARGS+=" --lr_poly_power 1.0" +ARGS+=" --loss_weights $LOSS_WEIGHTS" +ARGS+=" --warmup_updates $WARMUP_UPDATES" +ARGS+=" --max_update $MAX_UPDATE" +ARGS+=" --num_concat_batches $NUM_CONCAT_BATCHES" +ARGS+=" --update_freq $UPDATE_FREQ " +ARGS+=" --max_tokens $MAX_TOKENS" +ARGS+=" --max_tokens_valid $MAX_TOKENS" +ARGS+=" --skip_invalid_size_inputs_valid_test" # XXX ??? ??? ??? +ARGS+=" --infonce" +ARGS+=" --min_sample_size $MIN_SAMPLE_SIZE" +ARGS+=" --max_sample_size $MAX_SAMPLE_SIZE" +ARGS+=" --mask_prob $MASK_PROB" +ARGS+=" --quantize_targets" +ARGS+=" --extractor_mode $EXTRACTOR_MODE" +ARGS+=" --final_dim $FINAL_DIM" +ARGS+=" --latent_temp $LATENT_TEMP" +ARGS+=" --encoder_layerdrop $ENCODER_LAYERDROP" +ARGS+=" --dropout_input $DROPOUT_INPUT" +ARGS+=" --dropout_features $DROPOUT_FEATURES" +ARGS+=" --dropout $DROPOUT" +ARGS+=" --attention_dropout $ATTENTION_DROPOUT" +ARGS+=" --encoder_layers $ENCODER_LAYERS" +ARGS+=" --encoder_embed_dim $ENCODER_EMBED_DIM" +ARGS+=" --encoder_ffn_embed_dim $ENCODER_FFN_EMBED_DIM" +ARGS+=" --encoder_attention_heads $ENCODER_ATTENTION_HEADS" +ARGS+=" --feature_grad_mult $FEATURE_GRAD_MULT" +ARGS+=" --mha pyt" + +# float16 +[ "$FP16" = true ] && ARGS+=" --fp16" +[ "$FP16" = true ] && ARGS+=" --fp32_cosine_sim" +[ "$FP16" = true ] && ARGS+=" --fp32_conv_norms" +[ "$FP16" = true ] && ARGS+=" --fp32_pos_conv" +# bfloat16 +[ "$BF16" = true ] && ARGS+=" --bf16" +[ "$BF16" = true ] && ARGS+=" --fp32_pos_conv" +# Misc +[ "$NORMALIZE" = true ] && ARGS+=" --normalize" +[ "$CONV_BIAS" = true ] && ARGS+=" --conv_bias" +[ "$LAYER_NORM_FIRST" = true ] && ARGS+=" --layer_norm_first" +[ -n "$SEED" ] && ARGS+=" --seed $SEED" +[ -n "$EPOCHS_THIS_JOB" ] && ARGS+=" --epochs_this_job $EPOCHS_THIS_JOB" +[ "$CUDNN_BENCHMARK" = true ] && ARGS+=" --cudnn_benchmark" +[ "$FP32_TRANSFORMER_LAYERNORM" = true ] && ARGS+=" --fp32_transformer_layernorm" +[ "$FP32_MHA_SOFTMAX" = true ] && ARGS+=" --fp32_mha_softmax" +[ "$FP32_COSINE_SIM" = true ] && ARGS+=" --fp32_cosine_sim" +[ "$FP32_POS_CONV" = true ] && ARGS+=" --fp32_pos_conv" +[ "$FP32_CONV_NORMS" = true ] && ARGS+=" --fp32_conv_norms" +[ -n "$HOURGLASS_CONFIG" ] && ARGS+=" --hourglass_transformer $HOURGLASS_CONFIG" +[ "$NO_SAVE" = true ] && ARGS+=" --no_save" + +echo -e "\nFP16=$FP16, BP16=$BF16, ${NUM_GPUS}x(${MAX_TOKENS}x${NUM_CONCAT_BATCHES})x${UPDATE_FREQ}\n" + +set -x +python3 $DISTRIBUTED train.py pretrain $ARGS "$@" diff --git a/PyTorch/SpeechRecognition/wav2vec2/train.py b/PyTorch/SpeechRecognition/wav2vec2/train.py new file mode 100644 index 000000000..59a703f0e --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/train.py @@ -0,0 +1,398 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import common.filter_warnings + +import argparse +import copy +import io +import os +import sys +import random +from functools import partial +from itertools import cycle, islice +from pathlib import Path + +import torch +import numpy as np +from contextlib import suppress as empty_context +from torch.nn.parallel import DistributedDataParallel + +import wav2vec2.arg_parser +from common import tb_dllogger as logger +from common.dataset import adjust_max_tokens, get_batch_iterator +from common.fairseq.data import Dictionary +from common.fairseq.dist import ModuleProxyWrapper +from common.fairseq.utils import multiply_grads +from common.helpers import (Checkpointer, num_weights, to_gpu, + init_multi_tensor_ema, apply_multi_tensor_ema) +from common.optimizers import get_optimizer, lr_exp_policy, lr_poly_policy +from common.utils import print_once, set_torch_seed, setup_distributed +from wav2vec2.criterion import Wav2vecCriterion, CTCCriterion +from wav2vec2.logging import init_logger, W2v2Metrics, W2v2FineTuningMetrics +from wav2vec2.utils import build_model, load_dataset + + +@torch.no_grad() +def validate(epoch, step, valid_loader, model, ema_model, criterion, + val_metrics, val_ema_metrics, world_size, fp16, bf16): + + val_losses = [] + val_wer = [] + for model, metrics, scope in [(model, val_metrics, 'val'), + (ema_model, val_ema_metrics, 'val_ema')]: + if model is None: + continue + + model.eval() + criterion.eval() + metrics._start_accumulating(None, True, scope=scope) + output_keys = None + + assert len(valid_loader) > 1, ( + 'Validation needs at least 2 iterations to handle empty batches.') + + for batch in valid_loader: + is_empty_batch = len(batch) == 0 + if not is_empty_batch: + to_gpu(batch, fp16=fp16, bf16=bf16) + + loss, _, logging_output = criterion(model, batch) + + if output_keys is None: + output_keys = logging_output.keys() + + else: + assert output_keys is not None, ( + f'Invalid iters num: {len(valid_loader)}') + logging_output = {k: 0 for k in output_keys} + + logging_output['ignore'] = int(is_empty_batch) + metrics.log_scalars(logging_output) + metrics.all_reduce(world_size) + metrics.accumulate() + + metrics.finish_val(scope=scope) + logger.log(() if epoch is None else (epoch,), metrics, scope=scope, + tb_iter=step) + + val_losses.append(metrics.metrics[scope]['loss']) + if 'wer' in metrics.metrics[scope]: + val_wer.append(metrics.metrics[scope]['wer']) + model.train() + criterion.train() + + return val_losses, val_wer + + +def main(): + parser = argparse.ArgumentParser( + description='wav2vec 2.0 Deep Learning Example') + wav2vec2.arg_parser.populate(parser) + args = parser.parse_args() + + assert not args.bf16 or args.fp32_pos_conv, ( + "bfloat16 requires casting positional convolutions to float32") + + if args.mode == 'finetune': + wav2vec2.utils.update_args_for_finetuning(args, args.w2v_path) + + head = lambda list_: list_[0] # fairseq compat, scalars wrapped w/ lists + args.lr = head(args.lr) + args.update_freq = head(args.update_freq) + + assert(torch.cuda.is_available()) + torch.backends.cudnn.benchmark = args.cudnn_benchmark + + world_size = setup_distributed(args.local_rank) + args.world_size = world_size # For FP16Optimizer + print_once(f"World size: {world_size}") + + assert args.seed is not None, ( + "Random seed is used to ensure same model weights across all devices. " + "To allow None, draw a seed and synchronize across devices") + + set_torch_seed(args.seed + args.local_rank) + np.random.seed(args.seed + args.local_rank) + random.seed(args.seed + args.local_rank) + + pre_training = (args.mode == 'pretrain') + + checkpointer = Checkpointer(args, 'wav2vec2') + + if not pre_training: + assert args.labels or checkpointer.last_state, \ + "Supply output labels or resume from a checkpoint." + if checkpointer.last_state is not None: + f = io.StringIO(checkpointer.last_state["output_labels"]) + else: + f = open(Path(args.data, f"dict.{args.labels}.txt")) + target_dictionary = Dictionary.load(f) + f.seek(0) + checkpointer.output_labels = f.read() + f.close() + + Metrics = W2v2FineTuningMetrics + criterion = CTCCriterion(target_dictionary, post_process='letter') + else: + target_dictionary = None + Metrics = W2v2Metrics + criterion = Wav2vecCriterion(args) + + kw = {'benchmark_epochs': args.benchmark_epochs_num, 'cuda': not args.cpu} + metrics = Metrics(**kw) + val_metrics = Metrics(scopes=['val'], **kw) + val_ema_metrics = Metrics(scopes=['val_ema'], **kw) + + init_logger(args.output_dir, args.log_file, args.ema) + logger.log_parameters(vars(args), tb_subset='train') + + assert args.update_freq >= 1 + + model, seq_gen, tokenizer = build_model(args, args.mode, target_dictionary) + model.cuda() + print_once(f'Model size: {num_weights(model) / 10 ** 6:.1f}M params\n') + + print_once('Setting up datasets...') + train_dataset = load_dataset(args.train_subset, args, target_dictionary, + with_labels=not pre_training, training=True) + valid_dataset = load_dataset(args.valid_subset, args, target_dictionary, + with_labels=not pre_training, training=False) + + # Future-proof for adoption of native AMP + scaler = torch.cuda.amp.GradScaler(enabled=False) + + lr_kw = {'initial_lr_scale': args.initial_lr_scale, + 'final_lr_scale': args.final_lr_scale, + 'warmup_steps': args.warmup_updates, + 'hold_steps': args.hold_updates, + 'num_steps': args.max_update, + 'lr': args.lr} + if args.lr_policy == 'poly': + adjust_lr = partial(lr_poly_policy, power=args.lr_poly_power, **lr_kw) + elif args.lr_policy == 'exp': + adjust_lr = partial(lr_exp_policy, decay=args.lr_exp_decay, **lr_kw) + else: + raise ValueError + + assert args.fp16 + args.bf16 <= 1, ( + "Select a single mechanism for mixed precision training.") + + checkpointer.maybe_load_state(model=model) + + if args.bf16: + model.to(dtype=torch.bfloat16) + + if args.fp16: + model.half() + + if (args.fp16 or args.bf16) and args.fp32_pos_conv: + w2v = model.w2v_encoder.w2v_model if args.mode == 'finetune' else model + w2v.encoder.pos_conv.to(dtype=torch.float32) + + multi_gpu = world_size > 1 + if multi_gpu: + model = DistributedDataParallel(model, device_ids=[args.local_rank], + output_device=args.local_rank, + find_unused_parameters=True) + model = ModuleProxyWrapper(model) + + args.bf16_disable_loss_scaler = False # TODO Add support in the future + optim = get_optimizer(model, args) + adjust_lr(1, optim) + + if args.ema > 0.0: + raise NotImplementedError( + "EMA disabled, see https://github.com/pytorch/pytorch/issues/28594" + ) + else: + ema_model = None + + train_state = {'step': 0, 'epoch': 1, 'best_val_loss': float('inf'), + 'best_val_wer': float('inf')} + checkpointer.maybe_load_state(ema_model=ema_model, optimizer=optim, + scaler=scaler, train_state=train_state) + + shard_id = int(os.getenv("RANK", args.local_rank)) + + train_loader, sampler = get_batch_iterator( + train_dataset, + True, + max_tokens=args.max_tokens, + max_sentences=args.batch_size, + max_positions=(args.max_tokens, args.max_tokens), + ignore_invalid_inputs=True, + required_batch_size_multiple=args.required_batch_size_multiple, + seed=args.seed, + num_shards=world_size, + shard_id=shard_id, + num_workers=args.num_workers, + num_concat_batches=args.num_concat_batches) + + valid_loader, _ = get_batch_iterator( + valid_dataset, + False, + max_tokens=args.max_tokens_valid, + max_sentences=args.batch_size_valid, + max_positions=(sys.maxsize, sys.maxsize), + ignore_invalid_inputs=args.skip_invalid_size_inputs_valid_test, + required_batch_size_multiple=args.required_batch_size_multiple, + seed=args.seed, + num_shards=world_size, + shard_id=shard_id, + num_workers=args.num_workers, + num_concat_batches=args.num_concat_batches) + + steps_per_epoch = len(train_loader) // args.update_freq + + checkpointer.maybe_load_state(train_loader=train_loader) + checkpointer.last_state = None + + print_once(model) + model.train() + + step, epoch = train_state['step'], train_state['epoch'] + start_step = step + start_epoch = epoch + + while step < args.max_update: # training loop + set_torch_seed(args.seed + step) # reproducibility after resuming + metrics.start_epoch(epoch) + sampler.set_epoch(epoch) + + optim.zero_grad() + + itr = islice(train_loader, steps_per_epoch * args.update_freq) + for batch, accum_batches in zip(itr, cycle(range(args.update_freq))): + + if accum_batches == 0: + step += 1 + model.set_num_updates(step) + metrics.start_iter(accum_batches) + + to_gpu(batch, fp16=args.fp16, bf16=args.bf16) + + # use context manager to prevent redundant sync of gradients + if (multi_gpu and accum_batches + 1 < args.update_freq): + ctx = model.no_sync() + else: + ctx = empty_context() + + with ctx: + loss, _, logging_output = criterion(model, batch) + + if args.fp16 or args.bf16: + optim.backward(loss) + else: + scaler.scale(loss).backward() + # at this point, loss is scaled by loss_scale + # and averaged over different devices (because of DDP) (*) + + metrics.log_scalars(logging_output) + + if (accum_batches + 1) % args.update_freq == 0: + metrics.all_reduce(world_size) + + # scales gradients update by world_size + # (to restore sum of gradients - see (*)) + # divided by step_ntoks to average over tokens. + grads_mult_factor = world_size / metrics.partials['sample_size'] + + if args.optimizer == 'adam' and not (args.fp16 or args.bf16): + # adam and non-amp optimizer - can use 'scale' kwarg for step + # and defer grad multiplication + pass + elif args.fp16 or args.bf16: + optim.multiply_grads(grads_mult_factor) + else: + multiply_grads(optim, grads_mult_factor) + + try: + if args.fp16 or args.bf16: + # calculate grad norm, maybe clip + grad_norm = optim.clip_grad_norm(args.clip_norm) + + if args.optimizer == 'adam' and not (args.fp16 or args.bf16): + scaler.step(optim, scale=1. / grads_mult_factor) + else: + scaler.step(optim) + + scaler.update() + model.set_num_updates(step) + + except OverflowError as e: + print_once(f"Grad overflow, ignoring grad. {str(e)}") + grad_norm = torch.tensor(0.0).cuda() + + optim.zero_grad() + + if args.ema > 0.0: + apply_multi_tensor_ema(args.ema, *mt_ema_params) + + if args.fp16 or args.bf16: + metrics['loss_scale'] = optim.scaler.loss_scale + + metrics['lr'] = optim.param_groups[0]['lr'] + metrics.accumulate() + metrics.finish_iter() + + if step % args.log_frequency == 0: + metrics.finish_logging_interval() + epoch_step = step % steps_per_epoch or steps_per_epoch + logger.log((epoch, epoch_step, steps_per_epoch), + metrics, scope='train', tb_iter=step) + + adjust_lr(step, optim) + + if step >= args.max_update: + break + + # NOTE this will brake when resuming training on a different dataset + assert step <= steps_per_epoch * epoch + # end of iter + + metrics.finish_epoch() + logger.log((epoch,), metrics, scope='train_avg', flush_log=True, + tb_iter=step) + + print_once('Validating...') + val_losses, val_wer = validate( + epoch, step, valid_loader, model, ema_model, criterion, + val_metrics, val_ema_metrics, world_size, args.fp16, args.bf16) + + # save best ckpt based on non-EMA val results + checkpointer.maybe_save(model, ema_model, optim, scaler, train_state, + step, epoch, val_losses, val_wer, args) + + if 0 < args.epochs_this_job <= epoch + 1 - start_epoch: + print_once(f'Reached {args.epochs_this_job} epochs in this run.') + break + + if step >= args.max_update: + print_once(f'Reached {step} total updates.') + break + + epoch += 1 # end of epoch + + # finished training + if step > start_step: + logger.log((), metrics, scope='train_benchmark') + logger.log((), val_metrics, scope='val') + logger.log((), val_ema_metrics, scope='val_ema', flush_log=True) + + print_once(f'Finished after reaching update {step}.') + + +if __name__ == "__main__": + main() diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/__init__.py b/PyTorch/SpeechRecognition/wav2vec2/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/combine_filelists.py b/PyTorch/SpeechRecognition/wav2vec2/utils/combine_filelists.py new file mode 100644 index 000000000..c9b572d85 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/combine_filelists.py @@ -0,0 +1,32 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os.path import commonpath, join, relpath +import sys + + +def load_tsv(fpath): + with open(fpath) as f: + return [l.split() for l in f] + + +tsvs = [load_tsv(tsv) for tsv in sys.argv[1:]] +root = commonpath([t[0][0] for t in tsvs]) +tsvs = [[(relpath(join(lines[0][0], p), root), frames) for p, frames in lines[1:]] + for lines in tsvs] + +print(root) +for lines in tsvs: + for line in lines: + print("\t".join(line)) diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/combine_w2v2_filelist_with_phone_alignments.py b/PyTorch/SpeechRecognition/wav2vec2/utils/combine_w2v2_filelist_with_phone_alignments.py new file mode 100644 index 000000000..0828a6b81 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/combine_w2v2_filelist_with_phone_alignments.py @@ -0,0 +1,76 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from pathlib import Path + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument( + '--manifest', type=Path, nargs='+', + help='w2v2 manifest files with on every line') + parser.add_argument( + '--alignments', type=Path, + help='CPC_audio alignments with on every line') + parser.add_argument( + '--ids', type=Path, + help='List of IDs for this split (train/test, one per line)') + parser.add_argument( + '--out', type=Path, + help='Output manifest fpath') + + args = parser.parse_args() + + header = None + fpaths = {} + durs = {} + alis = {} + ids = [] + out = [] + + for fpath in args.manifest: + print(f'Loading {fpath}') + with open(fpath) as f: + for i, line in enumerate(f): + if i == 0: + header = line.strip() + continue + fp, dur = line.split() + id = Path(fp).stem + fpaths[id] = fp + durs[id] = dur # int(dur) + + with open(args.alignments) as f: + for line in f: + id, ph = line.strip().split(' ', 1) + alis[id] = ph + + ids = [line.strip() for line in open(args.ids)] + + for id in ids: + fp = fpaths[id] + d = durs[id] + a = alis[id] + out.append([fp, d, a]) + + with open(args.out.with_suffix('.tsv'), 'w') as f: + f.write(header + '\n') + for o in out: + f.write('\t'.join(o[:2]) + '\n') + + with open(args.out.with_suffix('.ph'), 'w') as f: + for o in out: + f.write(o[2] + '\n') diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/convert_librispeech.py b/PyTorch/SpeechRecognition/wav2vec2/utils/convert_librispeech.py new file mode 100644 index 000000000..e39a855f2 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/convert_librispeech.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import os +import glob +import multiprocessing +import json + +import pandas as pd + +from preprocessing_utils import parallel_preprocess + + +parser = argparse.ArgumentParser(description='Preprocess LibriSpeech.') +parser.add_argument('--input_dir', type=str, required=True, + help='LibriSpeech collection input dir') +parser.add_argument('--dest_dir', type=str, required=True, + help='Output dir') +parser.add_argument('--output_json', type=str, default='./', + help='name of the output json file.') +parser.add_argument('-s', '--speed', type=float, nargs='*', + help='Speed perturbation ratio') +parser.add_argument('--target_sr', type=int, default=None, + help='Target sample rate. ' + 'defaults to the input sample rate') +parser.add_argument('--overwrite', action='http://github.com/store_true', + help='Overwrite file if exists') +parser.add_argument('--parallel', type=int, default=multiprocessing.cpu_count(), + help='Number of threads to use when processing audio files') +args = parser.parse_args() + +args.input_dir = args.input_dir.rstrip('/') +args.dest_dir = args.dest_dir.rstrip('/') + + +def build_input_arr(input_dir): + txt_files = glob.glob(os.path.join(input_dir, '**', '*.trans.txt'), + recursive=True) + input_data = [] + for txt_file in txt_files: + rel_path = os.path.relpath(txt_file, input_dir) + with open(txt_file) as fp: + for line in fp: + fname, _, transcript = line.partition(' ') + input_data.append(dict(input_relpath=os.path.dirname(rel_path), + input_fname=fname+'.flac', + transcript=transcript)) + return input_data + + +print("[%s] Scaning input dir..." % args.output_json) +dataset = build_input_arr(input_dir=args.input_dir) + +print("[%s] Converting audio files..." % args.output_json) +dataset = parallel_preprocess(dataset=dataset, + input_dir=args.input_dir, + dest_dir=args.dest_dir, + target_sr=args.target_sr, + speed=args.speed, + overwrite=args.overwrite, + parallel=args.parallel) + +print("[%s] Generating json..." % args.output_json) +df = pd.DataFrame(dataset, dtype=object) + +# Save json with python. df.to_json() produces back slashed in file paths +dataset = df.to_dict(orient='records') +with open(args.output_json, 'w') as fp: + json.dump(dataset, fp, indent=2) diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/download_librispeech.py b/PyTorch/SpeechRecognition/wav2vec2/utils/download_librispeech.py new file mode 100644 index 000000000..860407106 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/download_librispeech.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import hashlib +import os +import requests +import tarfile + +from tqdm import tqdm + + +urls = { + "dev-clean": ("http://www.openslr.org/resources/12/dev-clean.tar.gz", "42e2234ba48799c1f50f24a7926300a1"), + "dev-other": ("http://www.openslr.org/resources/12/dev-other.tar.gz", "c8d0bcc9cca99d4f8b62fcc847357931"), + "test-clean": ("http://www.openslr.org/resources/12/test-clean.tar.gz", "32fa31d27d2e1cad72775fee3f4849a9"), + "test-other": ("http://www.openslr.org/resources/12/test-other.tar.gz", "fb5a50374b501bb3bac4815ee91d3135"), + "train-clean-100": ("http://www.openslr.org/resources/12/train-clean-100.tar.gz", "2a93770f6d5c6c964bc36631d331a522"), + "train-clean-360": ("http://www.openslr.org/resources/12/train-clean-360.tar.gz", "c0e676e450a7ff2f54aeade5171606fa"), + "train-other-500": ("http://www.openslr.org/resources/12/train-other-500.tar.gz", "d1a0fd59409feb2c614ce4d30c387708"), +} + + +def download_file(url, dest_folder, fname, overwrite=False): + fpath = os.path.join(dest_folder, fname) + if os.path.isfile(fpath): + if overwrite: + print("Overwriting existing file") + else: + print("File exists, skipping download.") + return + + tmp_fpath = fpath + '.tmp' + + if not os.path.exists(os.path.dirname(tmp_fpath)): + os.makedirs(os.path.dirname(tmp_fpath)) + + r = requests.get(url, stream=True) + file_size = int(r.headers['Content-Length']) + chunk_size = 1024 * 1024 # 1MB + total_chunks = int(file_size / chunk_size) + + with open(tmp_fpath, 'wb') as fp: + content_iterator = r.iter_content(chunk_size=chunk_size) + chunks = tqdm(content_iterator, total=total_chunks, + unit='MB', desc=fpath, leave=True) + for chunk in chunks: + fp.write(chunk) + + os.rename(tmp_fpath, fpath) + + +def md5_checksum(fpath, target_hash): + file_hash = hashlib.md5() + with open(fpath, "rb") as fp: + for chunk in iter(lambda: fp.read(1024*1024), b""): + file_hash.update(chunk) + return file_hash.hexdigest() == target_hash + + +def extract(fpath, dest_folder): + if fpath.endswith('.tar.gz'): + mode = 'r:gz' + elif fpath.endswith('.tar'): + mode = 'r:' + else: + raise IOError('fpath has unknown extention: %s' % fpath) + + with tarfile.open(fpath, mode) as tar: + members = tar.getmembers() + for member in tqdm(iterable=members, total=len(members), leave=True): + tar.extract(path=dest_folder, member=member) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser( + description='Download, verify and extract dataset files') + parser.add_argument('dest', type=str, + help='Download destnation folder.') + parser.add_argument('-e', type=str, default=None, + help='Extraction destnation folder. Defaults to download folder if not provided') + parser.add_argument('--skip_download', action='http://github.com/store_true', + help='Skip downloading the files') + parser.add_argument('--skip_checksum', action='http://github.com/store_true', + help='Skip checksum') + parser.add_argument('--skip_extract', action='http://github.com/store_true', + help='Skip extracting files') + parser.add_argument('--subsets', type=str, nargs="+", choices=list(urls.keys()), + default=list(urls.keys()), help='Subsets to download') + args = parser.parse_args() + args.e = args.e or args.dest + + print("\nNOTE: Depending on the selected subsets and connection bandwith " + "this process might take a few hours.\n") + + for subset in args.subsets: + url, md5 = urls[subset] + + if not args.skip_download: + fname = url.split('/')[-1] + print("Downloading %s:" % fname) + download_file(url=url, dest_folder=args.dest, fname=fname) + else: + print("Skipping file download") + + if not args.skip_checksum: + fname = url.split('/')[-1] + fpath = os.path.join(args.dest, fname) + print("Verifing %s: " % fname, end='') + ret = md5_checksum(fpath=fpath, target_hash=md5) + print("Passed" if ret else "Failed") + else: + print("Skipping checksum") + + if not args.skip_extract: + fname = url.split('/')[-1] + fpath = os.path.join(args.dest, fname) + print("Decompressing %s:" % fpath) + extract(fpath=fpath, dest_folder=args.e) + else: + print("Skipping file extraction") diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/download_utils.py b/PyTorch/SpeechRecognition/wav2vec2/utils/download_utils.py new file mode 100644 index 000000000..6fda8477c --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/download_utils.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import hashlib +import requests +import os +import tarfile +import tqdm + + +def download_file(url, dest_folder, fname, overwrite=False): + fpath = os.path.join(dest_folder, fname) + if os.path.isfile(fpath): + if overwrite: + print("Overwriting existing file") + else: + print("File exists, skipping download.") + return + + tmp_fpath = fpath + '.tmp' + + if not os.path.exists(os.path.dirname(tmp_fpath)): + os.makedirs(os.path.dirname(tmp_fpath)) + + r = requests.get(url, stream=True) + file_size = int(r.headers['Content-Length']) + chunk_size = 1024 * 1024 # 1MB + total_chunks = int(file_size / chunk_size) + + with open(tmp_fpath, 'wb') as fp: + content_iterator = r.iter_content(chunk_size=chunk_size) + chunks = tqdm.tqdm(content_iterator, total=total_chunks, + unit='MB', desc=fpath, leave=True) + for chunk in chunks: + fp.write(chunk) + + os.rename(tmp_fpath, fpath) + + +def md5_checksum(fpath, target_hash): + file_hash = hashlib.md5() + with open(fpath, "rb") as fp: + for chunk in iter(lambda: fp.read(1024*1024), b""): + file_hash.update(chunk) + return file_hash.hexdigest() == target_hash + + +def extract(fpath, dest_folder): + if fpath.endswith('.tar.gz'): + mode = 'r:gz' + elif fpath.endswith('.tar'): + mode = 'r:' + else: + raise IOError('fpath has unknown extention: %s' % fpath) + + with tarfile.open(fpath, mode) as tar: + members = tar.getmembers() + for member in tqdm.tqdm(iterable=members, total=len(members), leave=True): + tar.extract(path=dest_folder, member=member) diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/generate_1h_10h_datasets.py b/PyTorch/SpeechRecognition/wav2vec2/utils/generate_1h_10h_datasets.py new file mode 100644 index 000000000..bb3201e4d --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/generate_1h_10h_datasets.py @@ -0,0 +1,73 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from itertools import chain +from pathlib import Path + + +def load_lines(fpath): + with open(fpath) as f: + return [line for line in f] + + +parser = argparse.ArgumentParser() +parser.add_argument('ls_ft', type=Path, + help='Libri-light librispeech_finetuning dir') +parser.add_argument('ls_filelists', type=Path, + help='Directory with .tsv .wrd etc files for LibriSpeech full 960') +parser.add_argument('out', type=Path, help='Output directory') +args = parser.parse_args() + +# Load LS +tsv = load_lines(args.ls_filelists / "train-full-960.tsv") +wrd = load_lines(args.ls_filelists / "train-full-960.wrd") +ltr = load_lines(args.ls_filelists / "train-full-960.ltr") + +assert len(tsv) == len(wrd) + 1 +assert len(ltr) == len(wrd) + +files = {} +for path_frames, w, l in zip(tsv[1:], wrd, ltr): + path, _ = path_frames.split("\t") + key = Path(path).stem + files[key] = (path_frames, w, l) + +print(f"Loaded {len(files)} entries from {args.ls_filelists}/train-full-960") + +# Load LL-LS +files_1h = list((args.ls_ft / "1h").rglob("*.flac")) +files_9h = list((args.ls_ft / "9h").rglob("*.flac")) + +print(f"Found {len(files_1h)} files in the 1h dataset") +print(f"Found {len(files_9h)} files in the 9h dataset") + +for name, file_iter in [("train-1h", files_1h), + ("train-10h", chain(files_1h, files_9h))]: + + with open(args.out / f"{name}.tsv", "w") as ftsv, \ + open(args.out / f"{name}.wrd", "w") as fwrd, \ + open(args.out / f"{name}.ltr", "w") as fltr: + nframes = 0 + + ftsv.write(tsv[0]) + for fpath in file_iter: + key = fpath.stem + t, w, l = files[key] + ftsv.write(t) + fwrd.write(w) + fltr.write(l) + nframes += int(t.split()[1]) + + print(f"Written {nframes} frames ({nframes / 16000 / 60 / 60:.2f} h at 16kHz)") diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/generate_dictionary.py b/PyTorch/SpeechRecognition/wav2vec2/utils/generate_dictionary.py new file mode 100644 index 000000000..81531b2ee --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/generate_dictionary.py @@ -0,0 +1,29 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from collections import Counter +import sys + + +in_ltr = sys.argv[1] +out_dict = sys.argv[2] + +counter = Counter() +with open(in_ltr) as ltr: + for line in ltr: + counter.update(line[:-1].replace(" ", "")) + +with open(out_dict, "w") as out: + for letter, cnt in counter.most_common(): + out.write(f"{letter} {cnt}\n") diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/generate_filelist.py b/PyTorch/SpeechRecognition/wav2vec2/utils/generate_filelist.py new file mode 100644 index 000000000..c32eca5e4 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/generate_filelist.py @@ -0,0 +1,37 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from pathlib import Path + +import soundfile +import tqdm + + +parser = argparse.ArgumentParser(description="Write .tsv dataset filelists") +parser.add_argument("dir", type=Path, help="Dataset directory") +parser.add_argument("output_tsv", type=Path, help="Output .tsv file path") +parser.add_argument("--extension", type=str, default="flac", + help="Find files with this extension") +args = parser.parse_args() + +num_files = 0 +print(f"Collecting .{args.extension} files in {args.dir} ...") +with open(args.output_tsv, "w") as f: + f.write(f"{args.dir}\n") + for fname in tqdm.tqdm(args.dir.rglob("*." + args.extension)): + num_frames = soundfile.info(fname).frames + f.write(f"{fname.relative_to(args.dir)}\t{num_frames}\n") + num_files += 1 +print(f"Found {num_files} files for {args.output_tsv} .") diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/libri_labels.py b/PyTorch/SpeechRecognition/wav2vec2/utils/libri_labels.py new file mode 100644 index 000000000..1b207e1a6 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/libri_labels.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Helper script to pre-compute embeddings for a flashlight (previously called wav2letter++) dataset +""" + +import argparse +import os + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("tsv") + parser.add_argument("--output-dir", required=True) + parser.add_argument("--output-name", required=True) + args = parser.parse_args() + + os.makedirs(args.output_dir, exist_ok=True) + + transcriptions = {} + + with open(args.tsv, "r") as tsv, open( + os.path.join(args.output_dir, args.output_name + ".ltr"), "w" + ) as ltr_out, open( + os.path.join(args.output_dir, args.output_name + ".wrd"), "w" + ) as wrd_out: + root = next(tsv).strip() + for line in tsv: + line = line.strip() + dir = os.path.dirname(line) + if dir not in transcriptions: + parts = dir.split(os.path.sep) + trans_path = f"{parts[-2]}-{parts[-1]}.trans.txt" + path = os.path.join(root, dir, trans_path) + assert os.path.exists(path), f"File {path} does not exist." + texts = {} + with open(path, "r") as trans_f: + for tline in trans_f: + items = tline.strip().split() + texts[items[0]] = " ".join(items[1:]) + transcriptions[dir] = texts + part = os.path.basename(line).split(".")[0] + assert part in transcriptions[dir] + print(transcriptions[dir][part], file=wrd_out) + print( + " ".join(list(transcriptions[dir][part].replace(" ", "|"))) + " |", + file=ltr_out, + ) + + +if __name__ == "__main__": + main() diff --git a/PyTorch/SpeechRecognition/wav2vec2/utils/preprocessing_utils.py b/PyTorch/SpeechRecognition/wav2vec2/utils/preprocessing_utils.py new file mode 100644 index 000000000..28fe2ae20 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/utils/preprocessing_utils.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import multiprocessing +import functools + +import sox +from tqdm import tqdm + + +def preprocess(data, input_dir, dest_dir, target_sr=None, speed=None, + overwrite=True): + speed = speed or [] + speed.append(1) + speed = list(set(speed)) # Make uniqe + + input_fname = os.path.join(input_dir, + data['input_relpath'], + data['input_fname']) + input_sr = sox.file_info.sample_rate(input_fname) + target_sr = target_sr or input_sr + + os.makedirs(os.path.join(dest_dir, data['input_relpath']), exist_ok=True) + + output_dict = {} + output_dict['transcript'] = data['transcript'].lower().strip() + output_dict['files'] = [] + + fname = os.path.splitext(data['input_fname'])[0] + for s in speed: + output_fname = fname + '{}.wav'.format('' if s == 1 else '-{}'.format(s)) + output_fpath = os.path.join(dest_dir, + data['input_relpath'], + output_fname) + + if not os.path.exists(output_fpath) or overwrite: + cbn = sox.Transformer().speed(factor=s).convert(target_sr) + cbn.build(input_fname, output_fpath) + + file_info = sox.file_info.info(output_fpath) + file_info['fname'] = os.path.join(os.path.basename(dest_dir), + data['input_relpath'], + output_fname) + file_info['speed'] = s + output_dict['files'].append(file_info) + + if s == 1: + file_info = sox.file_info.info(output_fpath) + output_dict['original_duration'] = file_info['duration'] + output_dict['original_num_samples'] = file_info['num_samples'] + + return output_dict + + +def parallel_preprocess(dataset, input_dir, dest_dir, target_sr, speed, + overwrite, parallel): + with multiprocessing.Pool(parallel) as p: + func = functools.partial(preprocess, input_dir=input_dir, + dest_dir=dest_dir, target_sr=target_sr, + speed=speed, overwrite=overwrite) + dataset = list(tqdm(p.imap(func, dataset), total=len(dataset))) + return dataset diff --git a/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/__init__.py b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/arg_parser.py b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/arg_parser.py new file mode 100644 index 000000000..6c9a6e763 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/arg_parser.py @@ -0,0 +1,395 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys + + +def populate(parser): + choices = ["pretrain", "finetune"] + parser.add_argument("mode", help="Training mode", choices=choices) + mode = parser.parse_args([a for a in sys.argv[1:] if a in choices]).mode + + if mode == "pretrain": + populate_pretraining(parser) + else: + populate_finetuning(parser) + + populate_common(parser) + return parser + + +def populate_infer(parser): + populate_finetuning(parser) + populate_common(parser) + _populate_infer(parser) + return parser + + +def populate_common(parser): + train = parser.add_argument_group("training setup") + train.add_argument("--epochs_this_job", default=0, type=int, + help="Run for a number of epochs and exit") + train.add_argument("--cudnn_benchmark", action="http://github.com/store_true", + help="Enable cudnn benchmark") + train.add_argument("--local_rank", "--local-rank", default=os.getenv("LOCAL_RANK", 0), + type=int, help="GPU id used for distributed training") + + optim = parser.add_argument_group("optimization setup") + optim.add_argument("--optimizer", default="adam", type=str, + help="Optimization algorithm") + optim.add_argument("--ema", type=float, default=0.0, + help="Discount factor for EMA of model weights") + + io = parser.add_argument_group("feature and checkpointing setup") + io.add_argument("--log_frequency", default=1, type=int, + help="Number of steps between printing training stats") + io.add_argument("--output_dir", type=str, required=True, + help="Directory for logs and checkpoints") + io.add_argument("--log_file", type=str, default=None, + help="Path to save the training logfile.") + io.add_argument("--benchmark_epochs_num", type=int, default=3, + help="Number of last epochs to calculate throughput stats") + + ckpt = parser.add_argument_group("checkpoint") + ckpt.add_argument("--no_save", action="http://github.com/store_true", + help="Don't save models or checkpoints") + ckpt.add_argument("--resume", action="http://github.com/store_true", + help="Try to resume from last saved checkpoint") + ckpt.add_argument("--ckpt", default=None, type=str, + help="Path to a checkpoint for resuming training") + ckpt.add_argument("--save_frequency", default=10, type=int, + help="Checkpoint saving frequency in epochs") + ckpt.add_argument("--keep_milestones", default=[100, 200, 300, 400], + type=int, nargs="+", + help="Milestone checkpoints to keep from removing") + # io.add_argument("--save_best_from", default=380, type=int, + # help="Epoch on which to begin tracking best checkpoint (dev WER)") + + common = parser.add_argument_group("common") + common.add_argument("--seed", type=int, default=1, + help="Pseudo random number generator seed") + common.add_argument("--cpu", action="http://github.com/store_true", + help="Use CPU instead of CUDA") + common.add_argument("--amp", action="http://github.com/store_true", + help="Use automatic mixed precision") + common.add_argument("--fp16", action="http://github.com/store_true", + help="If fp16 is being used") + common.add_argument("--bf16", action="http://github.com/store_true", + help="Train in bfloat16 precision") + common.add_argument("--min_loss_scale", type=float, default=0.0001, + help="Minimum FP16/AMP loss scale, after which " + "training is stopped") + common.add_argument("--fp16_init_scale", type=int, default=128, + help="Default FP16 loss scale") + + common.add_argument("--fp32_transformer_layernorm", action="http://github.com/store_true", + help="Calculate MHA LayerNorms in full precision") + common.add_argument("--fp32_mha_softmax", action="http://github.com/store_true", + help="Calculate multi-head attention to FP32") + common.add_argument("--fp32_cosine_sim", action="http://github.com/store_true", + help="Calculate cosine similarity in FP32") + common.add_argument("--fp32_pos_conv", action="http://github.com/store_true", + help="Calculate positional conv in FP32") + common.add_argument("--fp32_conv_norms", action="http://github.com/store_true", + help="Calculate normalization in conv layers in FP32") + + common.add_argument("--mha", type=str, default="fairseq", + choices=["fairseq", "pyt"], help="MHA implementation") + + common.add_argument("--num_concat_batches", type=int, default=1) + + dataset = parser.add_argument_group("dataset") + dataset.add_argument("--num_workers", type=int, default=6, + help="How many subprocesses to use for data loading") + dataset.add_argument("--skip_invalid_size_inputs_valid_test", + action="http://github.com/store_true", + help="Ignore too long or too short lines in valid and" + " test set") + dataset.add_argument("--max_tokens", type=int, default=1400000, + help="Maximum number of tokens in a batch") + dataset.add_argument("--max_tokens_valid", type=int, default=1400000, + help="Maximum number of tokens in a validation batch " + "(defaults to --max-tokens)") + dataset.add_argument("--required_batch_size_multiple", type=int, default=8, + help="Batch size will be a multiplier of this value") + dataset.add_argument("--required_seq_len_multiple", type=int, default=2, + help="Pad the input to encoder such that the sequence" + " length is divisible by multiple") + dataset.add_argument("--train_subset", type=str, default="train", + help="Data subset to use for training (e.g. train, " + "valid, test)") + dataset.add_argument("--valid_subset", type=str, default="valid", + help="Comma separated list of data subsets to use for" + " validation (e.g. train, valid, test)") + dataset.add_argument("--batch_size", type=int, default=None, + help="Number of examples in a batch") + dataset.add_argument("--batch_size_valid", type=int, default=None, + help="Batch size of the validation batch (defaults " + "to --batch-size)") + + task = parser.add_argument_group("task") + task.add_argument("--data", type=str, + default="/workspace/fairseq/librispeech", + help="Path to data directory") + task.add_argument("--sample_rate", type=int, default=16000, + help="Target sample rate. audio files will be up/down " + "sampled to this rate") + task.add_argument("--enable_padding", action="http://github.com/store_true", + help="Pad shorter samples instead of cropping") + task.add_argument("--min_sample_size", type=int, default=None, + help="Min sample size to crop to for batching") + task.add_argument("--max_sample_size", type=int, default=None, + help="Max sample size to crop to for batching") + task.add_argument("--num_batch_buckets", type=int, default=0, + help="If >0, then bucket source and target lengths into " + "N buckets and pad accordingly; this is useful on " + "TPUs to minimize the number of compilations") + + opt = parser.add_argument_group("optimization & optimizer") + opt.add_argument("--max_update", type=int, default=400000, + help="Force stop training at specified update") + opt.add_argument("--update_freq", type=int, nargs="+", default=[64], + help="Accumulate grads and update params every N batches") + opt.add_argument("--lr", type=float, nargs="+", default=[0.0005], + help="Max learning rate, must be more than cfg.min_lr") + opt.add_argument("--adam_betas", type=float, nargs="+", default=[0.9, 0.98], + help="Betas for Adam optimizer") + opt.add_argument("--adam_eps", type=float, default=1e-06, + help="Epsilon for Adam optimizer") + opt.add_argument("--weight_decay", type=float, default=0.01, + help="Weight decay") + opt.add_argument("--clip_norm", type=float, default=0.0, + help="Clip threshold of gradients") + + sched = parser.add_argument_group("lr_scheduler") + sched.add_argument("--lr_policy", type=str, default="poly", + choices=["poly", "exp"], help="LR decay policy") + sched.add_argument("--warmup_updates", type=int, default=32000, + help="Warmup the learning rate linearly for the first " + "N updates") + sched.add_argument("--hold_updates", type=int, default=0, + help="The number of updates with const learning rate") + sched.add_argument("--initial_lr_scale", type=float, default=0.0, + help="Initial learning rate scale") + sched.add_argument("--final_lr_scale", type=float, default=0.0, + help="Final learning rate scale") + sched.add_argument("--lr_poly_power", type=float, default=1.0, + help="Poly lr policy policy power") + sched.add_argument("--lr_exp_decay", type=float, default=None, + help="Exp lr policy decay factor") + + drop = parser.add_argument_group("dropout") + drop.add_argument("--dropout", type=float, default=0.1, + help="Dropout probability for the transformer") + drop.add_argument("--attention_dropout", type=float, default=0.0, + help="Dropout probability for attention weights") + drop.add_argument("--activation_dropout", type=float, default=0.0, + help="Dropout probability after activation in FFN") + drop.add_argument("--dropout_input", type=float, default=0.1, + help="Dropout to apply to the input (after feat extr)") + drop.add_argument("--dropout_features", type=float, default=0.1, + help="Dropout to apply to the features (after feat extr)") + + mask = parser.add_argument_group("input masking") + mask.add_argument("--apply_mask", action="http://github.com/store_true", + help="Apply masking during fine-tuning") + mask.add_argument("--mask_length", type=int, default=10, + help="Repeat the mask indices multiple times") + mask.add_argument("--mask_prob", type=float, default=0.5, + help="Probability of replacing a token with mask " + "(normalized by length)") + mask.add_argument("--require_same_masks", type=bool, default=True, + help="Whether to number of masked timesteps must be the" + " same across all examples in a batch") + mask.add_argument("--mask_selection", default="static", + choices=["static", "uniform", "normal", "poisson"], + help="How to choose masks") + mask.add_argument("--mask_other", type=float, default=0, + help="Secondary mask argument (used for more complex " + "distributions), see help in compute_mask_indices") + mask.add_argument("--no_mask_overlap", type=bool, default=False, + help="Whether to allow masks to overlap") + mask.add_argument("--mask_min_space", type=int, default=1, + help="Min space between spans (if no overlap is enabled)") + mask.add_argument("--mask_channel_length", type=int, default=10, + help="Length of the mask for features (channels)") + mask.add_argument("--mask_channel_prob", type=float, default=0.0, + help="Probability of replacing a feature with 0") + mask.add_argument("--mask_channel_before", type=bool, default=False, + help="Apply channel-masking before frequency-masking") + mask.add_argument("--mask_channel_selection", default="static", + choices=["static", "uniform", "normal", "poisson"], + help="How to choose mask length for channel masking") + mask.add_argument("--mask_channel_other", type=float, default=0, + help="Secondary mask argument (used for more complex " + "distributions), see help in compute_mask_indicesh") + mask.add_argument("--no_mask_channel_overlap", type=bool, default=False, + help="Whether to allow channel masks to overlap") + mask.add_argument("--mask_channel_min_space", type=int, default=1, + help="Min space between spans (if no overlap is enabled)") + parser.add_argument("--feature_grad_mult", type=float, default=0.1, + help="Reset feature grad mult in wav2vec 2.0 to this") + # NOTE In Fairseq this is called `--layerdrop` in fine-tuning yamls + parser.add_argument("--encoder_layerdrop", type=float, default=0.05, + help="Probability of dropping a layer in wav2vec 2.0") + mask.add_argument("--mask_dropout", type=float, default=0.0, + help="Percent of masks to unmask for each sample") + + +def populate_finetuning(parser): + """Args for fine-tuning, absent from pre-trained ckpts.""" + ft = parser.add_argument_group("supervised fine-tuning") + ft.add_argument("--final_dropout", type=float, default=0.0, + help="Dropout after transformer and before final proj") + ft.add_argument("--w2v_path", type=str, default=None, + help="Path to wav2vec 2.0 model") + ft.add_argument("--blank_weight", type=float, default=0) + ft.add_argument("--blank_mode", type=str, default="add") + ft.add_argument("--labels", type=str, default="ltr", + help="Extension of the label file to load for fine-tuning") + ft.add_argument("--freeze_finetune_updates", type=int, default=0, + help="Don't finetune wav2vec for this many updates") + + +def populate_pretraining(parser): + """During fine-tuning these parameters will be loaded from a ckpt.""" + model = parser.add_argument_group("model") + model.add_argument("--extractor_mode", type=str, default="default", + help="Mode for feature extractor. default has a single " + "group norm with d groups in the first conv block," + " whereas layer_norm has layer norms in every " + "block (meant to use with normalize=True)") + model.add_argument("--encoder_layers", type=int, default=12, + help="Num encoder layers in the transformer") + model.add_argument("--encoder_embed_dim", type=int, default=768, + help="Encoder embedding dimension") + model.add_argument("--encoder_ffn_embed_dim", type=int, default=3072, + help="Encoder embedding dimension for FFN") + model.add_argument("--encoder_attention_heads", type=int, default=12, + help="Num encoder attention heads") + model.add_argument("--activation_fn", type=str, default="gelu", + help="Activation function to use") + model.add_argument("--final_dim", type=int, default=256, + help="Project final representations and targets to this" + " many dimensions. set to encoder_embed_dim " + "is <= 0") + model.add_argument("--layer_norm_first", action="http://github.com/store_true", + help="Apply layernorm first in the transformer") + model.add_argument("--conv_feature_layers", type=str, + default="[(512,10,5)]+[(512,3,2)]*4+[(512,2,2)]+[(512,2,2)]", + help="String describing convolutional feature " + "extraction layers in form of a python list that " + "contains [(dim, kernel_size, stride), ...]") + model.add_argument("--conv_bias", action="http://github.com/store_true", + help="Include bias in conv encoder") + model.add_argument("--logit_temp", type=float, default=0.1, + help="Temperature to divide logits by") + model.add_argument("--quantize_targets", action="http://github.com/store_true", + help="Use quantized targets") + model.add_argument("--quantize_input", action="http://github.com/store_true", + help="Use quantized inputs") + model.add_argument("--target_glu", action="http://github.com/store_true", + help="Adds projection + glu to targets") + model.add_argument("--quantizer_depth", type=int, default=1, + help="Number of quantizer layers") + model.add_argument("--quantizer_factor", type=int, default=3, + help="Dimensionality increase for inner quantizer " + "layers (if depth > 1)") + model.add_argument("--latent_vars", type=int, default=320, + help="Number of latent variables V in each group of the" + " codebook") + model.add_argument("--latent_groups", type=int, default=2, + help="Number of groups G of latent variables in the " + "codebook") + model.add_argument("--latent_dim", type=int, default=0, + help="If > 0, uses this dimensionality for latent var" + "iables. otherwise uses final_dim / latent_groups") + model.add_argument("--num_negatives", type=int, default=100, + help="Num of sampled negatives") + model.add_argument("--negatives_from_everywhere", action="http://github.com/store_true", + help="Sample negatives from everywhere, not just masked" + " states") + model.add_argument("--cross_sample_negatives", type=int, default=0, + help="Num of cross sampled negatives") + model.add_argument("--codebook_negatives", type=int, default=0, + help="Number of negative examples codebook") + model.add_argument("--conv_pos", type=int, default=128, + help="Number of filters for convolutional positional " + "embeddings") + model.add_argument("--conv_pos_groups", type=int, default=16, + help="Number of groups for convolutional positional " + "embedding") + model.add_argument("--latent_temp", type=float, nargs="+", + default=[2.0, 0.5, 0.999995], + help="Legacy (to be removed)") + model.add_argument("--normalize", action="http://github.com/store_true", + help="If set, normalizes input to have 0 mean and unit " + "variance") + parser.add_argument("--log_keys", type=str, nargs="*", + default=["prob_perplexity", "code_perplexity", "temp"], + help="Additional output keys to log") + + crit = parser.add_argument_group("criterion") + crit.add_argument("--infonce", action="http://github.com/store_true", + help="If set, uses cross entropy instead of binary cross" + " entropy (i.e. InfoNCE loss)") + crit.add_argument("--loss_weights", type=float, nargs="*", + default=[0.1, 10.0], help="Weights for the loss terms") + + joc = parser.add_argument_group("joc experimental") + joc.add_argument("--use_spectrogram_features", action="http://github.com/store_true", + help="Train on input spectrograms") + joc.add_argument("--rotary_embeddings", action="http://github.com/store_true", + help="Use rotarty embeddings for Transformer layers") + joc.add_argument("--hourglass_transformer", type=str, default=None, + help="Specify the number of layers and shorteining, e.g.," + " [n_pre,(n_hourglass, shorten_factor),n_post]") + joc.add_argument("--hourglass_resample", type=str, default="naive", + help="Method of up/downsampling in the hourglass model") + joc.add_argument("--spectrogram_feature_stacking", type=int, default=1) + joc.add_argument("--spectrogram_feature_subsampling", type=int, default=1) + joc.add_argument("--spectrogram_window_size", type=float, default=0.02) + joc.add_argument("--spectrogram_window_stride", type=float, default=0.01) + joc.add_argument("--spectrogram_n_filt", type=int, default=80) + return parser + + +def _populate_infer(parser): + # Fine-tuning only + infer = parser.add_argument_group("inference") + infer.add_argument("--steps", default=0, type=int, + help="Eval this many steps for every worker") + infer.add_argument("--warmup_steps", default=0, type=int, + help="Burn-in period before measuring latencies") + infer.add_argument("--labels_path", type=str, default=None, + help="Path to output labels file, e.g., dict.ltr.txt") + infer.add_argument("--save_predictions", type=str, default=None, + help="Save predictions in text form at this location") + infer.add_argument("--save_logits", default=None, type=str, + help="Save output logits under specified path") + infer.add_argument("--transcribe_wav", type=str, + help="Path to a single .wav file (16KHz)") + infer.add_argument("--transcribe_filelist", type=str, + help="Path to a filelist with one .wav path per line") + infer.add_argument("--torchscript", action="http://github.com/store_true", + help="Evaluate with a TorchScripted model") + infer.add_argument("--w2v_path_for_args", type=str, default=None, + help="Args to build model for inference (weights will " + "be loaded from --w2v_path)") diff --git a/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/criterion.py b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/criterion.py new file mode 100644 index 000000000..e67a68aa3 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/criterion.py @@ -0,0 +1,246 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import editdistance +import torch +import torch.nn.functional as F +from torch.nn.modules.loss import _Loss + +from common.fairseq import utils +from common.fairseq.data.data_utils import post_process +from common.utils import AttrDict + + +class Wav2vecCriterion(_Loss): + def __init__(self, args): + super().__init__(args) + self.infonce = args.infonce + self.loss_weights = args.loss_weights + self.log_keys = [] if args.log_keys is None else args.log_keys + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + net_output = model(**sample["net_input"], + sub_batch_sizes=sample["sub_batch_sizes"], + sub_batch_lens=sample["sub_batch_lens"]) + logits = model.get_logits(net_output).float() + target = model.get_targets(sample, net_output) + + weights = None + if hasattr(model, "get_target_weights") and not self.infonce: + weights = model.get_target_weights(target, net_output) + if torch.is_tensor(weights): + weights = weights.float() + + losses = [] + + reduction = "sum" if reduce else "none" + if self.infonce: + loss = F.cross_entropy(logits, target, reduction=reduction) + else: + loss = F.binary_cross_entropy_with_logits( + logits, target.float(), weights, reduction=reduction + ) + + if 'sample_size' in sample: + sample_size = sample['sample_size'] + elif 'mask_indices' in sample['net_input']: + sample_size = sample['net_input']['mask_indices'].sum() + elif self.infonce: + sample_size = target.numel() + else: + sample_size = target.long().sum().item() + + losses.append(loss.detach().clone()) + + if self.loss_weights is not None: + assert hasattr(model, "get_extra_losses") + extra_losses = model.get_extra_losses(net_output) + + if torch.is_tensor(extra_losses): + extra_losses = [extra_losses] + + if len(self.loss_weights) == 1 and len(extra_losses) != 1: + self.loss_weights = [self.loss_weights[0]] * len(extra_losses) + + assert len(extra_losses) == len(self.loss_weights), \ + f"{len(extra_losses)}, {len(self.loss_weights)}" + + for p, coef in zip(extra_losses, self.loss_weights): + if coef != 0 and p is not None: + p = coef * p.float() * sample_size + loss += p + losses.append(p) + + log_out = { + "loss": loss.item() if reduce else loss.detach(), + "ntokens": sample_size, + "nsentences": sample["id"].numel(), + "sample_size": sample_size, + } + + for lk in self.log_keys: + # Only store "logits" and "target" for computing MAP and MAUC + # during validation + if lk == "logits": + if not self.training: + log_out["logits"] = logits.cpu().numpy() + + elif lk == "target": + if not self.training: + # If the targets have been mixed with the predictions of + # teacher models, find the original targets + if hasattr(model, "get_original_targets"): + original_target = model.get_original_targets( + sample, net_output) + else: + original_target = target + log_out["target"] = original_target.cpu().numpy() + + elif lk in net_output: + log_out[lk] = float(net_output[lk]) + + if len(losses) > 1: + for i, l in enumerate(losses): + log_out[f"loss_{i}"] = l.item() + + if self.infonce: + with torch.no_grad(): + if logits.numel() == 0: + corr = 0 + count = 0 + else: + assert logits.dim() > 1, logits.shape + max_ = logits.argmax(-1) == 0 + min_ = logits.argmin(-1) == 0 + both = max_ & min_ + corr = max_.long().sum().item() - both.long().sum().item() + count = float(max_.numel()) + + log_out["correct"] = corr + log_out["count"] = count + + return loss, sample_size, log_out + + +class CTCCriterion(_Loss): + def __init__(self, target_dictionary, blank_idx=0, pad_idx=1, eos_idx=2, + zero_infinity=True, sentence_avg=True, post_process='letter'): + + super().__init__() + # keep all indexes for compatibility with fairseq + self.blank_idx = blank_idx + self.pad_idx = target_dictionary.pad() + self.eos_idx = target_dictionary.eos() + assert self.blank_idx != self.pad_idx != self.eos_idx + + self.target_dictionary = target_dictionary + self.zero_infinity = zero_infinity + self.sentence_avg = sentence_avg + self.post_process = post_process + + # currently we don't support decoders (e.g., KenLM) + self.w2l_decoder = None + + def forward(self, model, sample, reduce=True): + net_out = model(**sample["net_input"]) + logp = model.get_normalized_probs( + net_out["encoder_out"], net_out["padding_mask"], log_probs=True + ).contiguous() + + T, B, _ = logp.size() + + if net_out["padding_mask"] is not None: + lens = (~net_out["padding_mask"]).long().sum(-1) + else: + lens = logp.new_full((B,), T, dtype=torch.long) + + tgt = sample["target"] + pad_mask = (tgt != self.pad_idx) & (tgt != self.eos_idx) + tgt_flat = tgt.masked_select(pad_mask) + tgt_lens = sample["target_lengths"] + + with torch.backends.cudnn.flags(enabled=False): + loss = F.ctc_loss(logp, tgt_flat, lens, tgt_lens, + blank=self.blank_idx, reduction="sum", + zero_infinity=self.zero_infinity) + log_out = { + "loss": utils.item(loss.data), + "ntokens": sample["ntokens"], + "nsentences": sample["id"].numel(), + "sample_size": B if self.sentence_avg else sample["ntokens"] + } + + if not model.training: + log_out.update(self.calculate_wer(sample, logp, lens)) + + return loss, log_out['sample_size'], log_out + + def calculate_wer(self, sample, logp, lens): + with torch.no_grad(): + log = AttrDict({"wv_errs": 0, "w_errs": 0, "w_len": 0, + "c_errs": 0, "c_len": 0}) + + logp_t = logp.transpose(0, 1).float().contiguous().cpu() + tgt_labels = sample.get('target_label', sample['target']) + + head = lambda l: None if l is None or len(l) < 1 else l[0] + + for lp, L, tgt in zip(logp_t, lens, tgt_labels): + lp = lp[:L].unsqueeze(0) + + if self.w2l_decoder is not None: + decoded = head(head(self.w2l_decoder.decode(lp))) + else: + decoded = None + + mask = (tgt != self.pad_idx) & (tgt != self.eos_idx) + tgt_units = self.target_dictionary.string(tgt[mask]) + tgt_units_arr = tgt[mask].tolist() + + toks = lp.argmax(dim=-1).unique_consecutive() + pred_units_arr = toks[toks != self.blank_idx].tolist() + + log.c_errs += editdistance.eval(pred_units_arr, tgt_units_arr) + log.c_len += len(tgt_units_arr) + + tgt_words = post_process(tgt_units, self.post_process).split() + + pred_units = self.target_dictionary.string(pred_units_arr) + pred_words_raw = post_process(pred_units, + self.post_process).split() + + if decoded is not None and "words" in decoded: + pred_words = decoded["words"] + log.w_errs += editdistance.eval(pred_words, tgt_words) + log.wv_errs += editdistance.eval(pred_words_raw, tgt_words) + else: + dist = editdistance.eval(pred_words_raw, tgt_words) + log.w_errs += dist + log.wv_errs += dist + + log.w_len += len(tgt_words) + + return vars(log) diff --git a/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/logging.py b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/logging.py new file mode 100644 index 000000000..84a7c86e2 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/logging.py @@ -0,0 +1,189 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +from pathlib import Path + +import dllogger +import torch.distributed as dist +from dllogger import StdOutBackend, JSONStreamBackend, Verbosity + +from common import tb_dllogger +from common.metrics import MetricsAggregator +from common.tb_dllogger import (stdout_metric_format, stdout_step_format, + unique_log_fpath, TBLogger) + + +def init_logger(output_dir, log_file, ema_decay=0.0): + local_rank = 0 if not dist.is_initialized() else dist.get_rank() + + if local_rank == 0: + Path(output_dir).mkdir(parents=False, exist_ok=True) + log_fpath = log_file or Path(output_dir, 'nvlog.json') + dllogger.init(backends=[ + JSONStreamBackend(Verbosity.DEFAULT, log_fpath, append=True), + JSONStreamBackend(Verbosity.DEFAULT, unique_log_fpath(log_fpath)), + StdOutBackend(Verbosity.VERBOSE, step_format=stdout_step_format, + metric_format=stdout_metric_format) + ]) + init_train_metadata() + else: + dllogger.init(backends=[]) + + tb_train = ['train', 'train_avg'] + tb_val = ['val'] + tb_ema = [k + '_ema' for k in tb_val] if ema_decay > 0.0 else [] + + subset_names = { + 'train': 'train_inner', + 'train_avg': 'train', + 'val': 'valid', + 'val_ema': 'valid_ema', + } + enabled = (local_rank == 0) + tb_dllogger.tb_loggers = { + s: TBLogger(enabled, log_dir=output_dir, name=subset_names[s]) + for s in tb_train + tb_val + tb_ema} + + +def init_train_metadata(): + for id_, pref in [('train', ''), ('train_avg', 'avg train '), + ('val', ' avg val '), ('val_ema', ' EMA val ')]: + + dllogger.metadata(f"{id_}_loss", + {"name": f"{pref} loss", "format": ":>6.3f"}) + + dllogger.metadata(f"{id_}_accuracy", + {"name": f"{pref}acc", "format": ":>6.3f"}) + + dllogger.metadata(f"{id_}_prob_perplexity", + {"name": f"{pref}p pplx", "format": ":>6.3f"}) + + dllogger.metadata(f"{id_}_code_perplexity", + {"name": f"{pref}c pplx", "format": ":>6.3f"}) + + dllogger.metadata(f"{id_}_ntokens", + {"name": None, "unit": "tokens", "format": ":>8.0f"}) + + dllogger.metadata(f"{id_}_took", + {"name": "took", "unit": "s", "format": ":>3.2f"}) + + dllogger.metadata(f"{id_}_ntokens/s", + {"name": None, "unit": "tokens/s", "format": ":>8.2f"}) + + dllogger.metadata(f"{id_}_uer", + {"name": f"{pref} uer", "format": ":>6.2f"}) + + dllogger.metadata(f"{id_}_wer", + {"name": f"{pref} wer", "format": ":>6.2f"}) + + dllogger.metadata(f"{id_}_raw_wer", + {"name": f"{pref} raw wer", "format": ":>6.2f"}) + + dllogger.metadata(f"{id_}_lr", + {"name": "lr", "format": ":>3.2e"}) + + dllogger.metadata(f"{id_}_loss_scale", + {"name": "loss scale", "format": ":>3.2e"}) + + +def init_infer_metadata(): + for step in ['DNN', 'data+DNN', 'data']: + for c in [0.99, 0.95, 0.9, 0.5]: + cs = 'avg' if c == 0.5 else f'{int(100 * c)}%' + dllogger.metadata(f'{step.lower()}_latency_{c}', + {'name': f'{step} latency {cs}', + 'format': ':>7.2f', 'unit': 'ms'}) + dllogger.metadata( + 'eval_wer', {'name': 'WER', 'format': ':>3.2f', 'unit': '%'}) + + +class W2v2Metrics(MetricsAggregator): + + def __init__(self, benchmark_epochs, scopes=('train', 'train_avg'), cuda=True): + super().__init__( + benchmark_epochs=benchmark_epochs, + benchmark_keys=('took', 'accuracy', 'loss', 'ntokens/s'), + scopes=scopes, + dllogger_keys=('loss', 'ntokens', 'accuracy', 'prob_perplexity', + 'code_perplexity', + 'took', 'loss_scale', 'lr', 'ntokens/s'), + reduce_mean=('temp', 'prob_perplexity', 'code_perplexity'), + reduce_last=('lr', 'loss_scale'), + cuda=cuda) + + def accumulate(self, scopes=None): + if 'ignore' not in self.partials or self.partials['ignore'] == 0.0: + # compute_loss_and_accuracy + ntokens = self.partials['ntokens'] + for k, v in self.partials.items(): + if k.startswith('loss'): + self.partials[k] = v / ntokens / math.log(2) # as in fairseq + + self['accuracy'] = (self.partials.pop('correct') + / self.partials.pop('count')) + part_counts = self.partial_counts + assert part_counts['correct'] == part_counts['count'] == 1 + + super().accumulate(scopes=scopes) + + def _finish_accumulating(self, scope='train'): + super()._finish_accumulating(scope=scope) + m = self.metrics[scope] + count = self.metric_counts[scope] + m['ntokens/s'] = m['ntokens'] * count['ntokens'] / m['took'] + + +class W2v2FineTuningMetrics(MetricsAggregator): + + def __init__( + self, + benchmark_epochs, + benchmark_keys=('took', 'accuracy', 'loss', 'ntokens/s'), + scopes=('train', 'train_avg'), + dllogger_keys=('loss', 'ntokens', 'accuracy', 'lr', + 'prob_perplexity', 'took', 'ntokens/s', 'uer', + 'wer', 'raw_wer'), + reduce_mean=('temp', 'prob_perplexity', 'code_perplexity'), + reduce_last=('lr',), + cuda=True): + super().__init__( + benchmark_epochs=benchmark_epochs, benchmark_keys=benchmark_keys, + scopes=scopes, dllogger_keys=dllogger_keys, + reduce_mean=reduce_mean, reduce_last=reduce_last, cuda=cuda) + + def accumulate(self, scopes=None): + if 'ignore' not in self.partials or self.partials['ignore'] == 0.0: + # compute_loss_and_accuracy + nsentences = self.partials['nsentences'] + for k, v in self.partials.items(): + if k.startswith('loss'): + self.partials[k] = v / nsentences / math.log(2) # as in fairseq + + super().accumulate(scopes=scopes) + + def _finish_accumulating(self, scope='train'): + super()._finish_accumulating(scope=scope) + + m = self.metrics[scope] + count = self.metric_counts[scope] + + m['ntokens/s'] = m['ntokens'] * count['ntokens'] / m['took'] + + if 'c_errs' in m: + m['uer'] = 100 * m['c_errs'] / m['c_len'] + if 'w_errs' in m: + m['wer'] = 100 * m['w_errs'] / m['w_len'] + if 'wv_errs' in m: + m['raw_wer'] = 100 * m['wv_errs'] / m['w_len'] diff --git a/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/model.py b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/model.py new file mode 100644 index 000000000..69363b705 --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/model.py @@ -0,0 +1,1549 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import contextlib +import math +from typing import Dict, List, Optional, Tuple + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch import Tensor + +from common import fairseq_fake_modules +from common.fairseq import utils +from common.fairseq.data.data_utils import compute_mask_indices +from common.fairseq.modules import ( + Fp32GroupNorm, + Fp32LayerNorm, + Fp32MaskedGroupNorm, + GradMultiply, + GumbelVectorQuantizer, + LayerNorm, + MaskedGroupNorm, + MultiheadAttention, + SamePad, + TransposeLast, +) +from common.features import FilterbankFeatures +from common.helpers import load_wrapped_state +from common.pyt_mha import PytMultiheadAttention +from common.utils import print_once + + +class Fp32Conv1d(nn.Conv1d): + """Casts to FP32. TorchScript ready, does not use inheritance. + + Details: https://github.com/pytorch/pytorch/issues/42885 . + """ + + def forward(self, x): + return F.conv1d( + x.float(), self.weight, bias=self.bias, stride=self.stride, + padding=self.padding, dilation=self.dilation, groups=self.groups + ).to(dtype=x.dtype) + + +def init_bert_params(module): + """ + Initialize the weights specific to the BERT Model. + This overrides the default initializations depending on the specified arguments. + 1. If normal_init_linear_weights is set then weights of linear + layer will be initialized using the normal distribution and + bais will be set to the specified value. + 2. If normal_init_embed_weights is set then weights of embedding + layer will be initialized using the normal distribution. + 3. If normal_init_proj_weights is set then weights of + in_project_weight for MultiHeadAttention initialized using + the normal distribution (to be validated). + """ + + def normal_(data): + # with FSDP, module params will be on CUDA, so we cast them back to CPU + # so that the RNG is consistent with and without FSDP + data.copy_( + data.cpu().normal_(mean=0.0, std=0.02).to(data.device) + ) + + if isinstance(module, nn.Linear): + normal_(module.weight.data) + if module.bias is not None: + module.bias.data.zero_() + if isinstance(module, nn.Embedding): + normal_(module.weight.data) + if module.padding_idx is not None: + module.weight.data[module.padding_idx].zero_() + if isinstance(module, MultiheadAttention): + normal_(module.q_proj.weight.data) + normal_(module.k_proj.weight.data) + normal_(module.v_proj.weight.data) + if isinstance(module, PytMultiheadAttention): + normal_(module.qkv.weight.data) + + +def Linear(in_features, out_features, bias=True): + m = nn.Linear(in_features, out_features, bias) + nn.init.xavier_uniform_(m.weight) + if bias: + nn.init.constant_(m.bias, 0.0) + return m + + +class MaskedBlock(nn.Module): + + def __init__(self, *args): + super().__init__() + + self.conv = args[0] + self.drop = args[1] + if len(args) == 4: + self.norm = args[2] + self.activation = args[3] + else: + self.norm = None + self.activation = args[2] + + def hook(state_dict, prefix, *args, **kwargs): + """Rename Blocks saved as nn.Sequential.""" + new_sd = {} + for k, v in state_dict.items(): + if not k.startswith(prefix): + new_sd[k] = v + else: + *pref, feat, conv, mod_num, layer_num, param = k.split(".") + assert feat == "feature_extractor" and conv == "conv_layers" + if layer_num == "0": + new_k = ".".join(pref + [feat, conv, mod_num, "conv", param]) + elif layer_num == "2": + new_k = ".".join(pref + [feat, conv, mod_num, "norm", param]) + else: + raise ValueError + print(f"Rename {k} --> {new_k}") + new_sd[new_k] = v + state_dict.clear() + state_dict.update(new_sd) + + self._register_load_state_dict_pre_hook(hook) + + def forward(self, x: Tensor, x_lens: Tensor): + x = self.drop(self.conv(x)) + x_lens = (x_lens - self.conv.kernel_size[0]) / self.conv.stride[0] + 1 + x_lens = torch.floor(x_lens).long() + + if self.norm is not None: + if isinstance(self.norm, nn.Sequential): + # LayerNorm wraped with nn.Sequential + raise ValueError("LayerNorm does not require masking") + else: + x = self.norm(x, x_lens) + return self.activation(x), x_lens + + +class Wav2Vec2Model(nn.Module): + def __init__(self, cfg): + super().__init__() + self.cfg = cfg + self.use_spectrogram_features = cfg.use_spectrogram_features + + if self.use_spectrogram_features: + self.spec_feature_extractor = FilterbankFeatures( + frame_stacking=cfg.spectrogram_feature_stacking, + frame_subsampling=cfg.spectrogram_feature_subsampling, + window_size=cfg.spectrogram_window_size, + window_stride=cfg.spectrogram_window_stride, + n_filt=cfg.spectrogram_n_filt).cuda() + self.feature_extractr = None + self.spec_feature_extractor.eval() + self.embed = self.spec_feature_extractor.output_dim() + else: + feature_enc_layers = eval(cfg.conv_feature_layers) + self.embed = feature_enc_layers[-1][0] + self.spec_feature_extractor = None + self.feature_extractor = ConvFeatureExtractionModel( + conv_layers=feature_enc_layers, + dropout=0.0, + mode=cfg.extractor_mode, + conv_bias=cfg.conv_bias, + fp32_norms=cfg.fp32_conv_norms, + masked=getattr(cfg, 'masked_feature_extractor', False), + ) + + self.post_extract_proj = ( + nn.Linear(self.embed, cfg.encoder_embed_dim) + if self.embed != cfg.encoder_embed_dim and not cfg.quantize_input + else None + ) + self.mask_prob = cfg.mask_prob + self.mask_selection = cfg.mask_selection + self.mask_other = cfg.mask_other + self.mask_length = cfg.mask_length + self.no_mask_overlap = cfg.no_mask_overlap + self.mask_min_space = cfg.mask_min_space + + self.mask_channel_prob = cfg.mask_channel_prob + self.mask_channel_before = cfg.mask_channel_before + self.mask_channel_selection = cfg.mask_channel_selection + self.mask_channel_other = cfg.mask_channel_other + self.mask_channel_length = cfg.mask_channel_length + self.no_mask_channel_overlap = cfg.no_mask_channel_overlap + self.mask_channel_min_space = cfg.mask_channel_min_space + + self.dropout_input = nn.Dropout(cfg.dropout_input) + self.dropout_features = nn.Dropout(cfg.dropout_features) + + self.feature_grad_mult = cfg.feature_grad_mult + + self.quantizer = None + self.input_quantizer = None + + self.n_negatives = cfg.num_negatives + self.cross_sample_negatives = cfg.cross_sample_negatives + self.codebook_negatives = cfg.codebook_negatives + self.negatives_from_everywhere = cfg.negatives_from_everywhere + + self.logit_temp = cfg.logit_temp + + self.fp32_cosine_sim = cfg.fp32_cosine_sim + + final_dim = cfg.final_dim if cfg.final_dim > 0 else cfg.encoder_embed_dim + + if cfg.quantize_targets: + vq_dim = cfg.latent_dim if cfg.latent_dim > 0 else final_dim + self.quantizer = GumbelVectorQuantizer( + dim=self.embed, + num_vars=cfg.latent_vars, + temp=cfg.latent_temp, + groups=cfg.latent_groups, + combine_groups=False, + vq_dim=vq_dim, + time_first=True, + weight_proj_depth=cfg.quantizer_depth, + weight_proj_factor=cfg.quantizer_factor, + ) + self.project_q = nn.Linear(vq_dim, final_dim) + else: + self.project_q = nn.Linear(self.embed, final_dim) + + if cfg.quantize_input: + if cfg.same_quantizer and self.quantizer is not None: + vq_dim = final_dim + self.input_quantizer = self.quantizer + else: + vq_dim = cfg.latent_dim if cfg.latent_dim > 0 else cfg.encoder_embed_dim + self.input_quantizer = GumbelVectorQuantizer( + dim=self.embed, + num_vars=cfg.latent_vars, + temp=cfg.latent_temp, + groups=cfg.latent_groups, + combine_groups=False, + vq_dim=vq_dim, + time_first=True, + weight_proj_depth=cfg.quantizer_depth, + weight_proj_factor=cfg.quantizer_factor, + ) + self.project_inp = nn.Linear(vq_dim, cfg.encoder_embed_dim) + + self.mask_emb = nn.Parameter( + torch.FloatTensor(cfg.encoder_embed_dim).uniform_() + ) + + self.encoder = TransformerEncoder(cfg) + self.layer_norm = LayerNorm(self.embed) + + self.target_glu = None + if cfg.target_glu: + self.target_glu = nn.Sequential( + nn.Linear(final_dim, final_dim * 2), nn.GLU() + ) + + self.final_proj = nn.Linear(cfg.encoder_embed_dim, final_dim) + + self.conv_cfg_list = eval(self.cfg.conv_feature_layers) + + def apply_mask( + self, + x, + padding_mask, + mask_indices=None, + mask_channel_indices=None, + ): + B, T, C = x.shape + + if self.mask_channel_prob > 0 and self.mask_channel_before: + mask_channel_indices = compute_mask_indices( + (B, C), + None, + self.mask_channel_prob, + self.mask_channel_length, + self.mask_channel_selection, + self.mask_channel_other, + no_overlap=self.no_mask_channel_overlap, + min_space=self.mask_channel_min_space, + ) + mask_channel_indices = ( + torch.from_numpy(mask_channel_indices) + .to(x.device) + .unsqueeze(1) + .expand(-1, T, -1) + ) + x[mask_channel_indices] = 0 + + if self.mask_prob > 0: + if mask_indices is None: + mask_indices = compute_mask_indices( + (B, T), + padding_mask, + self.mask_prob, + self.mask_length, + self.mask_selection, + self.mask_other, + min_masks=2, + no_overlap=self.no_mask_overlap, + min_space=self.mask_min_space, + require_same_masks=True, + mask_dropout=0.0, + ) + mask_indices = torch.from_numpy(mask_indices).to(x.device) + x[mask_indices] = self.mask_emb + else: + mask_indices = None + + if self.mask_channel_prob > 0 and not self.mask_channel_before: + if mask_channel_indices is None: + mask_channel_indices = compute_mask_indices( + (B, C), + None, + self.mask_channel_prob, + self.mask_channel_length, + self.mask_channel_selection, + self.mask_channel_other, + no_overlap=self.no_mask_channel_overlap, + min_space=self.mask_channel_min_space, + ) + mask_channel_indices = ( + torch.from_numpy(mask_channel_indices) + .to(x.device) + .unsqueeze(1) + .expand(-1, T, -1) + ) + x[mask_channel_indices] = 0 + + return x, mask_indices + + def sample_negatives(self, y, num, padding_count=None): + + if self.n_negatives == 0 and self.cross_sample_negatives == 0: + return y.new(0) + + bsz, tsz, fsz = y.shape + y = y.view(-1, fsz) # BTC => (BxT)C + + cross_high = tsz * bsz + high = tsz - (padding_count or 0) + with torch.no_grad(): + assert high > 1, f"{bsz,tsz,fsz}" + + if self.n_negatives > 0: + tszs = torch.arange(num, device=y.device).unsqueeze(-1) + tszs = tszs.expand(-1, self.n_negatives).flatten() + + neg_idxs = torch.randint( + low=0, high=high - 1, size=(bsz, self.n_negatives * num), + device=y.device + ) + neg_idxs[neg_idxs >= tszs] += 1 + + if self.cross_sample_negatives > 0: + tszs = torch.arange(num, device=y.device).unsqueeze(-1) + tszs = tszs.expand(-1, self.cross_sample_negatives).flatten() + + cross_neg_idxs = torch.randint( + low=0, + high=cross_high - 1, + size=(bsz, self.cross_sample_negatives * num), + device=y.device + ) + cross_neg_idxs[cross_neg_idxs >= tszs] += 1 + + if self.n_negatives > 0: + for i in range(1, bsz): + neg_idxs[i] += i * high + else: + neg_idxs = cross_neg_idxs + + if self.cross_sample_negatives > 0 and self.n_negatives > 0: + neg_idxs = torch.cat([neg_idxs, cross_neg_idxs], dim=1) + + negs = y[neg_idxs.view(-1)] + negs = negs.view( + bsz, num, self.n_negatives + self.cross_sample_negatives, fsz + ).permute( + 2, 0, 1, 3 + ) # to NxBxTxC + return negs, neg_idxs + + def compute_preds(self, x, y, negatives): + + neg_is_pos = (y == negatives).all(-1) + y = y.unsqueeze(0) + targets = torch.cat([y, negatives], dim=0) + + if self.fp32_cosine_sim: + logits = torch.cosine_similarity(x.float(), targets.float(), + dim=-1).type_as(x) + else: + logits = torch.cosine_similarity(x, targets, dim=-1) + + logits = logits / self.logit_temp + + if neg_is_pos.any(): + if not hasattr(self, "_inftensor"): + self._inftensor = float("-inf") + logits[1:][neg_is_pos] = self._inftensor + + return logits + + def _conv_out_length(self, input_length: torch.Tensor, kernel_size: int, stride: int): + return torch.floor((input_length - kernel_size) / stride + 1) + + def _get_feat_extract_output_lengths(self, input_lengths: torch.LongTensor): + """ + Computes the output length of the convolutional layers + """ + for i in range(len(self.conv_cfg_list)): + input_lengths = self._conv_out_length( + input_lengths, + self.conv_cfg_list[i][1], + self.conv_cfg_list[i][2] + ) + + return input_lengths.to(torch.long) + + def infer(self, source: Tensor, padding_mask: Tensor): + """Forward method for (masked) inference.""" + + input_lengths = (1 - padding_mask.long()).sum(-1) + output_lengths = self._get_feat_extract_output_lengths(input_lengths) + + features, _ = self.feature_extractor.masked_forward(source, input_lengths) + features = features.transpose(1, 2) + features = self.layer_norm(features) + + padding_mask = torch.zeros( + features.shape[:2], dtype=features.dtype, device=features.device + ) + + # these two operations makes sure that all values + # before the output lengths indices are attended to + padding_mask[ + ( + torch.arange(padding_mask.shape[0], device=padding_mask.device), + output_lengths - 1, + ) + ] = 1 + padding_mask = (1 - padding_mask.flip([-1]).cumsum(-1).flip([-1])) == 1 + + if self.post_extract_proj is not None: + features = self.post_extract_proj(features) + + x = self.dropout_input(features) + x, _ = self.encoder(x, padding_mask=padding_mask) + return x, padding_mask + + def forward( + self, + source, + padding_mask: Optional[Tensor] = None, + mask=True, + features_only=False, + layer=-1, + mask_indices=None, + mask_channel_indices=None, + padding_count=None, + sub_batch_sizes=None, + sub_batch_lens=None, + ): + masked_inference = self.feature_extractor.masked + + if self.spec_feature_extractor is not None: + if padding_mask is not None and padding_mask.any(): + input_lengths = (1 - padding_mask.long()).sum(-1) + else: + input_lengths = (torch.zeros(source.size(0)) + source.size(1)).cuda() + + features, output_lengths = self.spec_feature_extractor(source, input_lengths) + output_lengths = output_lengths.to(torch.long) + + else: + if self.training and self.feature_grad_mult > 0: + features = self.feature_extractor(source) + if self.feature_grad_mult != 1.0: + features = GradMultiply.apply(features, self.feature_grad_mult) + else: + with torch.no_grad(): + if masked_inference: + input_lengths = (1 - padding_mask.long()).sum(-1) + features, _ = self.feature_extractor.masked_forward(source, input_lengths) + else: + features = self.feature_extractor(source) + + if masked_inference or (padding_mask is not None and padding_mask.any()): + input_lengths = (1 - padding_mask.long()).sum(-1) + # apply conv formula to get real output_lengths + output_lengths = self._get_feat_extract_output_lengths(input_lengths) + else: + output_lengths = None + + features_pen = features.float().pow(2).mean() + features = features.transpose(1, 2) + features = self.layer_norm(features) + unmasked_features = features.clone() + + if output_lengths is not None: + + padding_mask = torch.zeros( + features.shape[:2], dtype=features.dtype, device=features.device + ) + + # these two operations makes sure that all values + # before the output lengths indices are attended to + padding_mask[ + ( + torch.arange(padding_mask.shape[0], device=padding_mask.device), + output_lengths - 1, + ) + ] = 1 + padding_mask = (1 - padding_mask.flip([-1]).cumsum(-1).flip([-1])) == 1 + else: + padding_mask = None + + if self.post_extract_proj is not None: + features = self.post_extract_proj(features) + + features = self.dropout_input(features) + unmasked_features = self.dropout_features(unmasked_features) + + num_vars = None + code_ppl = None + prob_ppl = None + curr_temp = None + + if self.input_quantizer: + q = self.input_quantizer(features, produce_targets=False) + features = q["x"] + num_vars = q["num_vars"] + code_ppl = q["code_perplexity"] + prob_ppl = q["prob_perplexity"] + curr_temp = q["temp"] + features = self.project_inp(features) + + split_accumulation = sub_batch_sizes is not None and sub_batch_sizes.size(0) > 1 + if split_accumulation: + assert sub_batch_sizes is not None + assert self.quantizer is not None + assert not self.negatives_from_everywhere + assert self.codebook_negatives == 0 + assert self.target_glu is None + assert mask_indices is None + assert mask_channel_indices is None + assert mask + + split_sizes = sub_batch_sizes.tolist() + sub_x, sub_y, sub_mask_indices, sub_negs = [], [], [], [] + + for s, e in zip(np.cumsum(split_sizes) - split_sizes, np.cumsum(split_sizes)): + x_, mask_indices_ = self.apply_mask( + features[s:e], + padding_mask[s:e] if padding_mask is not None else None, + ) + sub_x.append(x_) + sub_mask_indices.append(mask_indices_) + y_ = unmasked_features[s:e][mask_indices_].view( + e-s, -1, unmasked_features.size(-1) + ) + + q_ = self.quantizer(y_, produce_targets=False) + y_ = q_["x"] + y_ = self.project_q(y_) + + negs_, _ = self.sample_negatives( + y_, + y_.size(1), + padding_count=padding_count, + ) + sub_y.append(y_) + sub_negs.append(negs_) + + x = torch.cat(sub_x, dim=0) + mask_indices = torch.cat(sub_mask_indices, dim=0) + + x, layer_results = self.encoder(x, padding_mask=padding_mask, layer=layer) + + if features_only: + return { + "x": x, + "padding_mask": padding_mask, + "features": unmasked_features, + "layer_results": layer_results, + } + + x = x[mask_indices] # .view(x.size(0), -1, x.size(-1)) + x = self.final_proj(x) + + # At this point, x needs to be smartly reshaped / split into x_'s + + sub_x2 = [] + offset = 0 + for y_, mask_inds_, negs_ in zip(sub_y, sub_mask_indices, sub_negs): + sz = mask_inds_.sum() + x_ = x[offset:offset+sz].view(mask_inds_.size(0), -1, x.size(-1)) + x_ = self.compute_preds(x_, y_, negs_) + sub_x2.append(x_) + offset += sz + + x = torch.cat([x_.view(x_.size(0), 1, -1) for x_ in sub_x2], dim=2) + + result = { + "x": x, + "padding_mask": padding_mask, + "features_pen": features_pen, + } + + # TODO Reassemble q stats, currently using first chunk's stats + q = q_ + + if q["prob_perplexity"] is not None: + result["prob_perplexity"] = q["prob_perplexity"] + result["code_perplexity"] = q["code_perplexity"] + result["num_vars"] = q["num_vars"] + result["temp"] = q["temp"] + + return result + + # End split_accumulation ---------------------------------------------- + + if mask: + x, mask_indices = self.apply_mask( + features, + padding_mask, + mask_indices=mask_indices, + mask_channel_indices=mask_channel_indices, + ) + if mask_indices is not None: + y = unmasked_features[mask_indices].view( + unmasked_features.size(0), -1, unmasked_features.size(-1) + ) + else: + y = unmasked_features + else: + x = features + y = unmasked_features + mask_indices = None + + x, layer_results = self.encoder(x, padding_mask=padding_mask, layer=layer) + + if features_only: + return { + "x": x, + "padding_mask": padding_mask, + "features": unmasked_features, + "layer_results": layer_results, + } + + if self.quantizer: + q = self.quantizer(y, produce_targets=False) + y = q["x"] + num_vars = q["num_vars"] + code_ppl = q["code_perplexity"] + prob_ppl = q["prob_perplexity"] + curr_temp = q["temp"] + + y = self.project_q(y) + + if self.negatives_from_everywhere: + neg_cands = self.quantizer(unmasked_features, produce_targets=False)[ + "x" + ] + negs, _ = self.sample_negatives( + neg_cands, + y.size(1), + padding_count=padding_count, + ) + negs = self.project_q(negs) + + else: + negs, _ = self.sample_negatives( + y, + y.size(1), + padding_count=padding_count, + ) + + if self.codebook_negatives > 0: + cb_negs = self.quantizer.sample_from_codebook( + y.size(0) * y.size(1), self.codebook_negatives + ) + cb_negs = cb_negs.view( + self.codebook_negatives, y.size(0), y.size(1), -1 + ) # order doesnt matter + cb_negs = self.project_q(cb_negs) + negs = torch.cat([negs, cb_negs], dim=0) + else: + y = self.project_q(y) + + if self.negatives_from_everywhere: + negs, _ = self.sample_negatives( + unmasked_features, + y.size(1), + padding_count=padding_count, + ) + negs = self.project_q(negs) + else: + negs, _ = self.sample_negatives( + y, + y.size(1), + padding_count=padding_count, + ) + + x = x[mask_indices].view(x.size(0), -1, x.size(-1)) + + if self.target_glu: + y = self.target_glu(y) + negs = self.target_glu(negs) + + x = self.final_proj(x) + x = self.compute_preds(x, y, negs) + + result = { + "x": x, + "padding_mask": padding_mask, + "features_pen": features_pen, + } + + if prob_ppl is not None: + result["prob_perplexity"] = prob_ppl + result["code_perplexity"] = code_ppl + result["num_vars"] = num_vars + result["temp"] = curr_temp + + return result + + def quantize(self, x): + assert self.quantizer is not None + x = self.feature_extractor(x) + x = x.transpose(1, 2) + x = self.layer_norm(x) + return self.quantizer.forward_idx(x) + + def extract_features(self, source, padding_mask, mask=False, layer=-1): + res = self.forward( + source, padding_mask, mask=mask, features_only=True, layer=layer + ) + return res + + def get_logits(self, net_output): + logits = net_output["x"] + logits = logits.transpose(0, 2) + logits = logits.reshape(-1, logits.size(-1)) + return logits + + def get_targets(self, sample, net_output, expand_steps=True): + x = net_output["x"] + return x.new_zeros(x.size(1) * x.size(2), dtype=torch.long) + + def get_extra_losses(self, net_output): + pen = [] + + if "prob_perplexity" in net_output: + pen.append( + (net_output["num_vars"] - net_output["prob_perplexity"]) + / net_output["num_vars"] + ) + + if "features_pen" in net_output: + pen.append(net_output["features_pen"]) + + return pen + + def remove_pretraining_modules(self): + self.quantizer = None + self.project_q = None + self.target_glu = None + self.final_proj = None + + def get_normalized_probs( + self, + net_output: Tuple[Tensor, Optional[Dict[str, List[Optional[Tensor]]]]], + log_probs: bool, + sample: Optional[Dict[str, Tensor]] = None, + ): + """Get normalized probabilities (or log probs) from a net's output.""" + return self.get_normalized_probs_scriptable(net_output, log_probs, sample) + + # TorchScript doesn't support super() method so that the scriptable Subclass + # can't access the base class model in Torchscript. + # Current workaround is to add a helper function with different name and + # call the helper function from scriptable Subclass. + def get_normalized_probs_scriptable( + self, + net_output: Tuple[Tensor, Optional[Dict[str, List[Optional[Tensor]]]]], + log_probs: bool, + sample: Optional[Dict[str, Tensor]] = None, + ): + """Scriptable helper function for get_normalized_probs in ~BaseFairseqModel""" + if hasattr(self, "decoder"): + return self.decoder.get_normalized_probs(net_output, log_probs, sample) + elif torch.is_tensor(net_output): + # syntactic sugar for simple models which don't have a decoder + # (e.g., the classification tutorial) + logits = net_output.float() + if log_probs: + return F.log_softmax(logits, dim=-1) + else: + return F.softmax(logits, dim=-1) + raise NotImplementedError + + def max_positions(self): + """Maximum length supported by the model.""" + return None + + def load_state_dict( + self, + state_dict, + strict=True, + ): + """Copies parameters and buffers from *state_dict* into this module and + its descendants. + + Overrides the method in :class:`nn.Module`. Compared with that method + this additionally "upgrades" *state_dicts* from old checkpoints. + """ + self.upgrade_state_dict(state_dict) + new_state_dict = state_dict + + return super().load_state_dict(new_state_dict, strict) + + def upgrade_state_dict(self, state_dict): + """Upgrade old state dicts to work with newer code.""" + self.upgrade_state_dict_named(state_dict, "") + + def upgrade_state_dict_named(self, state_dict, name): + """Upgrade old state dicts to work with newer code. + + Args: + state_dict (dict): state dictionary to upgrade, in place + name (str): the state dict key corresponding to the current module + """ + assert state_dict is not None + + def do_upgrade(m, prefix): + if len(prefix) > 0: + prefix += "." + + for n, c in m.named_children(): + name = prefix + n + if hasattr(c, "upgrade_state_dict_named"): + c.upgrade_state_dict_named(state_dict, name) + elif hasattr(c, "upgrade_state_dict"): + c.upgrade_state_dict(state_dict) + do_upgrade(c, name) + + do_upgrade(self, name) + + def set_num_updates(self, num_updates): + """State from trainer to pass along to model at every update.""" + for m in self.modules(): + if hasattr(m, "set_num_updates") and m != self: + m.set_num_updates(num_updates) + + def prepare_for_inference_(self, cfg): + """Prepare model for inference.""" + kwargs = {} + kwargs["beamable_mm_beam_size"] = ( + None + if getattr(cfg.generation, "no_beamable_mm", False) + else getattr(cfg.generation, "beam", 5) + ) + kwargs["need_attn"] = getattr(cfg.generation, "print_alignment", False) + if getattr(cfg.generation, "retain_dropout", False): + kwargs["retain_dropout"] = cfg.generation.retain_dropout + kwargs["retain_dropout_modules"] = cfg.generation.retain_dropout_modules + self.make_generation_fast_(**kwargs) + + def make_generation_fast_(self, **kwargs): + """ + Legacy entry point to optimize model for faster generation. + Prefer prepare_for_inference_. + """ + if self._is_generation_fast: + return # only apply once + self._is_generation_fast = True + + # remove weight norm from all modules in the network + def apply_remove_weight_norm(module): + try: + nn.utils.remove_weight_norm(module) + except (AttributeError, ValueError): # this module didn't have weight norm + return + + self.apply(apply_remove_weight_norm) + + def train(mode=True): + if mode: + raise RuntimeError("cannot train after make_generation_fast") + + # this model should no longer be used for training + self.eval() + self.train = train + + def prepare_for_onnx_export_(self, **kwargs): + """Make model exportable via ONNX trace.""" + seen = set() + + def apply_prepare_for_onnx_export_(module): + if ( + module != self + and hasattr(module, "prepare_for_onnx_export_") + and module not in seen + ): + seen.add(module) + module.prepare_for_onnx_export_(**kwargs) + + self.apply(apply_prepare_for_onnx_export_) + + def remove_conv_wn(self): + nn.utils.remove_weight_norm(self.encoder.pos_conv[0]) + + def apply_conv_wn(self): + nn.utils.weight_norm(self.encoder.pos_conv[0], name="weight", dim=2) + + +class ConvFeatureExtractionModel(nn.Module): + def __init__( + self, + conv_layers: List[Tuple[int, int, int]], + dropout: float = 0.0, + mode: str = "default", + conv_bias: bool = False, + fp32_norms: bool = True, + masked: bool = False, + ): + super().__init__() + + assert mode in {"default", "layer_norm"} + self.mode = mode + self.masked = masked + + LayerNorm_ = Fp32LayerNorm if fp32_norms else nn.LayerNorm + if masked and mode == "default": + Block_ = MaskedBlock + GroupNorm_ = Fp32MaskedGroupNorm if fp32_norms else MaskedGroupNorm + else: + Block_ = nn.Sequential + GroupNorm_ = Fp32GroupNorm if fp32_norms else nn.GroupNorm + + def block( + n_in, + n_out, + k, + stride, + is_layer_norm=False, + is_group_norm=False, + conv_bias=False, + ): + assert not (is_layer_norm and is_group_norm), ( + "layer norm and group norm are mutually exclusive") + + def make_conv(): + conv = nn.Conv1d(n_in, n_out, k, stride=stride, bias=conv_bias) + nn.init.kaiming_normal_(conv.weight) + return conv + + def make_norm(): + if is_group_norm: + l = GroupNorm_(dim, dim, affine=True) + elif is_layer_norm: + l = nn.Sequential(TransposeLast(), + LayerNorm_(dim, elementwise_affine=True), + TransposeLast()) + return l + + has_norm = is_layer_norm or is_group_norm + return Block_(make_conv(), + nn.Dropout(p=dropout), + *([make_norm()] if has_norm else []), + nn.GELU()) + in_d = 1 + self.conv_layers = nn.ModuleList() + for i, cl in enumerate(conv_layers): + assert len(cl) == 3, "invalid conv definition: " + str(cl) + (dim, k, stride) = cl + + self.conv_layers.append( + block( + in_d, + dim, + k, + stride, + is_layer_norm=mode == "layer_norm", + is_group_norm=mode == "default" and i == 0, + conv_bias=conv_bias, + ) + ) + in_d = dim + + def forward(self, x): + # BxT -> BxCxT + x = x.unsqueeze(1) + + for conv in self.conv_layers: + x = conv(x) + return x + + def masked_forward(self, x: Tensor, x_lens: Tensor): + # BxT -> BxCxT + x = x.unsqueeze(1) + + for conv in self.conv_layers: + x, x_lens = conv(x, x_lens) + return x, x_lens + + +class Upsampler(nn.Module): + def __init__(self, emb_dim, factor, mode="linear"): + super().__init__() + assert mode in ("linear", "naive") + self.factor = factor + if mode == "linear": + self.linear = nn.Linear(emb_dim, emb_dim * factor) + else: + self.linear = None + + def forward(self, x): + if self.linear is not None: + # T x B x C -> B x T x C + x = x.transpose(0, 1) + x = self.linear(x) + x = x.reshape(x.size(0), x.size(1) * self.factor, -1) + x = x.transpose(0, 1) + else: + x = x.repeat_interleave(self.factor, dim=0) + + return x + + +class Downsampler(nn.Module): + def __init__(self, emb_dim, factor, mode="linear"): + super().__init__() + assert mode in ("linear", "naive") + self.factor = factor + if mode == "linear": + self.linear = nn.Linear(emb_dim * factor, emb_dim) + else: + self.linear = None + + def forward(self, x): + if self.linear is not None: + # T x B x C -> B x T x C + x = x.transpose(0, 1) + B, T, C = x.size() + x = x.reshape(B, T // self.factor, C * self.factor) + x = self.linear(x) + x = x.transpose(0, 1) + else: + # T x B x C -> B x C x T + x = x.permute(1, 2, 0) + x = F.avg_pool1d(x, kernel_size=self.factor, stride=self.factor) + x = x.permute(2, 0, 1) + return x + + +class TransformerEncoder(nn.Module): + def __init__(self, args): + super().__init__() + + self.dropout = args.dropout + self.embedding_dim = args.encoder_embed_dim + + PosConv = Fp32Conv1d if args.fp32_pos_conv else nn.Conv1d + + self.pos_conv = PosConv( + self.embedding_dim, + self.embedding_dim, + kernel_size=args.conv_pos, + padding=args.conv_pos // 2, + groups=args.conv_pos_groups, + ) + dropout = 0 + std = math.sqrt((4 * (1.0 - dropout)) / (args.conv_pos * self.embedding_dim)) + nn.init.normal_(self.pos_conv.weight, mean=0, std=std) + nn.init.constant_(self.pos_conv.bias, 0) + + self.pos_conv = nn.utils.weight_norm(self.pos_conv, name="weight", dim=2) + self.pos_conv = nn.Sequential(self.pos_conv, SamePad(args.conv_pos), nn.GELU()) + + def create_decoder_layers(n_layers): + return nn.ModuleList([ + TransformerSentenceEncoderLayer( + embedding_dim=self.embedding_dim, + ffn_embedding_dim=args.encoder_ffn_embed_dim, + num_attention_heads=args.encoder_attention_heads, + dropout=self.dropout, + attention_dropout=args.attention_dropout, + activation_dropout=args.activation_dropout, + activation_fn=args.activation_fn, + layer_norm_first=args.layer_norm_first, + rotary_embeddings=args.rotary_embeddings, + mha=args.mha, + fp32_transformer_layernorm=args.fp32_transformer_layernorm, + fp32_mha_softmax=args.fp32_mha_softmax, + ) + for _ in range(n_layers) + ]) + + if args.hourglass_transformer: + n_pre, (n_hourglass, self.shorten_factor), n_post = eval( + args.hourglass_transformer) + + self.layers = create_decoder_layers(n_pre) + self.hourglass_layers = create_decoder_layers(n_hourglass) + self.post_layers = create_decoder_layers(n_post) + + assert args.hourglass_resample in ['linear', 'naive'] + # otherwise i want to resample before merging resutls + assert not args.layer_norm_first + + kw = {'emb_dim': self.embedding_dim, 'factor': self.shorten_factor, + 'mode': args.hourglass_resample} + self.upsample_layer = Upsampler(**kw) + self.downsample_layer = Downsampler(**kw) + else: + self.layers = create_decoder_layers(args.encoder_layers) + self.hourglass_layers = None + self.post_layers = None + + self.layer_norm_first = args.layer_norm_first + self.layer_norm = LayerNorm(self.embedding_dim) + self.layerdrop = args.encoder_layerdrop + + self.apply(init_bert_params) + + def forward(self, x: Tensor, padding_mask: Optional[Tensor] = None, + layer: int = -1): + + x, layer_results = self.extract_features(x, padding_mask, layer) + + if self.layer_norm_first and layer == -1: + x = self.layer_norm(x) + + return x, layer_results + + def process_layers(self, x: Tensor, padding_mask: Optional[Tensor], + tgt_layer: int = -1): + + for i, layer in enumerate(self.layers): + if not self.training or (torch.rand(1) > self.layerdrop): + x, _ = layer(x, self_attn_padding_mask=padding_mask, + need_weights=False) + if i == tgt_layer: + return x + return x + + def process_hourglass_layers(self, x: Tensor, padding_mask: + Optional[Tensor], tgt_layer: int = -1): + + for i, layer in enumerate(self.hourglass_layers): + if not self.training or (torch.rand(1) > self.layerdrop): + x, _ = layer(x, self_attn_padding_mask=padding_mask, + need_weights=False) + if i == tgt_layer: + return x + return x + + def process_post_layers(self, x: Tensor, padding_mask: Optional[Tensor], + tgt_layer: int = -1): + + if self.post_layers is None: + return x + else: + for i, layer in enumerate(self.post_layers): + if not self.training or (torch.rand(1) > self.layerdrop): + x, _ = layer(x, self_attn_padding_mask=padding_mask, + need_weights=False) + if i == tgt_layer: + return x + return x + + def extract_features(self, x: Tensor, padding_mask: Optional[Tensor] = None, + tgt_layer: int = -1): + + if padding_mask is not None: + x[padding_mask] = 0 + + x_conv = self.pos_conv(x.transpose(1, 2)) + x_conv = x_conv.transpose(1, 2) + x = x + x_conv + + if not self.layer_norm_first: + x = self.layer_norm(x) + + x = F.dropout(x, p=self.dropout, training=self.training) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + if self.hourglass_layers is not None: + # we don't want to take outputs from inside of hourglass + # as they are shortened and differnt + n_layers_before_upsampling = (len(self.layers) # pre layers + + len(self.hourglass_layers)) + assert tgt_layer == -1 or tgt_layer >= n_layers_before_upsampling + if tgt_layer is not None: + tgt_layer = tgt_layer - n_layers_before_upsampling + + x = self.process_layers(x, padding_mask) + res = x + hourglass_pad_mask = padding_mask + + diff = ((self.shorten_factor - x.size(0) % self.shorten_factor) + % self.shorten_factor) + + if diff != 0: + x = torch.cat([x, x.new_zeros(diff, x.size(1), x.size(2))]) + + if hourglass_pad_mask is not None: + if diff != 0: + hourglass_pad_mask = torch.cat([ + hourglass_pad_mask, + x.new_ones(hourglass_pad_mask.size(0), diff) + ], dim=1) + + hourglass_pad_mask = (F.avg_pool1d( + hourglass_pad_mask.unsqueeze(0).float(), + self.shorten_factor, + self.shorten_factor + ).int() > 0).squeeze(0) + + x = self.downsample_layer(x) + x = self.process_hourglass_layers(x, hourglass_pad_mask) + x = self.upsample_layer(x) + + if diff != 0: + x = x[:-diff] + + x = x + res + x = self.process_post_layers(x, padding_mask, tgt_layer) + else: + x = self.process_layers(x, padding_mask, tgt_layer) + + # T x B x C -> B x T x C + return x.transpose(0, 1), [] + + def max_positions(self): + """Maximum output length supported by the encoder.""" + return self.args.max_positions + + def upgrade_state_dict_named(self, state_dict, name): + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + return state_dict + + +class TransformerSentenceEncoderLayer(nn.Module): + """ + Implements a Transformer Encoder Layer used in BERT/XLM style pre-trained + models. + """ + + def __init__( + self, + embedding_dim: float = 768, + ffn_embedding_dim: float = 3072, + num_attention_heads: float = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + activation_fn: str = "relu", + layer_norm_first: bool = False, + rotary_embeddings: bool = False, + mha: str = 'fairseq', + fp32_transformer_layernorm: bool = False, + fp32_mha_softmax: bool = False, + ) -> None: + + assert not fp32_mha_softmax, "Support for FP32 MHA Softmax disabled" + + super().__init__() + # Initialize parameters + self.embedding_dim = embedding_dim + self.dropout = dropout + self.activation_dropout = activation_dropout + + # Initialize blocks + self.activation_fn = utils.get_activation_fn(activation_fn) + + MHA = {'fairseq': MultiheadAttention, + 'pyt': PytMultiheadAttention}[mha] + + self.self_attn = MHA( + self.embedding_dim, + num_attention_heads, + dropout=attention_dropout, + self_attention=True, + rotary_embeddings=rotary_embeddings + ) + + self.dropout1 = nn.Dropout(dropout) + self.dropout2 = nn.Dropout(self.activation_dropout) + self.dropout3 = nn.Dropout(dropout) + + self.layer_norm_first = layer_norm_first + + LN = Fp32LayerNorm if fp32_transformer_layernorm else LayerNorm + + # layer norm associated with the self attention layer + self.self_attn_layer_norm = LN(self.embedding_dim) + self.fc1 = nn.Linear(self.embedding_dim, ffn_embedding_dim) + self.fc2 = nn.Linear(ffn_embedding_dim, self.embedding_dim) + + # layer norm associated with the position wise feed-forward NN + self.final_layer_norm = LN(self.embedding_dim) + + def forward( + self, + x: torch.Tensor, + self_attn_mask: Optional[Tensor] = None, + self_attn_padding_mask: Optional[Tensor] = None, + need_weights: bool = False, + ): + """ + LayerNorm is applied either before or after the self-attention/ffn + modules similar to the original Transformer imlementation. + """ + residual = x + + if self.layer_norm_first: + x = self.self_attn_layer_norm(x) + x, attn = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=self_attn_padding_mask, + attn_mask=self_attn_mask, + ) + x = self.dropout1(x) + x = residual + x + + residual = x + x = self.final_layer_norm(x) + x = self.activation_fn(self.fc1(x)) + x = self.dropout2(x) + x = self.fc2(x) + x = self.dropout3(x) + x = residual + x + else: + x, attn = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=self_attn_padding_mask, + ) + + x = self.dropout1(x) + x = residual + x + + x = self.self_attn_layer_norm(x) + + residual = x + x = self.activation_fn(self.fc1(x)) + x = self.dropout2(x) + x = self.fc2(x) + x = self.dropout3(x) + x = residual + x + x = self.final_layer_norm(x) + + return x, attn + + +class Wav2VecEncoder(nn.Module): + def __init__(self, cfg, init_state_dict=None, output_size=None): + super().__init__() + + self.apply_mask = cfg.apply_mask + self.w2v_model = Wav2Vec2Model(cfg) + + if init_state_dict is not None: + load_wrapped_state(self.w2v_model, init_state_dict) + + self.w2v_model.remove_pretraining_modules() + + d = cfg.encoder_embed_dim + + self.final_dropout = nn.Dropout(cfg.final_dropout) + self.freeze_finetune_updates = cfg.freeze_finetune_updates + self.num_updates = 0 + + tgt_d = None + self.proj = None + + if output_size is not None: + tgt_d = output_size + elif getattr(cfg, "decoder_embed_dim", d) != d: + tgt_d = cfg.decoder_embed_dim + + if tgt_d is not None: + self.proj = Linear(d, tgt_d) + + def set_num_updates(self, num_updates): + """Set the number of parameters updates.""" + self.num_updates = num_updates + + def extract_features(self, source, padding_mask, layer): + + assert not self.training + + with torch.no_grad(): + out = self.w2v_model.extract_features( + source=source, padding_mask=padding_mask, mask=False, + layer=layer) + + return out + + def infer(self, source: Tensor, padding_mask: Optional[Tensor], + tbc: bool = True): + assert padding_mask is not None + + x, padding_mask = self.w2v_model.infer(source, padding_mask) + + if tbc: + # BTC -> TBC + x = x.transpose(0, 1) + + x = self.final_dropout(x) + + if self.proj is not None: + x = self.proj(x) + + return x, padding_mask + + def forward(self, source: Tensor, padding_mask: Optional[Tensor], + tbc: bool = True): + + ft = self.freeze_finetune_updates <= self.num_updates + + with torch.no_grad() if not ft else contextlib.ExitStack(): + res = self.w2v_model.extract_features( + source=source, + padding_mask=padding_mask, + mask=self.apply_mask and self.training + ) + + x = res["x"] + padding_mask = res["padding_mask"] + layer_results = res["layer_results"] + + if tbc: + # BTC -> TBC + x = x.transpose(0, 1) + + x = self.final_dropout(x) + + if self.proj is not None: + x = self.proj(x) + + return { + "encoder_out": x, # T x B x C + "encoder_padding_mask": padding_mask.transpose(0, 1) + if padding_mask is not None + else None, # T x B + "padding_mask": padding_mask, + "layer_results": layer_results, + } + + def reorder_encoder_out(self, encoder_out, new_order): + if encoder_out["encoder_out"] is not None: + encoder_out["encoder_out"] = encoder_out["encoder_out"].index_select( + 1, new_order + ) + if encoder_out["encoder_padding_mask"] is not None: + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(0, new_order) + return encoder_out + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return None + + def upgrade_state_dict_named(self, state_dict, name): + return state_dict + + +class Wav2VecCtc(nn.Module): + def __init__(self, cfg, w2v_encoder): + super().__init__() + self.cfg = cfg + self.w2v_encoder = w2v_encoder + self.blank_weight = cfg.blank_weight + self.blank_mode = cfg.blank_mode + + def upgrade_state_dict_named(self, state_dict, name): + super().upgrade_state_dict_named(state_dict, name) + return state_dict + + @torch.jit.export + def get_logits(self, logits: Tensor, padding_mask: Optional[Tensor], normalize: bool = False): + + if self.blank_weight != 0: + if self.blank_mode == "add": + logits[..., 0] += self.blank_weight + elif self.blank_mode == "set": + logits[..., 0] = self.blank_weight + else: + raise ValueError(f"invalid blank mode {self.blank_mode}") + + if padding_mask is not None and padding_mask.any(): + num_classes = logits.size(-1) + masking_tensor = torch.full((num_classes,), float("-inf"), + dtype=logits.dtype, device=logits.device) + masking_tensor[0] = 0 + logits[padding_mask.T] = masking_tensor + + if normalize: + logits = F.log_softmax(logits.float(), dim=-1) + + return logits + + @torch.jit.export + def get_normalized_probs(self, logits: Tensor, padding_mask: Optional[Tensor], log_probs: bool): + """Get normalized probabilities (or log probs) from a net's output.""" + + logits = self.get_logits(logits, padding_mask, normalize=False) + + if log_probs: + return F.log_softmax(logits.float(), dim=-1) + else: + return F.softmax(logits.float(), dim=-1) + + def forward(self, source: Tensor, padding_mask: Optional[Tensor], + tbc: bool = True): + return self.w2v_encoder(source, padding_mask, tbc) + + def set_num_updates(self, num_updates): + """Set the number of parameters updates.""" + self.w2v_encoder.set_num_updates(num_updates) diff --git a/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/utils.py b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/utils.py new file mode 100644 index 000000000..53beca50e --- /dev/null +++ b/PyTorch/SpeechRecognition/wav2vec2/wav2vec2/utils.py @@ -0,0 +1,193 @@ +# Copyright (c) 2017-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the license found in the LICENSE file in +# the root directory of this source tree. An additional grant of patent rights +# can be found in the PATENTS file in the same directory. + +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import os +from functools import reduce +from pathlib import Path + +import torch + +import wav2vec2.arg_parser +from common.fairseq.data import AddTargetDataset, FileAudioDataset +from common.utils import AttrDict, print_once +from wav2vec2.model import Wav2Vec2Model, Wav2VecEncoder, Wav2VecCtc + + +blank_symbol = "" # for CTC + + +# Supervised CTC training +class LabelEncoder(object): + def __init__(self, dictionary): + self.dictionary = dictionary + + def __call__(self, label): + return self.dictionary.encode_line( + label, append_eos=False, add_if_not_exist=False + ) + + +# For frame-wise phoneme labels +class PhoneLabelEncoder: + def __call__(self, label): + return torch.IntTensor([int(id) for id in label.split()]) + + +def load_dataset(split, args, target_dictionary=None, with_labels=False, + training=True): + + dataset = FileAudioDataset( + manifest_path=Path(args.data, f'{split}.tsv'), + sample_rate=args.sample_rate, + min_sample_size=args.min_sample_size if training else None, + max_sample_size=args.max_sample_size if training else None, + pad=(hasattr(args, 'labels') or args.enable_padding), + normalize=args.normalize, + num_buckets=args.num_batch_buckets, + compute_mask_indices=False, + repeat_to_refsize=(args.num_concat_batches > 1), + ) + + if with_labels: + assert args.labels + assert hasattr(args, 'labels') + + skip_inds = getattr(dataset, "skipped_indices", set()) + with open(Path(args.data, f"{split}.{args.labels}")) as f: + labels = [line for i, line in enumerate(f) if i not in skip_inds] + + assert len(labels) == len(dataset), ( + f"labels length ({len(labels)}) and dataset length " + f"({len(dataset)}) do not match" + ) + + dataset = AddTargetDataset( + dataset, + labels, + pad=target_dictionary.pad(), + eos=target_dictionary.eos(), + batch_targets=True, + process_label=LabelEncoder(target_dictionary), + add_to_input=False + ) + + return dataset + + +def load_phone_classification_dataset(split, args): + + assert not args.labels + + manifest_path = os.path.join(args.data, "{}.tsv".format(split)) + + dataset = FileAudioDataset( + manifest_path=manifest_path, + sample_rate=args.sample_rate, + max_sample_size=args.max_sample_size, + min_sample_size=args.min_sample_size, + pad=args.labels is not None or args.enable_padding, + normalize=args.normalize, + num_buckets=args.num_batch_buckets, + compute_mask_indices=False, + ) + + return dataset + + +def _prune_infer_state_dict_prefix(state_dict, + prefix='w2v_encoder.w2v_model.'): + pref_len = len(prefix) + return { + (k[pref_len:] if k.startswith(prefix) else k): v + for k, v in state_dict.items() + } + + +def build_model(args, mode='pretrain', target_dictionary=None): + + cfg = AttrDict(vars(args)) + if mode == 'pretrain': + assert target_dictionary is None + model = Wav2Vec2Model(cfg) + elif mode == 'finetune': + state = torch.load(args.w2v_path, map_location='cpu')['model'] + enc = Wav2VecEncoder(cfg, state, output_size=len(target_dictionary)) + model = Wav2VecCtc(cfg, enc) + elif mode == 'infer': + enc = Wav2VecEncoder(cfg, None, output_size=len(target_dictionary)) + model = Wav2VecCtc(cfg, enc) + else: + raise ValueError + + sequence_generator = None + tokenizer = None + + actualized_cfg = getattr(model, "cfg", None) + if actualized_cfg is not None and "w2v_args" in actualized_cfg: + cfg.w2v_args = actualized_cfg.w2v_args + + return model, sequence_generator, tokenizer + + +def build_phone_classification_model(args): + model = Wav2VecEncoder(args) + + actualized_cfg = getattr(model, "cfg", None) + if actualized_cfg is not None: + if "w2v_args" in actualized_cfg: + raise NotImplementedError + return model + + +def get_ckpt_args(ckpt): + """Return a dictionary of args saved inside a ckpt. + + Handles old and new Fairseq ckpts, Nvidia DLE ckpts. + """ + if "cfg" in ckpt: + import omegaconf + w2v_args = omegaconf.OmegaConf.to_container(ckpt["cfg"]) + # Flatten nested dicts (hopefully matching keys have same values) + w2v_args = reduce(lambda a, b: {**(a or {}), **(b or {})}, + w2v_args.values()) + else: # Legacy checkpoints + w2v_args = ckpt["args"] + if type(w2v_args) is argparse.Namespace: + w2v_args = vars(w2v_args) + return w2v_args + + +def update_args_for_finetuning(args, w2v_path_for_args): + w2v_args = get_ckpt_args(torch.load(w2v_path_for_args, map_location="cpu")) + + pretrain_parser = argparse.ArgumentParser() + wav2vec2.arg_parser.populate_pretraining(pretrain_parser) + my_args = vars(pretrain_parser.parse_args([])) + + for arg in my_args: + if arg in w2v_args and my_args[arg] != w2v_args[arg]: + fname = Path(args.w2v_path).name + print_once(f'Setting from {fname}: {arg}={w2v_args[arg]}', + local_rank=args.local_rank) + setattr(args, arg, w2v_args[arg]) + else: + setattr(args, arg, my_args[arg]) diff --git a/PyTorch/SpeechSynthesis/FastPitch/Dockerfile b/PyTorch/SpeechSynthesis/FastPitch/Dockerfile index a16c55e0f..56b496c82 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/Dockerfile +++ b/PyTorch/SpeechSynthesis/FastPitch/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:21.05-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.08-py3 FROM ${FROM_IMAGE_NAME} ENV PYTHONPATH /workspace/fastpitch diff --git a/PyTorch/SpeechSynthesis/FastPitch/README.md b/PyTorch/SpeechSynthesis/FastPitch/README.md index 3c070d4a1..e06ccbfb9 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/README.md +++ b/PyTorch/SpeechSynthesis/FastPitch/README.md @@ -25,6 +25,7 @@ This repository provides a script and recipe to train the FastPitch model to ach * [Multi-dataset](#multi-dataset) * [Training process](#training-process) * [Inference process](#inference-process) + * [Example: Training a model on Mandarin Chinese](#example-training-a-model-on-mandarin-chinese) - [Performance](#performance) * [Benchmarking](#benchmarking) * [Training performance benchmark](#training-performance-benchmark) @@ -50,22 +51,22 @@ This repository provides a script and recipe to train the FastPitch model to ach [FastPitch](https://arxiv.org/abs/2006.06873) is one of two major components in a neural, text-to-speech (TTS) system: * a mel-spectrogram generator such as [FastPitch](https://arxiv.org/abs/2006.06873) or [Tacotron 2](https://arxiv.org/abs/1712.05884), and -* a waveform synthesizer such as [WaveGlow](https://arxiv.org/abs/1811.00002) (see [NVIDIA example code](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2)). +* a waveform synthesizer such as [WaveGlow](https://arxiv.org/abs/1811.00002) (refer to [NVIDIA example code](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2)). -Such two-component TTS system is able to synthesize natural sounding speech from raw transcripts. +Such a two-component TTS system is able to synthesize natural-sounding speech from raw transcripts. The FastPitch model generates mel-spectrograms and predicts a pitch contour from raw input text. In version 1.1, it does not need any pre-trained aligning model to bootstrap from. -It allows to exert additional control over the synthesized utterances, such as: +It allows exerting additional control over the synthesized utterances, such as: * modify the pitch contour to control the prosody, -* increase or decrease the fundamental frequency in a naturally sounding way, that preserves the perceived identity of the speaker, +* increase or decrease the fundamental frequency in a natural sounding way, that preserves the perceived identity of the speaker, * alter the rate of speech, * adjust the energy, * specify input as graphemes or phonemes, * switch speakers when the model has been trained with data from multiple speakers. Some of the capabilities of FastPitch are presented on the website with [samples](https://fastpitch.github.io/). -Speech synthesized with FastPitch has state-of-the-art quality, and does not suffer from missing/repeating phrases like Tacotron 2 does. +Speech synthesized with FastPitch has state-of-the-art quality, and does not suffer from missing/repeating phrases as Tacotron 2 does. This is reflected in Mean Opinion Scores ([details](https://arxiv.org/abs/2006.06873)). | Model | Mean Opinion Score (MOS) | @@ -93,7 +94,7 @@ The FastPitch model is similar to [FastSpeech2](https://arxiv.org/abs/2006.04558 FastPitch is trained on a publicly available [LJ Speech dataset](https://keithito.com/LJ-Speech-Dataset/). -This model is trained with mixed precision using Tensor Cores on Volta, Turing, and the NVIDIA Ampere GPU architectures. Therefore, researchers can get results from 2.0x to 2.7x faster than training without Tensor Cores, while experiencing the benefits of mixed precision training. This model is tested against each NGC monthly container release to ensure consistent accuracy and performance over time. +This model is trained with mixed precision using Tensor Cores on NVIDIA Volta, NVIDIA Turing, and the NVIDIA Ampere GPU architectures. Therefore, researchers can get results from 2.0x to 2.7x faster than training without Tensor Cores while experiencing the benefits of mixed precision training. This model is tested against each NGC monthly container release to ensure consistent accuracy and performance over time. ### Model architecture @@ -105,14 +106,14 @@ from raw text (Figure 1). The entire process is parallel, which means that all i

Figure 1. Architecture of FastPitch (source). The model is composed of a bidirectional Transformer backbone (also known as a Transformer encoder), a pitch predictor, and a duration predictor. After passing through the first *N* Transformer blocks, encoding, the signal is augmented with pitch information and discretely upsampled. Then it goes through another set of *N* Transformer blocks, with the goal of -smoothing out the upsampled signal, and constructing a mel-spectrogram. +smoothing out the upsampled signal and constructing a mel-spectrogram.

### Default configuration The FastPitch model supports multi-GPU and mixed precision training with dynamic loss -scaling (see Apex code +scaling (refer to Apex code [here](https://github.com/NVIDIA/apex/blob/master/apex/fp16_utils/loss_scaler.py)), as well as mixed precision inference. @@ -123,9 +124,9 @@ The following features were implemented in this model: training, * gradient accumulation for reproducible results regardless of the number of GPUs. -Pitch contours and mel-spectrograms can be generated on-line during training. +Pitch contours and mel-spectrograms can be generated online during training. To speed-up training, those could be generated during the pre-processing step and read -directly from the disk during training. For more information on data pre-processing refer to [Dataset guidelines +directly from the disk during training. For more information on data pre-processing, refer to [Dataset guidelines ](#dataset-guidelines) and the [paper](https://arxiv.org/abs/2006.06873). ### Feature support matrix @@ -144,21 +145,21 @@ implementation of mixed precision training. It allows us to use FP16 training with FP32 master weights by modifying just a few lines of code. DistributedDataParallel (DDP) - The model uses PyTorch Lightning implementation -of distributed data parallelism at the module level which can run across +of distributed data parallelism at the module level, which can run across multiple machines. ### Mixed precision training -Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in Volta, and following with both the Turing and Ampere architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures. Using mixed precision training requires two steps: +Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in NVIDIA Volta, and following with both the Turing and Ampere architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures. Using mixed precision training requires two steps: 1. Porting the model to use the FP16 data type where appropriate. 2. Adding loss scaling to preserve small gradient values. The ability to train deep learning networks with lower precision was introduced in the Pascal architecture and first supported in [CUDA 8](https://devblogs.nvidia.com/parallelforall/tag/fp16/) in the NVIDIA Deep Learning SDK. For information about: -- How to train using mixed precision, see the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) documentation. -- Techniques used for mixed precision training, see the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. -- APEX tools for mixed precision training, see the [NVIDIA Apex: Tools for Easy Mixed-Precision Training in PyTorch](https://devblogs.nvidia.com/apex-pytorch-easy-mixed-precision-training/). +- How to train using mixed precision, refer to the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) documentation. +- Techniques used for mixed precision training, refer to the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. +- APEX tools for mixed precision training, refer to the [NVIDIA Apex: Tools for Easy Mixed-Precision Training in PyTorch](https://devblogs.nvidia.com/apex-pytorch-easy-mixed-precision-training/). #### Enabling mixed precision @@ -167,9 +168,9 @@ Mixed precision is using [native PyTorch implementation](https://pytorch.org/blo #### Enabling TF32 -TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on Volta GPUs. +TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math, also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on Volta GPUs. -TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require high dynamic range for weights or activations. +TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require a high dynamic range for weights or activations. For more information, refer to the [TensorFloat-32 in the A100 GPU Accelerates AI Training, HPC up to 20x](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) blog post. @@ -178,10 +179,10 @@ TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by defaul ### Glossary **Character duration** -The time during which a character is being articulated. Could be measured in milliseconds, mel-spectrogram frames, etc. Some characters are not pronounced, and thus have 0 duration. +The time during which a character is being articulated. It could be measured in milliseconds, mel-spectrogram frames, and so on. Some characters are not pronounced, and thus, have 0 duration. **Fundamental frequency** -The lowest vibration frequency of a periodic soundwave, for example, produced by a vibrating instrument. It is perceived as the loudest. In the context of speech, it refers to the frequency of vibration of vocal chords. Abbreviated as *f0*. +The lowest vibration frequency of a periodic soundwave, for example, is produced by a vibrating instrument, and it is perceived as the loudest. In the context of speech, it refers to the frequency of vibration of vocal cords. It is abbreviated as *f0*. **Pitch** A perceived frequency of vibration of music or sound. @@ -195,9 +196,9 @@ The following section lists the requirements that you need to meet in order to s ### Requirements -This repository contains Dockerfile which extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: +This repository contains Dockerfile that extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: - [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -- [PyTorch 21.05-py3 NGC container](https://ngc.nvidia.com/registry/nvidia-pytorch) +- [PyTorch 22.08-py3 NGC container](https://ngc.nvidia.com/registry/nvidia-pytorch) or newer - supported GPUs: - [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) @@ -205,16 +206,16 @@ or newer - [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) -For more information about how to get started with NGC containers, see the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: +For more information about how to get started with NGC containers, refer to the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: - [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) - [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) - [Running PyTorch](https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes/running.html#running) -For those unable to use the PyTorch NGC container, to set up the required environment or create your own container, see the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). +For those unable to use the PyTorch NGC container, to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). ## Quick Start Guide -To train your model using mixed or TF32 precision with Tensor Cores or using FP32, perform the following steps using the default parameters of the FastPitch model on the LJSpeech 1.1 dataset. For the specifics concerning training and inference, see the [Advanced](#advanced) section. Pre-trained FastPitch models are available for download on [NGC](https://ngc.nvidia.com/catalog/models?query=FastPitch&quickFilter=models). +To train your model using mixed or TF32 precision with Tensor Cores or using FP32, perform the following steps using the default parameters of the FastPitch model on the LJSpeech 1.1 dataset. For the specifics concerning training and inference, refer to the [Advanced](#advanced) section. Pre-trained FastPitch models are available for download on [NGC](https://ngc.nvidia.com/catalog/models?query=FastPitch&quickFilter=models). 1. Clone the repository. ```bash @@ -224,7 +225,7 @@ To train your model using mixed or TF32 precision with Tensor Cores or using FP3 2. Build and run the FastPitch PyTorch NGC container. - By default the container will use all available GPUs. + By default, the container will use all available GPUs. ```bash bash scripts/docker/build.sh bash scripts/docker/interactive.sh @@ -232,20 +233,20 @@ To train your model using mixed or TF32 precision with Tensor Cores or using FP3 3. Download and preprocess the dataset. - Use the scripts to automatically download and preprocess the training, validation and test datasets: + Use the scripts to automatically download and preprocess the training, validation, and test datasets: ```bash bash scripts/download_dataset.sh bash scripts/prepare_dataset.sh ``` - The data is downloaded to the `./LJSpeech-1.1` directory (on the host). The + The data is downloaded to the `./LJSpeech-1.1` directory (on the host). The `./LJSpeech-1.1` directory is mounted under the `/workspace/fastpitch/LJSpeech-1.1` location in the NGC container. The complete dataset has the following structure: ```bash ./LJSpeech-1.1 - ├── mels # (optional) Pre-calculated target mel-spectrograms; may be calculated on-line + ├── mels # (optional) Pre-calculated target mel-spectrograms; can be calculated online ├── metadata.csv # Mapping of waveforms to utterances - ├── pitch # Fundamental frequency countours for input utterances; may be calculated on-line + ├── pitch # Fundamental frequency contours for input utterances; can be calculated online ├── README └── wavs # Raw waveforms ``` @@ -309,17 +310,17 @@ given model * `/loss_function.py` - loss function for the model In the root directory `./` of this repository, the `./train.py` script is used for -training while inference can be executed with the `./inference.py` script. The -script `./models.py` is used to construct a model of requested type and properties. +training, while inference can be executed with the `./inference.py` script. The +script `./models.py` is used to construct a model of the requested type and properties. -The repository is structured similarly to the [NVIDIA Tacotron2 Deep Learning example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2), so that they could be combined in more advanced use cases. +The repository is structured similarly to the [NVIDIA Tacotron2 Deep Learning example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2) so that they could be combined in more advanced use cases. ### Parameters In this section, we list the most important hyperparameters and command-line arguments, together with their default values that are used to train FastPitch. -* `--epochs` - number of epochs (default: 1500) +* `--epochs` - number of epochs (default: 1000) * `--learning-rate` - learning rate (default: 0.1) * `--batch-size` - batch size for a single forward-backward step (default: 16) * `--grad-accumulation` - number of steps over which gradients are accumulated (default: 2) @@ -330,8 +331,8 @@ together with their default values that are used to train FastPitch. ### Command-line options -To see the full list of available options and their descriptions, use the `-h` -or `--help` command line option, for example: +To review the full list of available options and their descriptions, use the `-h` +or `--help` command-line option, for example: ```bash python train.py --help ``` @@ -351,7 +352,7 @@ The `./scripts/download_dataset.sh` script will automatically download and extra #### Dataset guidelines -The LJSpeech dataset has 13,100 clips that amount to about 24 hours of speech of a single, female speaker. Since the original dataset does not define a train/dev/test split of the data, we provide a split in the form of three file lists: +The LJSpeech dataset has 13,100 clips that amount to about 24 hours of speech of a single female speaker. Since the original dataset does not define a train/dev/test split of the data, we provide a split in the form of three file lists: ```bash ./filelists ├── ljs_audio_pitch_text_train_v3.txt @@ -359,10 +360,10 @@ The LJSpeech dataset has 13,100 clips that amount to about 24 hours of speech of └── ljs_audio_pitch_text_val.txt ``` -FastPitch predicts character durations just like [FastSpeech](https://arxiv.org/abs/1905.09263) does. +FastPitch predicts character durations just as [FastSpeech](https://arxiv.org/abs/1905.09263) does. FastPitch 1.1 aligns input symbols to output mel-spectrogram frames automatically and does not rely on any external aligning model. FastPitch training can now be started on raw waveforms -without any pre-processing: pitch values and mel-spectrograms will be calculated on-line. +without any pre-processing: pitch values and mel-spectrograms will be calculated online. For every mel-spectrogram frame, its fundamental frequency in Hz is estimated with the Probabilistic YIN algorithm. @@ -371,8 +372,8 @@ the Probabilistic YIN algorithm. Pitch contour estimate

- Figure 2. Pitch estimates for mel-spectrogram frames of phrase "in being comparatively" -(in blue) averaged over characters (in red). Silent letters have duration 0 and are omitted. + Figure 2. Pitch estimates for mel-spectrogram frames of the phrase "in being comparatively" +(in blue) averaged over characters (in red). Silent letters have a duration of 0 and are omitted.

#### Multi-dataset @@ -385,7 +386,7 @@ Follow these steps to use datasets different from the default LJSpeech dataset. └── wavs ``` -2. Prepare filelists with transcripts and paths to .wav files. They define training/validation split of the data (test is currently unused): +2. Prepare filelists with transcripts and paths to .wav files. They define the training/validation split of the data (the test is currently unused): ```bash ./filelists ├── my-dataset_audio_text_train.txt @@ -424,7 +425,7 @@ In order to use the prepared dataset, pass the following to the `train.py` scrip ### Training process -FastPitch is trained to generate mel-spectrograms from raw text input. It uses short time Fourier transform (STFT) +FastPitch is trained to generate mel-spectrograms from raw text input. It uses short-time Fourier transform (STFT) to generate target mel-spectrograms from audio waveforms to be the training targets. The training loss is averaged over an entire training epoch, whereas the @@ -478,9 +479,132 @@ Pitch can be adjusted by transforming those pitch cues. A few simple examples ar The flags can be combined. Modify these functions directly in the `inference.py` script to gain more control over the final result. -You can find all the available options by calling `python inference.py --help`. +You can find all the available options by callng `python inference.py --help`. More examples are presented on the website with [samples](https://fastpitch.github.io/). +### Example: Training a model on Mandarin Chinese + +FastPitch can easily be trained or fine-tuned on datasets in various languages. +We present an example of training on the Mandarin Chinese dataset capable of pronouncing +phrases in English (for example, brand names). +For an overview of the deployment of this model in Chunghwa Telecom, +refer to the [blogpost](https://blogs.nvidia.com.tw/2022/06/20/cht-bilingual-speech-synthesis-enables-more-realistic-interactions/) (in Chinese). + + +1. Set up the repository and run a Docker container + + Follow stetps 1. and 2. of the [Quick Start Guide](#quick-start-guide). + +2. Download the data + + The dataset for this section has been provided by Chunghwa Telecom Laboratories + and is available for [download on NGC](https://catalog.ngc.nvidia.com/orgs/nvidia/resources/sf_bilingual_speech_zh_en) + under the CC BY-NC 4.0 license. + + The dataset can be downloaded manually after signing in to NGC as `files.zip` or `SF_bilingual.zip`, depending on the method (manual or via command line). + Afterward, it has to be pre-processed to extract pitch for training and prepare train/dev/test filelists: + ```bash + pip install -r scripts/mandarin_chinese/requirements.txt + bash scripts/mandarin_chinese/prepare_dataset.sh path/to/files.zip + ``` + + The procedure should take about half an hour. If it completes successfully, + `./data/SF_bilingual prepared successfully.` will be written to the standard output. + + After pre-processing, the dataset will be located at `./data/SF_bilingual`, + and training/inference filelists at `./filelists/sf_*`. + +3. Add support for textual inputs in the target language. + + The model is trained end-to-end, and supporting a new language requires + to specify the input `symbol set`, `text normalization` routines, + and (optionally) grapheme-to-phoneme (G2P) conversion for phoneme-based synthesis. + Our main modifications touch the following files: + + ```bash + ./common/text + ├── symbols.py + ├── text_processing.py + └── zh + ├── chinese.py + ├── mandarin_text_processing.py + └── pinyin_dict.txt + ``` + We make small changes to `symbols.py` and `text_processing.py` and keep + the crucial code in the `zh` directory. + + We design our Mandarin Chinese symbol set as an extension of the English + symbol set, appending to `symbols` lists of `_mandarin_phonemes` and `_chinese_punctuation`: + + ```python + # common/text/symbols.py + + def get_symbols(symbol_set='english_basic'): + + # ... + + elif symbol_set == 'english_mandarin_basic': + from .zh.chinese import chinese_punctuations, valid_symbols as mandarin_valid_symbols + + # Prepend "#" to mandarin phonemes to ensure uniqueness (some are the same as uppercase letters): + _mandarin_phonemes = ['#' + s for s in mandarin_valid_symbols] + + _pad = '_' + _punctuation = '!\'(),.:;? ' + _chinese_punctuation = ["#" + p for p in chinese_punctuations] + _special = '-' + _letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + symbols = list(_pad + _special + _punctuation + _letters) + _arpabet + _mandarin_phonemes + _chinese_punctuation + ``` + + Text normalization and G2P are performed by a `TextProcessing` instance. We implement Mandarin text processing + inside a `MandarinTextProcessing` class. For G2P, an off-shelf [pypinyin](https://github.com/mozillazg/python-pinyin) phonemizer and [the CMU Dictionary](http://www.speech.cs.cmu.edu/cgi-bin/cmudict) are used. + `MandarinTextProcessing` is applied to the data only if `english_mandarin_basic` symbol set is in use: + + ```python + # common/text/text_processing.py + + def get_text_processing(symbol_set, text_cleaners, p_arpabet): + if symbol_set in ['englh_basic', 'english_basic_lowercase', 'english_expanded']: + return TextProcessing(symbol_set, text_cleaners, p_arpabet=p_arpabet) + elif symbol_set == 'english_mandarin_basic': + from common.text.zh.mandarin_text_processing import MandarinTextProcessing + return MandarinTextProcessing(symbol_set, text_cleaners, p_arpabet=p_arpabet) + ``` + + Note that text normalization is dependent on the target language, domain, and assumptions + on how normalized the input already is. + +4. Train the model + + The `SF dataset` is rather small (4.5 h compared to 24 h in `LJSpeech-1.1`). + There are numerous English phrases in the transcriptions, such as technical terms + and proper nouns. Thus, it is beneficial to initialize model weights with + a pre-trained English model from NGC, using the flag `--init-from-checkpoint`. + + Note that by initializing with another model, possibly trained on a different symbol set, + we also initialize grapheme/phoneme embedding tables. For this reason, we design + the `english_mandarin_basic` symbol set as an extension of `english_basic`, + so that the same English phonemes would retain their embeddings. + + In order to train, issue + ```bash + NUM_GPUS= GRAD_ACCUMULATION= bash scripts/mandarin_chinese/train.sh + ``` + Adjust the variables to satisfy `$NUM_GPUS x $GRAD_ACCUMULATION = 256`. + + The model will be trained for 1000 epochs. Note that we have disabled mixed-precision + training, as we found it unstable at times on this dataset. + +5. Synthesize + + After training, samples can be synthesized ([audio sample](./audio/com_SF_ce1514_fastpitch_waveglow.wav)): + ```bash + bash scripts/mandarin_chinese/inference.sh + ``` + Paths to specific checkpoints can be supplied as env variables or changed + directly in the `.sh` files. + ## Performance ### Benchmarking @@ -508,7 +632,7 @@ To benchmark the training performance on a specific batch size, run: AMP=false NUM_GPUS=8 BS=16 GRAD_ACCUMULATION=2 EPOCHS=10 bash scripts/train.sh ``` -Each of these scripts runs for 10 epochs and for each epoch measures the +Each of these scripts runs for 10 epochs, and for each epoch, measures the average number of items per second. The performance results can be read from the `nvlog.json` files produced by the commands. @@ -529,7 +653,7 @@ To benchmark the inference performance on a specific batch size, run: The output log files will contain performance numbers for the FastPitch model (number of output mel-spectrogram frames per second, reported as `generator_frames/s w `) -and for WaveGlow (number of output samples per second, reported as ` waveglow_samples/s +and for WaveGlow (nuber of output samples per second, reported as ` waveglow_samples/s `). The `inference.py` script will run a few warm-up iterations before running the benchmark. Inference will be averaged over 100 runs, as set by the `REPEATS` env variable. @@ -542,12 +666,12 @@ and accuracy in training and inference. ##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `./platform/DGXA100_FastPitch_{AMP,TF32}_8GPU.sh` training script in the 21.05-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. +Our results were obtained by running the `./platform/DGXA100_FastPitch_{AMP,TF32}_8GPU.sh` training script in the PyTorch 21.05-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. | Loss (Model/Epoch) | 50 | 250 | 500 | 750 | 1000 | 1250 | 1500 | |:---------------------|------:|------:|------:|------:|------:|------:|------:| -| FastPitch AMP | 3.35 | 2.89 | 2.79 | 2.71 | 2.68 | 2.64 | 2.61 | -| FastPitch TF32 | 3.37 | 2.88 | 2.78 | 2.71 | 2.68 | 2.63 | 2.61 | +| FastPitch AMP | 3.35 | 2.89 | 2.79 | 2.71 | 2.68 | 2.64 | 2.61 | +| FastPitch TF32 | 3.37 | 2.88 | 2.78 | 2.71 | 2.68 | 2.63 | 2.61 | ##### Training accuracy: NVIDIA DGX-1 (8x V100 16GB) @@ -558,8 +682,8 @@ All of the results were produced using the `train.py` script as described in the | Loss (Model/Epoch) | 50 | 250 | 500 | 750 | 1000 | 1250 | 1500 | |:---------------------|------:|------:|------:|------:|------:|------:|------:| -| FastPitch AMP | 3.38 | 2.88 | 2.79 | 2.71 | 2.68 | 2.64 | 2.61 | -| FastPitch FP32 | 3.38 | 2.89 | 2.80 | 2.71 | 2.68 | 2.65 | 2.62 | +| FastPitch AMP | 3.38 | 2.88 | 2.79 | 2.71 | 2.68 | 2.64 | 2.61 | +| FastPitch FP32 | 3.38 | 2.89 | 2.80 | 2.71 | 2.68 | 2.65 | 2.62 |
@@ -570,50 +694,49 @@ All of the results were produced using the `train.py` script as described in the ##### Training performance: NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `./platform/DGXA100_FastPitch_{AMP,TF32}_8GPU.sh` training script in the 21.05-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers, in output mel-scale spectrogram frames per second, were averaged over +Our results were obtained by running the `./platform/DGXA100_FastPitch_{AMP,TF32}_8GPU.sh` training script in the PyTorch 22.08-py3 NGC container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers, in output mel-scale spectrogram frames per second, were averaged over an entire training epoch. -| Batch size / GPU | Grad accumulation | GPUs | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 to mixed precision) | Weak scaling - TF32 | Weak scaling - mixed precision | -|---:|--:|--:|--------:|--------:|-----:|-----:|-----:| -| 32 | 8 | 1 | 97,735 | 101,730 | 1.04 | 1.00 | 1.00 | -| 32 | 2 | 4 | 337,163 | 352,300 | 1.04 | 3.45 | 3.46 | -| 32 | 1 | 8 | 599,221 | 623,498 | 1.04 | 6.13 | 6.13 | +| Batch size / GPU | GPUs | Grad accumulation | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 to mixed precision) | Strong scaling - TF32 | Strong scaling - mixed precision | +|-----:|--:|---:|--------:|----------:|--------:|-----:|------:| +| 128 | 1 | 2 | 141,028 | 148,149 | 1.05 | 1.00 | 1.00 | +| 64 | 4 | 1 | 525,879 | 614,857 | 1.17 | 3.73 | 4.15 | +| 32 | 8 | 1 | 914,350 | 1,022,722 | 1.12 | 6.48 | 6.90 | ###### Expected training time -The following table shows the expected training time for convergence for 1500 epochs: +The following table shows the expected training time for convergence for 1000 epochs: | Batch size / GPU | GPUs | Grad accumulation | Time to train with TF32 (Hrs) | Time to train with mixed precision (Hrs) | Speed-up with mixed precision| -|---:|--:|--:|-----:|-----:|-----:| -| 32 | 1 | 8 | 32.8 | 31.6 | 1.04 | -| 32 | 4 | 2 | 9.6 | 9.2 | 1.04 | -| 32 | 8 | 1 | 5.5 | 5.3 | 1.04 | +|----:|--:|--:|-----:|-----:|-----:| +| 128 | 1 | 2 | 14.5 | 13.8 | 1.05 | +| 64 | 4 | 1 | 4.1 | 3.3 | 1.17 | +| 32 | 8 | 1 | 2.2 | 2.0 | 1.12 | ##### Training performance: NVIDIA DGX-1 (8x V100 16GB) Our results were obtained by running the `./platform/DGX1_FastPitch_{AMP,FP32}_8GPU.sh` -training script in the PyTorch 21.05-py3 NGC container on NVIDIA DGX-1 with +training script in the PyTorch 22.08-py3 NGC container on NVIDIA DGX-1 with 8x V100 16GB GPUs. Performance numbers, in output mel-scale spectrogram frames per second, were averaged over an entire training epoch. | Batch size / GPU | GPUs | Grad accumulation | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 to mixed precision) | Strong scaling - FP32 | Strong scaling - mixed precision | -|---:|--:|---:|--------:|--------:|-----:|-----:|-----:| -| 16 | 1 | 16 | 33,456 | 63,986 | 1.91 | 1.00 | 1.00 | -| 16 | 4 | 4 | 120,393 | 209,335 | 1.74 | 3.60 | 3.27 | -| 16 | 8 | 2 | 222,161 | 356,522 | 1.60 | 6.64 | 5.57 | - +|-----:|---:|-----:|---------:|----------:|--------:|-----:|------:| +| 16 | 1 | 16 | 31,863 | 83,761 | 2.63 | 1.00 | 1.00 | +| 16 | 4 | 4 | 117,971 | 269,143 | 2.28 | 3.70 | 3.21 | +| 16 | 8 | 2 | 225,826 | 435,799 | 1.93 | 7.09 | 5.20 | To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). ###### Expected training time -The following table shows the expected training time for convergence for 1500 epochs: +The following table shows the expected training time for convergence for 1000 epochs: | Batch size / GPU | GPUs | Grad accumulation | Time to train with FP32 (Hrs) | Time to train with mixed precision (Hrs) | Speed-up with mixed precision| |---:|--:|---:|-----:|-----:|-----:| -| 16 | 1 | 16 | 89.3 | 47.4 | 1.91 | -| 16 | 4 | 4 | 24.9 | 14.6 | 1.74 | -| 16 | 8 | 2 | 13.6 | 8.6 | 1.60 | +| 16 | 1 | 16 | 64.2 | 24.4 | 2.63 | +| 16 | 4 | 4 | 17.4 | 7.6 | 2.28 | +| 16 | 8 | 2 | 9.1 | 4.7 | 1.93 | Note that most of the quality is achieved after the initial 1000 epochs. @@ -622,61 +745,128 @@ Note that most of the quality is achieved after the initial 1000 epochs. The following tables show inference statistics for the FastPitch and WaveGlow text-to-speech system, gathered from 100 inference runs. Latency is measured from the start of FastPitch inference to the end of WaveGlow inference. Throughput is measured -as the number of generated audio samples per second at 22KHz. RTF is the real-time factor which denotes the number of seconds of speech generated in a second of wall-clock time, per input utterance. +as the number of generated audio samples per second at 22KHz. RTF is the real-time factor that denotes the number of seconds of speech generated in a second of wall-clock time per input utterance. The used WaveGlow model is a 256-channel model. Note that performance numbers are related to the length of input. The numbers reported below were taken with a moderate length of 128 characters. Longer utterances yield higher RTF, as the generator is fully parallel. ##### Inference performance: NVIDIA DGX A100 (1x A100 80GB) -Our results were obtained by running the `./scripts/inference_benchmark.sh` inferencing benchmarking script in the 21.05-py3 NGC container on NVIDIA DGX A100 (1x A100 80GB) GPU. +Our results were obtained by running the `./scripts/inference_benchmark.sh` inferencing benchmarking script in the PyTorch 22.08-py3 NGC container on NVIDIA DGX A100 (1x A100 80GB) GPU. + +FastPitch (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (frames/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.005 | 0.006 | 0.006 | 0.006 | 120,333 | 0.97 | 1397.07 | +| 4 | FP16 | 0.006 | 0.006 | 0.006 | 0.006 | 424,053 | 1.12 | 1230.81 | +| 8 | FP16 | 0.008 | 0.010 | 0.010 | 0.011 | 669,549 | 1.12 | 971.68 | +| 1 | TF32 | 0.005 | 0.006 | 0.006 | 0.007 | 123,718 | - | 1436.37 | +| 4 | TF32 | 0.007 | 0.007 | 0.007 | 0.007 | 379,980 | - | 1102.89 | +| 8 | TF32 | 0.009 | 0.009 | 0.009 | 0.009 | 600,435 | - | 871.38 | + +FastPitch + HiFi-GAN (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (samples/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.015 | 0.016 | 0.016 | 0.016 | 11,431,335 | 1.28 | 518.43 | +| 4 | FP16 | 0.038 | 0.040 | 0.040 | 0.040 | 17,670,528 | 1.42 | 200.35 | +| 8 | FP16 | 0.069 | 0.069 | 0.070 | 0.070 | 19,750,759 | 1.46 | 111.97 | +| 1 | TF32 | 0.019 | 0.020 | 0.020 | 0.020 | 8,912,296 | - | 404.19 | +| 4 | TF32 | 0.054 | 0.055 | 0.055 | 0.055 | 12,471,624 | - | 141.40 | +| 8 | TF32 | 0.100 | 0.100 | 0.100 | 0.101 | 13,543,317 | - | 76.78 | + +FastPitch + WaveGlow (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (samples/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.076 | 0.077 | 0.077 | 0.078 | 2,223,336 | 1.38 | 100.83 | +| 4 | FP16 | 0.265 | 0.267 | 0.267 | 0.267 | 2,552,577 | 1.36 | 28.94 | +| 8 | FP16 | 0.515 | 0.515 | 0.516 | 0.516 | 2,630,328 | 1.37 | 14.91 | +| 1 | TF32 | 0.105 | 0.106 | 0.106 | 0.107 | 1,610,266 | - | 73.03 | +| 4 | TF32 | 0.362 | 0.363 | 0.363 | 0.363 | 1,872,327 | - | 21.23 | +| 8 | TF32 | 0.708 | 0.709 | 0.709 | 0.709 | 1,915,577 | - | 10.86 | -|Batch size|Precision|Avg latency (s)|Latency tolerance interval 90% (s)|Latency tolerance interval 95% (s)|Latency tolerance interval 99% (s)|Throughput (samples/sec)|Speed-up with mixed precision|Avg RTF| -|-----:|-------:|----------:|--------:|--------:|--------:|---------------:|----------:|------:| -| 1 | FP16 | 0.091 | 0.092 | 0.092 | 0.092 | 1,879,189 | 1.28 | 85.22 | -| 4 | FP16 | 0.335 | 0.337 | 0.337 | 0.338 | 2,043,641 | 1.21 | 23.17 | -| 8 | FP16 | 0.652 | 0.654 | 0.654 | 0.655 | 2,103,765 | 1.21 | 11.93 | -| 1 | TF32 | 0.117 | 0.117 | 0.118 | 0.118 | 1,473,838 | - | 66.84 | -| 4 | TF32 | 0.406 | 0.408 | 0.408 | 0.409 | 1,688,141 | - | 19.14 | -| 8 | TF32 | 0.792 | 0.794 | 0.794 | 0.795 | 1,735,463 | - | 9.84 | ##### Inference performance: NVIDIA DGX-1 (1x V100 16GB) Our results were obtained by running the `./scripts/inference_benchmark.sh` script in -the PyTorch 21.05-py3 NGC container. The input utterance has 128 characters, synthesized audio has 8.05 s. - +the PyTorch 22.08-py3 NGC container. The input utterance has 128 characters, synthesized audio has 8.05 s. + +FastPitch (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (frames/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.007 | 0.008 | 0.008 | 0.008 | 88,908 | 1.10 | 1032.23 | +| 4 | FP16 | 0.010 | 0.010 | 0.010 | 0.010 | 272,564 | 1.73 | 791.12 | +| 8 | FP16 | 0.013 | 0.013 | 0.013 | 0.013 | 415,263 | 2.35 | 602.65 | +| 1 | FP32 | 0.008 | 0.008 | 0.008 | 0.009 | 80,558 | - | 935.28 | +| 4 | FP32 | 0.017 | 0.017 | 0.017 | 0.017 | 157,114 | - | 456.02 | +| 8 | FP32 | 0.030 | 0.030 | 0.030 | 0.030 | 176,754 | - | 256.51 | + +FastPitch + HiFi-GAN (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (samples/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.025 | 0.025 | 0.025 | 0.025 | 6,788,274 | 2.09 | 307.86 | +| 4 | FP16 | 0.067 | 0.068 | 0.068 | 0.068 | 10,066,291 | 2.63 | 114.13 | +| 8 | FP16 | 0.123 | 0.124 | 0.124 | 0.124 | 10,992,774 | 2.78 | 62.32 | +| 1 | FP32 | 0.052 | 0.053 | 0.053 | 0.053 | 3,246,699 | - | 147.24 | +| 4 | FP32 | 0.177 | 0.178 | 0.179 | 0.179 | 3,829,018 | - | 43.41 | +| 8 | FP32 | 0.343 | 0.345 | 0.345 | 0.346 | 3,953,920 | - | 22.41 | + +FastPitch + WaveGlow (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (samples/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.134 | 0.135 | 0.135 | 0.135 | 1,259,550 | 2.89 | 57.12 | +| 4 | FP16 | 0.503 | 0.504 | 0.505 | 0.505 | 1,346,145 | 2.88 | 15.26 | +| 8 | FP16 | 0.995 | 0.999 | 0.999 | 1.001 | 1,360,952 | 2.89 | 7.72 | +| 1 | FP32 | 0.389 | 0.391 | 0.392 | 0.393 | 435,564 | - | 19.75 | +| 4 | FP32 | 1.453 | 1.455 | 1.456 | 1.457 | 466,685 | - | 5.29 | +| 8 | FP32 | 2.875 | 2.879 | 2.880 | 2.882 | 471,602 | - | 2.67 | -|Batch size|Precision|Avg latency (s)|Latency tolerance interval 90% (s)|Latency tolerance interval 95% (s)|Latency tolerance interval 99% (s)|Throughput (samples/sec)|Speed-up with mixed precision|Avg RTF| -|-----:|-------:|----------:|--------:|--------:|--------:|---------------:|----------:|------:| -| 1 | FP16 | 0.149 | 0.150 | 0.150 | 0.151 | 1,154,061 | 2.64 | 52.34 | -| 4 | FP16 | 0.535 | 0.538 | 0.538 | 0.539 | 1,282,680 | 2.71 | 14.54 | -| 8 | FP16 | 1.055 | 1.058 | 1.059 | 1.060 | 1,300,261 | 2.71 | 7.37 | -| 1 | FP32 | 0.393 | 0.395 | 0.395 | 0.396 | 436,961 | - | 19.82 | -| 4 | FP32 | 1.449 | 1.452 | 1.452 | 1.453 | 473,515 | - | 5.37 | -| 8 | FP32 | 2.861 | 2.865 | 2.866 | 2.867 | 479,642 | - | 2.72 | ##### Inference performance: NVIDIA T4 Our results were obtained by running the `./scripts/inference_benchmark.sh` script in -the PyTorch 21.05-py3 NGC container. +the PyTorch 22.08-py3 NGC container. The input utterance has 128 characters, synthesized audio has 8.05 s. -|Batch size|Precision|Avg latency (s)|Latency tolerance interval 90% (s)|Latency tolerance interval 95% (s)|Latency tolerance interval 99% (s)|Throughput (samples/sec)|Speed-up with mixed precision|Avg RTF| -|-----:|-------:|----------:|--------:|--------:|--------:|--------------:|----------:|------:| -| 1 | FP16 | 0.446 | 0.449 | 0.449 | 0.450 | 384,743 | 2.72 | 17.45 | -| 4 | FP16 | 1.822 | 1.826 | 1.827 | 1.828 | 376,480 | 2.70 | 4.27 | -| 8 | FP16 | 3.656 | 3.662 | 3.664 | 3.666 | 375,329 | 2.70 | 2.13 | -| 1 | FP32 | 1.213 | 1.218 | 1.219 | 1.220 | 141,403 | - | 6.41 | -| 4 | FP32 | 4.928 | 4.937 | 4.939 | 4.942 | 139,208 | - | 1.58 | -| 8 | FP32 | 9.853 | 9.868 | 9.871 | 9.877 | 139,266 | - | 0.79 | +FastPitch (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (frames/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.008 | 0.008 | 0.008 | 0.008 | 87,937 | 1.69 | 1020.95 | +| 4 | FP16 | 0.017 | 0.017 | 0.017 | 0.018 | 154,880 | 2.55 | 449.54 | +| 8 | FP16 | 0.029 | 0.030 | 0.030 | 0.030 | 181,776 | 2.61 | 263.80 | +| 1 | FP32 | 0.013 | 0.013 | 0.013 | 0.013 | 52,062 | - | 604.45 | +| 4 | FP32 | 0.044 | 0.045 | 0.045 | 0.045 | 60,733 | - | 176.28 | +| 8 | FP32 | 0.076 | 0.077 | 0.077 | 0.077 | 69,685 | - | 101.13 | + +FastPitch + HiFi-GAN (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (samples/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.055 | 0.056 | 0.056 | 0.057 | 3,076,809 | 2.55 | 139.54 | +| 4 | FP16 | 0.201 | 0.203 | 0.204 | 0.204 | 3,360,014 | 2.67 | 38.10 | +| 8 | FP16 | 0.393 | 0.395 | 0.396 | 0.397 | 3,444,245 | 2.65 | 19.53 | +| 1 | FP32 | 0.140 | 0.142 | 0.142 | 0.142 | 1,208,678 | - | 54.82 | +| 4 | FP32 | 0.538 | 0.542 | 0.543 | 0.545 | 1,260,627 | - | 14.29 | +| 8 | FP32 | 1.045 | 1.049 | 1.050 | 1.051 | 1,297,726 | - | 7.36 | + +FastPitch + WaveGlow (TorchScript, denoising) +| Batch size | Precision | Avg latency (s) | Latency tolerance interval 90% (s) | Latency tolerance interval 95% (s) | Latency tolerance interval 99% (s) | Throughput (samples/sec) | Speed-up with mixed precision | Avg RTF | +|--------------|-------------|-------------------|--------------------------------------|--------------------------------------|--------------------------------------|----------------------------|---------------------------------|-----------| +| 1 | FP16 | 0.409 | 0.411 | 0.411 | 0.412 | 414,019 | 2.65 | 18.78 | +| 4 | FP16 | 1.619 | 1.622 | 1.623 | 1.624 | 418,010 | 2.91 | 4.74 | +| 8 | FP16 | 3.214 | 3.219 | 3.220 | 3.222 | 421,148 | 2.72 | 2.39 | +| 1 | FP32 | 1.084 | 1.087 | 1.088 | 1.089 | 156,345 | - | 7.09 | +| 4 | FP32 | 4.721 | 4.735 | 4.738 | 4.743 | 143,585 | - | 1.63 | +| 8 | FP32 | 8.764 | 8.777 | 8.779 | 8.784 | 154,694 | - | 0.88 | ## Release notes -We're constantly refining and improving our performance on AI and HPC workloads even on the same hardware with frequent updates to our software stack. For our latest performance data please refer to these pages for AI and HPC benchmarks. +We're constantly refining and improving our performance on AI and HPC workloads even on the same hardware, with frequent updates to our software stack. For our latest performance data, refer to these pages for AI and HPC benchmarks. ### Changelog +October 2022 +- Updated performance tables + July 2022 -- Performance optimizations, speedups up to 2x (DGX-1) and 2.5x (DGX A100) +- Performance optimizations, speedups up to 1.2x (DGX-1) and 1.6x (DGX A100) June 2022 - MHA bug fix affecting models with > 1 attention heads @@ -703,4 +893,4 @@ May 2020 ### Known issues -There are no known issues with this model with this model. +There are no known issues with this model. diff --git a/PyTorch/SpeechSynthesis/FastPitch/audio/com_SF_ce1514_fastpitch_waveglow.wav b/PyTorch/SpeechSynthesis/FastPitch/audio/com_SF_ce1514_fastpitch_waveglow.wav new file mode 100644 index 000000000..d4c2201e9 Binary files /dev/null and b/PyTorch/SpeechSynthesis/FastPitch/audio/com_SF_ce1514_fastpitch_waveglow.wav differ diff --git a/PyTorch/SpeechSynthesis/FastPitch/common/text/symbols.py b/PyTorch/SpeechSynthesis/FastPitch/common/text/symbols.py index cfdb5755a..01e5a36c9 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/common/text/symbols.py +++ b/PyTorch/SpeechSynthesis/FastPitch/common/text/symbols.py @@ -31,6 +31,18 @@ def get_symbols(symbol_set='english_basic'): _accented = 'áçéêëñöøćž' _letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' symbols = list(_punctuation + _math + _special + _accented + _letters) + _arpabet + elif symbol_set == 'english_mandarin_basic': + from .zh.chinese import chinese_punctuations, valid_symbols as mandarin_valid_symbols + + # Prepend "#" to mandarin phonemes to ensure uniqueness (some are the same as uppercase letters): + _mandarin_phonemes = ['#' + s for s in mandarin_valid_symbols] + + _pad = '_' + _punctuation = '!\'(),.:;? ' + _chinese_punctuation = ["#" + p for p in chinese_punctuations] + _special = '-' + _letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + symbols = list(_pad + _special + _punctuation + _letters) + _arpabet + _mandarin_phonemes + _chinese_punctuation else: raise Exception("{} symbol set does not exist".format(symbol_set)) @@ -38,7 +50,7 @@ def get_symbols(symbol_set='english_basic'): def get_pad_idx(symbol_set='english_basic'): - if symbol_set in {'english_basic', 'english_basic_lowercase'}: + if symbol_set in {'english_basic', 'english_basic_lowercase', 'english_mandarin_basic'}: return 0 else: raise Exception("{} symbol set not used yet".format(symbol_set)) diff --git a/PyTorch/SpeechSynthesis/FastPitch/common/text/text_processing.py b/PyTorch/SpeechSynthesis/FastPitch/common/text/text_processing.py index b700df1f4..1cd9fcf46 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/common/text/text_processing.py +++ b/PyTorch/SpeechSynthesis/FastPitch/common/text/text_processing.py @@ -162,3 +162,13 @@ def encode_text(self, text, return_all=False): return text_encoded, text_clean, text_arpabet return text_encoded + + +def get_text_processing(symbol_set, text_cleaners, p_arpabet): + if symbol_set in ['english_basic', 'english_basic_lowercase', 'english_expanded']: + return TextProcessing(symbol_set, text_cleaners, p_arpabet=p_arpabet) + elif symbol_set == 'english_mandarin_basic': + from common.text.zh.mandarin_text_processing import MandarinTextProcessing + return MandarinTextProcessing(symbol_set, text_cleaners, p_arpabet=p_arpabet) + else: + raise ValueError(f"No TextProcessing for symbol set {symbol_set} unknown.") diff --git a/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/chinese.py b/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/chinese.py new file mode 100644 index 000000000..3e2d10dda --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/chinese.py @@ -0,0 +1,81 @@ +# ***************************************************************************** +# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the NVIDIA CORPORATION nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ***************************************************************************** + +import re + +from pypinyin import lazy_pinyin, Style + + +valid_symbols = ['^', 'A', 'AI', 'AN', 'ANG', 'AO', 'B', 'C', 'CH', 'D', + 'E', 'EI', 'EN', 'ENG', 'ER', 'F', 'G', 'H', 'I', 'IE', + 'IN', 'ING', 'IU', 'J', 'K', 'L', 'M', 'N', 'O', 'ONG', + 'OU', 'P', 'Q', 'R', 'S', 'SH', 'T', 'U', 'UI', 'UN', + 'V', 'VE', 'VN', 'W', 'X', 'Y', 'Z', 'ZH'] +tones = ['1', '2', '3', '4', '5'] +chinese_punctuations = ",。?!;:、‘’“”()【】「」《》" +valid_symbols += tones + + +def load_pinyin_dict(path="common/text/zh/pinyin_dict.txt"): + with open(path) as f: + return {l.split()[0]: l.split()[1:] for l in f} + +pinyin_dict = load_pinyin_dict() + + +def is_chinese(text): + return u'\u4e00' <= text[0] <= u'\u9fff' or text[0] in chinese_punctuations + + +def split_text(text): + regex = r'([\u4e00-\u9fff' + chinese_punctuations + ']+)' + return re.split(regex, text) + + +def chinese_text_to_symbols(text): + symbols = [] + phonemes_and_tones = "" + + # convert text to mandarin pinyin sequence + # ignore polyphonic words as it has little effect on training + pinyin_seq = lazy_pinyin(text, style=Style.TONE3) + + for item in pinyin_seq: + if item in chinese_punctuations: + symbols += [item] + phonemes_and_tones += ' ' + item + continue + if not item[-1].isdigit(): + item += '5' + item, tone = item[:-1], item[-1] + phonemes = pinyin_dict[item.upper()] + symbols += phonemes + symbols += [tone] + + phonemes_and_tones += '{' + ' '.join(phonemes + [tone]) + '}' + + return symbols, phonemes_and_tones diff --git a/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/mandarin_text_processing.py b/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/mandarin_text_processing.py new file mode 100644 index 000000000..baad2fb83 --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/mandarin_text_processing.py @@ -0,0 +1,74 @@ +import re +import numpy as np +from .chinese import split_text, is_chinese, chinese_text_to_symbols +from ..text_processing import TextProcessing + + +class MandarinTextProcessing(TextProcessing): + def __init__(self, symbol_set, cleaner_names, p_arpabet=0.0, + handle_arpabet='word', handle_arpabet_ambiguous='ignore', + expand_currency=True): + + super().__init__(symbol_set, cleaner_names, p_arpabet, handle_arpabet, + handle_arpabet_ambiguous, expand_currency) + + + def sequence_to_text(self, sequence): + result = '' + + tmp = '' + for symbol_id in sequence: + if symbol_id in self.id_to_symbol: + s = self.id_to_symbol[symbol_id] + # Enclose ARPAbet and mandarin phonemes back in curly braces: + if len(s) > 1 and s[0] == '@': + s = '{%s}' % s[1:] + result += s + elif len(s) > 1 and s[0] == '#' and s[1].isdigit(): # mandarin tone + tmp += s[1] + '} ' + result += tmp + tmp = '' + elif len(s) > 1 and s[0] == '#' and (s[1].isalpha() or s[1] == '^'): # mandarin phoneme + if tmp == '': + tmp += ' {' + s[1:] + ' ' + else: + tmp += s[1:] + ' ' + elif len(s) > 1 and s[0] == '#': # chinese punctuation + s = s[1] + result += s + else: + result += s + + return result.replace('}{', ' ').replace(' ', ' ') + + + def chinese_symbols_to_sequence(self, symbols): + return self.symbols_to_sequence(['#' + s for s in symbols]) + + + def encode_text(self, text, return_all=False): + # split the text into English and Chinese segments + segments = [segment for segment in split_text(text) if segment != ""] + + text_encoded = [] + text_clean = "" + text_arpabet = "" + + for segment in segments: + if is_chinese(segment[0]): # process the Chinese segment + chinese_symbols, segment_arpabet = chinese_text_to_symbols(segment) + segment_encoded = self.chinese_symbols_to_sequence(chinese_symbols) + segment_clean = segment + segment_encoded = segment_encoded + else: # process the English segment + segment_encoded, segment_clean, segment_arpabet = \ + super().encode_text(segment, return_all=True) + + text_encoded += segment_encoded + text_clean += segment_clean + text_arpabet += segment_arpabet + + if return_all: + return text_encoded, text_clean, text_arpabet + + return text_encoded \ No newline at end of file diff --git a/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/pinyin_dict.txt b/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/pinyin_dict.txt new file mode 100644 index 000000000..d2eccb89d --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/common/text/zh/pinyin_dict.txt @@ -0,0 +1,412 @@ +NIN N IN +FA F A +BAI B AI +YIN Y IN +DE D E +SHEN SH EN +TAN T AN +PAO P AO +WENG W ENG +LAN L AN +CHUAN CH U AN +SEI S EI +DANG D ANG +XUE X VE +YUAN Y V AN +HU H U +CUAN C U AN +BO B O +SHAI SH AI +CHUI CH UI +SHOU SH OU +QIU Q IU +SONG S ONG +KAI K AI +LING L ING +SUO S U O +ZHUAI ZH U AI +ZHEN ZH EN +GENG G ENG +YAN Y AN +CU C U +ZHUA ZH U A +MA M A +SOU S OU +GOU G OU +PU P U +GUA G U A +RONG R ONG +JIAN J I AN +FOU F OU +FO F O +ZHUAN ZH U AN +DIU D IU +TIAN T I AN +QUN Q VN +NE N E +LIN L IN +QIE Q IE +LANG L ANG +CAO C AO +PANG P ANG +GAN G AN +KUI K UI +ROU R OU +NING N ING +NOU N OU +CUI C UI +NA N A +MING M ING +JUAN J V AN +NIAN N I AN +JIONG J I ONG +LE L E +GEN G EN +CHUO CH U O +SANG S ANG +MANG M ANG +GANG G ANG +SHENG SH ENG +KENG K ENG +ANG ^ ANG +ZHONG ZH ONG +PEI P EI +LO L O +BEN B EN +SAN S AN +WAI W AI +BA B A +ZEI Z EI +BANG B ANG +MENG M ENG +HA H A +SHAO SH AO +RENG R ENG +XUAN X V AN +GUAI G U AI +QUAN Q V AN +DIE D IE +CEN C EN +QIONG Q I ONG +QIAO Q I AO +NAN N AN +CANG C ANG +NANG N ANG +LA L A +KU K U +KAO K AO +XI X I +MO M O +CHAN CH AN +DUO D U O +DIAO D I AO +HUN H UN +LOU L OU +HANG H ANG +CENG C ENG +ZHI ZH I +RUAN R U AN +QIANG Q I ANG +MIU M IU +WO W O +GEI G EI +EI ^ EI +CHAI CH AI +ZHUI ZH UI +CHU CH U +YONG Y ONG +SHUO SH U O +DING D ING +CHE CH E +YO Y O +PENG P ENG +RANG R ANG +BU B U +NIU N IU +KE K E +MI M I +GUAN G U AN +RE R E +NI N I +TI T I +DIA D I A +NUO N U O +WANG W ANG +QIAN Q I AN +LUO L U O +YA Y A +CI C I +GUN G UN +GAO G AO +DOU D OU +DAI D AI +BAO B AO +BIN B IN +NAI N AI +SE S E +PA P A +ZAO Z AO +AO ^ AO +NIE N IE +BENG B ENG +ZHU ZH U +JU J V +XIU X IU +XIAN X I AN +RUI R UI +SAI S AI +SHUANG SH U ANG +SHUAI SH U AI +HEN H EN +OU ^ OU +HUA H U A +LONG L ONG +ZI Z I +SHE SH E +JUN J VN +YE Y E +TUI T UI +GUANG G U ANG +MAN M AN +LAI L AI +ZHUN ZH UN +CHUANG CH U ANG +ZUI Z UI +SU S U +TE T E +TAO T AO +CONG C ONG +TONG T ONG +HENG H ENG +ZUO Z U O +LU L U +BAN B AN +PIAO P I AO +XIANG X I ANG +LIANG L I ANG +ZU Z U +NIANG N I ANG +LIU L IU +BIE B IE +CHA CH A +YANG Y ANG +LVE L VE +LENG L ENG +KOU K OU +AN ^ AN +CHUN CH UN +ZAI Z AI +DONG D ONG +SHI SH I +CHAO CH AO +ZHAI ZH AI +RI R I +HUAI H U AI +TOU T OU +SENG S ENG +GUO G U O +NENG N ENG +ZUN Z UN +XIONG X I ONG +ZEN Z EN +TANG T ANG +BIAN B I AN +QU Q V +QI Q I +ZHAN ZH AN +JIAO J I AO +CHENG CH ENG +CHONG CH ONG +KEI K EI +MEI M EI +LV L V +SHUA SH U A +CA C A +DENG D ENG +TING T ING +YAO Y AO +TIAO T I AO +ME M E +CE C E +ZUAN Z U AN +SEN S EN +O ^ O +ZENG Z ENG +RAO R AO +WEI W EI +KUAN K U AN +PING P ING +MAI M AI +HUAN H U AN +DEN D EN +BING B ING +QING Q ING +PIN P IN +GAI G AI +LI L I +ZHENG ZH ENG +ZAN Z AN +BEI B EI +SHU SH U +MU M U +KUO K U O +JIE J IE +CHUAI CH U AI +FAN F AN +PI P I +SHUI SH UI +YING Y ING +QIN Q IN +SHA SH A +KANG K ANG +CHEN CH EN +JIANG J I ANG +RAN R AN +LUAN L U AN +HEI H EI +XING X ING +WAN W AN +TA T A +XU X V +TENG T ENG +ZA Z A +KEN K EN +DAN D AN +TU T U +KUANG K U ANG +JING J ING +REN R EN +CHOU CH OU +KUA K U A +HE H E +DAO D AO +NEI N EI +KUAI K U AI +HAO H AO +MIAO M I AO +YI Y I +ZHAO ZH AO +TUO T U O +ZHEI ZH EI +FU F U +FEN F EN +JIA J I A +WA W A +CUO C U O +WU W U +MEN M EN +XUN X VN +MOU M OU +SHAN SH AN +PAI P AI +GONG G ONG +NONG N ONG +COU C OU +KONG K ONG +HUO H U O +HUANG H U ANG +JIU J IU +HONG H ONG +MIE M IE +HUI H UI +WEN W EN +ZHUO ZH U O +MIAN M I AN +BI B I +ZE Z E +YUN Y VN +GA G A +SUAN S U AN +SUN S UN +MAO M AO +XIA X I A +KA K A +NAO N AO +TIE T IE +GE G E +GUI G UI +LAO L AO +ZOU Z OU +SAO S AO +PO P O +JIN J IN +DUAN D U AN +DU D U +RUN R UN +YUE Y VE +DUN D UN +A ^ A +PIE P IE +SHANG SH ANG +XIN X IN +CAN C AN +PAN P AN +LIE L IE +QIA Q I A +GU G U +ZHE ZH E +ZONG Z ONG +DIAN D I AN +LIA L I A +FENG F ENG +JUE J VE +LIAO L I AO +SA S A +TAI T AI +LEI L EI +SHUN SH UN +HAI H AI +NEN N EN +MIN M IN +PIAN P I AN +CHI CH I +CHANG CH ANG +NIAO N I AO +JI J I +TEI T EI +FANG F ANG +POU P OU +QUE Q VE +ZHOU ZH OU +NV N V +ER ^ ER +YU Y V +XIE X IE +FAI F AI +EN ^ EN +NVE N VE +KAN K AN +LUN L UN +ZHUANG ZH U ANG +HAN H AN +NG N EN +DI D I +SHEI SH EI +RUO R U O +KUN K UN +DUI D UI +TUAN T U AN +ZANG Z ANG +CUN C UN +YOU Y OU +SUI S UI +DEI D EI +RU R U +NU N U +ZHANG ZH ANG +BIAO B I AO +NUAN N U AN +SHUAN SH U AN +XIAO X I AO +TUN T UN +E ^ E +SI S I +HOU H OU +FEI F EI +ZHA ZH A +CAI C AI +KIU K IU +DA D A +PEN P EN +LIAN L I AN +AI ^ AI diff --git a/PyTorch/SpeechSynthesis/FastPitch/common/utils.py b/PyTorch/SpeechSynthesis/FastPitch/common/utils.py index e81f1e17b..81ee5642a 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/common/utils.py +++ b/PyTorch/SpeechSynthesis/FastPitch/common/utils.py @@ -137,6 +137,27 @@ def get_padding(kernel_size, dilation=1): return int((kernel_size*dilation - dilation)/2) +def load_pretrained_weights(model, ckpt_fpath): + model = getattr(model, "module", model) + weights = torch.load(ckpt_fpath, map_location="cpu")["state_dict"] + weights = {re.sub("^module.", "", k): v for k, v in weights.items()} + + ckpt_emb = weights["encoder.word_emb.weight"] + new_emb = model.state_dict()["encoder.word_emb.weight"] + + ckpt_vocab_size = ckpt_emb.size(0) + new_vocab_size = new_emb.size(0) + if ckpt_vocab_size != new_vocab_size: + print("WARNING: Resuming from a checkpoint with a different size " + "of embedding table. For best results, extend the vocab " + "and ensure the common symbols' indices match.") + min_len = min(ckpt_vocab_size, new_vocab_size) + weights["encoder.word_emb.weight"] = ckpt_emb if ckpt_vocab_size > new_vocab_size else new_emb + weights["encoder.word_emb.weight"][:min_len] = ckpt_emb[:min_len] + + model.load_state_dict(weights) + + class AttrDict(dict): def __init__(self, *args, **kwargs): super(AttrDict, self).__init__(*args, **kwargs) diff --git a/PyTorch/SpeechSynthesis/FastPitch/fastpitch/data_function.py b/PyTorch/SpeechSynthesis/FastPitch/fastpitch/data_function.py index 0014a997a..8e64e97dd 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/fastpitch/data_function.py +++ b/PyTorch/SpeechSynthesis/FastPitch/fastpitch/data_function.py @@ -38,7 +38,7 @@ from scipy.stats import betabinom import common.layers as layers -from common.text.text_processing import TextProcessing +from common.text.text_processing import get_text_processing from common.utils import load_wav_to_torch, load_filepaths_and_text, to_gpu @@ -179,7 +179,7 @@ def __init__(self, 'Only 0.0 and 1.0 p_arpabet is currently supported. ' 'Variable probability breaks caching of betabinomial matrices.') - self.tp = TextProcessing(symbol_set, text_cleaners, p_arpabet=p_arpabet) + self.tp = get_text_processing(symbol_set, text_cleaners, p_arpabet) self.n_speakers = n_speakers self.pitch_tmp_dir = pitch_online_dir self.f0_method = pitch_online_method @@ -325,6 +325,14 @@ def get_pitch(self, index, mel_len=None): return pitch_mel +def ensure_disjoint(*tts_datasets): + paths = [set(list(zip(*d.audiopaths_and_text))[0]) for d in tts_datasets] + assert sum(len(p) for p in paths) == len(set().union(*paths)), ( + "Your datasets (train, val) are not disjoint. " + "Review filelists and restart training." + ) + + class TTSCollate: """Zero-pads model inputs and targets based on number of frames per step""" diff --git a/PyTorch/SpeechSynthesis/FastPitch/inference.py b/PyTorch/SpeechSynthesis/FastPitch/inference.py index 85f4816f9..8a884a831 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/inference.py +++ b/PyTorch/SpeechSynthesis/FastPitch/inference.py @@ -35,7 +35,7 @@ from common.tb_dllogger import (init_inference_metadata, stdout_metric_format, unique_log_fpath) from common.text import cmudict -from common.text.text_processing import TextProcessing +from common.text.text_processing import get_text_processing from common.utils import l2_promote from fastpitch.pitch_transform import pitch_transform_custom from hifigan.data_function import MAX_WAV_VALUE, mel_spectrogram @@ -161,7 +161,7 @@ def load_fields(fpath): def prepare_input_sequence(fields, device, symbol_set, text_cleaners, batch_size=128, dataset=None, load_mels=False, load_pitch=False, p_arpabet=0.0): - tp = TextProcessing(symbol_set, text_cleaners, p_arpabet=p_arpabet) + tp = get_text_processing(symbol_set, text_cleaners, p_arpabet) fields['text'] = [torch.LongTensor(tp.encode_text(text)) for text in fields['text']] diff --git a/PyTorch/SpeechSynthesis/FastPitch/phrases/phrase_bilingual.txt b/PyTorch/SpeechSynthesis/FastPitch/phrases/phrase_bilingual.txt new file mode 100644 index 000000000..ec1d65b27 --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/phrases/phrase_bilingual.txt @@ -0,0 +1,20 @@ +nokia有跟facebook簽約。 +讓net backup同時強化重覆刪除和資料搜尋功能。 +classic仍有一定的價值。 +資料代管商ball的虛擬化工具。 +針對vmware虛擬化環境的基本功能。 +這跟微軟bing有何關連? +由ben toyota所寫的the accidental billionaires。 +v d s技術提供一個如同伺服器般的獨立操作系統環境。 +專利設計通過美國f d a認證與臨床測試。 +你可直接把圖片丟進wave訊息中。 +由前英國陸軍軍官neil laughton領軍。 +這次android版也沿用了同樣的輸入法。 +facebook新註冊用戶。 +現在android跟iphone都支援這項功能。 +o r g的經理maxim weinstein。 +但本來就甚少舉辦活動的kingston金士頓。 +touchstone充電系統是還蠻酷的技術。 +雖然caspian市佔率不斷下滑。 +第一隻中文化的google android手機。 +因為google自家已經有android的同級競爭產品。 \ No newline at end of file diff --git a/PyTorch/SpeechSynthesis/FastPitch/prepare_dataset.py b/PyTorch/SpeechSynthesis/FastPitch/prepare_dataset.py index d93065b42..f4c0e4e66 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/prepare_dataset.py +++ b/PyTorch/SpeechSynthesis/FastPitch/prepare_dataset.py @@ -77,6 +77,11 @@ def parse_args(parser): # Performance parser.add_argument('-b', '--batch-size', default=1, type=int) parser.add_argument('--n-workers', type=int, default=16) + + # Language + parser.add_argument('--symbol_set', default='english_basic', + choices=['english_basic', 'english_mandarin_basic'], + help='Symbols in the dataset') return parser @@ -101,7 +106,7 @@ def main(): if args.save_alignment_priors: Path(args.dataset_path, 'alignment_priors').mkdir(parents=False, exist_ok=True) - + for filelist in args.wav_text_filelists: print(f'Processing {filelist}...') @@ -111,6 +116,7 @@ def main(): filelist, text_cleaners=['english_cleaners_v2'], n_mel_channels=args.n_mel_channels, + symbol_set=args.symbol_set, p_arpabet=0.0, n_speakers=args.n_speakers, load_mel_from_disk=False, diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_benchmark.sh b/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_benchmark.sh index 5803b9f96..f5d935031 100755 --- a/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_benchmark.sh +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_benchmark.sh @@ -9,6 +9,7 @@ set -a : ${WARMUP:=64} : ${REPEATS:=500} : ${AMP:=false} +: ${CUDNN_BENCHMARK:=true} for BATCH_SIZE in $BS_SEQUENCE ; do LOG_FILE="$OUTPUT_DIR"/perf-infer_amp-${AMP}_bs${BATCH_SIZE}.json diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_example.sh b/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_example.sh index 88ddd08b9..8d4b82f86 100755 --- a/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_example.sh +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/inference_example.sh @@ -12,6 +12,7 @@ export TORCH_CUDNN_V8_API_ENABLED=1 : ${REPEATS:=1} : ${CPU:=false} : ${PHONE:=true} +: ${CUDNN_BENCHMARK:=false} # Paths to pre-trained models downloadable from NVIDIA NGC (LJSpeech-1.1) FASTPITCH_LJ="pretrained_models/fastpitch/nvidia_fastpitch_210824.pt" @@ -54,9 +55,7 @@ mkdir -p "$OUTPUT_DIR" echo -e "\nAMP=$AMP, batch_size=$BATCH_SIZE\n" -ARGS="" ARGS+=" --cuda" -# ARGS+=" --cudnn-benchmark" # Enable for benchmarking or long operation ARGS+=" --dataset-path $DATASET_DIR" ARGS+=" -i $FILELIST" ARGS+=" -o $OUTPUT_DIR" @@ -67,12 +66,12 @@ ARGS+=" --warmup-steps $WARMUP" ARGS+=" --repeats $REPEATS" ARGS+=" --speaker $SPEAKER" [ "$CPU" = false ] && ARGS+=" --cuda" -[ "$CPU" = false ] && ARGS+=" --cudnn-benchmark" [ "$AMP" = true ] && ARGS+=" --amp" [ "$TORCHSCRIPT" = true ] && ARGS+=" --torchscript" [ -n "$HIFIGAN" ] && ARGS+=" --hifigan $HIFIGAN" [ -n "$WAVEGLOW" ] && ARGS+=" --waveglow $WAVEGLOW" [ -n "$FASTPITCH" ] && ARGS+=" --fastpitch $FASTPITCH" [ "$PHONE" = true ] && ARGS+=" --p-arpabet 1.0" +[[ "$CUDNN_BENCHMARK" = true && "$CPU" = false ]] && ARGS+=" --cudnn-benchmark" python inference.py $ARGS "$@" diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/README.md b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/README.md new file mode 100644 index 000000000..708c0b86d --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/README.md @@ -0,0 +1,5 @@ +Scripts in this directory are meant for training a Mandarin Chinese model +on a publicly available [SF Bilingual Speech in Chinese and English](https://catalog.ngc.nvidia.com/orgs/nvidia/resources/sf_bilingual_speech_zh_en) +dataset. + +A step-by-step guide is provided in the general [README.md](../../README.md#example-training-a-model-on-mandarin-chinese). diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/inference.sh b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/inference.sh new file mode 100644 index 000000000..e067910f3 --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/inference.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -a + +bash scripts/download_models.sh waveglow + +PYTHONIOENCODING=utf-8 + +: ${BATCH_SIZE:=20} +: ${FILELIST:="filelists/sf_test.tsv"} +: ${FASTPITCH:="output_sf/FastPitch_checkpoint_1000.pt"} +: ${OUTPUT_DIR:="output_sf/audio_sf_test_fastpitch1000ep_waveglow_denoise0.01"} + +# Disable HiFi-GAN and enable WaveGlow +HIFIGAN="" +WAVEGLOW="pretrained_models/waveglow/nvidia_waveglow256pyt_fp16.pt" + +bash scripts/inference_example.sh "$@" diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/prepare_dataset.sh b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/prepare_dataset.sh new file mode 100644 index 000000000..50d067366 --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/prepare_dataset.sh @@ -0,0 +1,57 @@ +set -e + +URL="https://catalog.ngc.nvidia.com/orgs/nvidia/resources/sf_bilingual_speech_zh_en" + +if [[ $1 == "" ]]; then + echo -e "\n**************************************************************************************" + echo -e "\nThe dataset needs to be downloaded manually from NGC by a signed in user:" + echo -e "\n\t$URL\n" + echo -e "Save as files.zip and run the script:" + echo -e "\n\tbash $0 path/to/files.zip\n" + echo -e "**************************************************************************************\n" + exit 0 +fi + +mkdir -p data + +echo "Extracting the data..." +# The dataset downloaded from NGC might be double-zipped as: +# SF_bilingual -> SF_bilingual.zip -> files.zip +if [ $(basename $1) == "files.zip" ]; then + unzip $1 -d data/ + unzip data/SF_bilingual.zip -d data/ +elif [ $(basename $1) == "SF_bilingual.zip" ]; then + unzip $1 -d data/ +else + echo "Unknown input file. Supply either files.zip or SF_bilingual.zip as the first argument:" + echo "\t$0 [files.zip|SF_bilingual.zip]" + exit 1 +fi +echo "Extracting the data... OK" + +# Make filelists +echo "Generating filelists..." +python scripts/mandarin_chinese/split_sf.py data/SF_bilingual/text_SF.txt filelists/ +echo "Generating filelists... OK" + +# Extract pitch (optionally extract mels) +set -e + +export PYTHONIOENCODING=utf-8 + +: ${DATA_DIR:=data/SF_bilingual} +: ${ARGS="--extract-mels"} + +echo "Extracting pitch..." +python prepare_dataset.py \ + --wav-text-filelists filelists/sf_audio_text.txt \ + --n-workers 16 \ + --batch-size 1 \ + --dataset-path $DATA_DIR \ + --extract-pitch \ + --f0-method pyin \ + --symbol_set english_mandarin_basic \ + $ARGS + +echo "Extracting pitch... OK" +echo "./data/SF_bilingual prepared successfully." diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/requirements.txt b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/requirements.txt new file mode 100644 index 000000000..2adeeb82c --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/requirements.txt @@ -0,0 +1 @@ +pypinyin==0.47.1 diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/split_sf.py b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/split_sf.py new file mode 100644 index 000000000..97636ea65 --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/split_sf.py @@ -0,0 +1,94 @@ +# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from pathlib import Path + + +# Define val and test; the remaining ones will be train IDs +val_ids = { + 'com_SF_ce227', 'com_SF_ce832', 'com_SF_ce912','com_SF_ce979', + 'com_SF_ce998', 'com_SF_ce1045', 'com_SF_ce1282','com_SF_ce1329', + 'com_SF_ce1350', 'com_SF_ce1376', 'com_SF_ce1519','com_SF_ce1664', + 'com_SF_ce1777', 'com_SF_ce1843', 'com_SF_ce2017','com_SF_ce2042', + 'com_SF_ce2100', 'com_SF_ce2251', 'com_SF_ce2443','com_SF_ce2566', +} + +test_ids = { + 'com_SF_ce161', 'com_SF_ce577', 'com_SF_ce781', 'com_SF_ce814', + 'com_SF_ce1042', 'com_SF_ce1089', 'com_SF_ce1123', 'com_SF_ce1425', + 'com_SF_ce1514', 'com_SF_ce1577', 'com_SF_ce1780', 'com_SF_ce1857', + 'com_SF_ce1940', 'com_SF_ce2051', 'com_SF_ce2181', 'com_SF_ce2258', + 'com_SF_ce2406', 'com_SF_ce2512', 'com_SF_ce2564', 'com_SF_ce2657' +} + + +def generate(fpath, ids_text, pitch=True, text=True): + + with open(fpath, 'w') as f: + for id_, txt in ids_text.items(): + row = f"wavs/{id_}.wav" + row += "|" + f"pitch/{id_}.pt" if pitch else "" + row += "|" + txt if text else "" + f.write(row + "\n") + + +def generate_inference_tsv(fpath, ids_text): + + with open(fpath, 'w') as f: + f.write("output\ttext\n") + for id_, txt in ids_text.items(): + f.write(f"{id_}.wav\t{txt}\n") + + +def main(): + parser = argparse.ArgumentParser( + description='SF bilingual dataset filelists generator') + parser.add_argument('transcripts', type=Path, default='./text_SF.txt', + help='Path to LJSpeech dataset metadata') + parser.add_argument('output_dir', default='data/filelists', type=Path, + help='Directory to generate filelists to') + args = parser.parse_args() + + with open(args.transcripts) as f: + # A dict of ID:transcript pairs + transcripts = dict(line.replace("\ufeff", "").replace("-", "-").strip().split(' ', 1) + for line in f) + transcripts = {id_.replace("com_DL", "com_SF"): text.lower() + for id_, text in transcripts.items()} + + val_ids_text = {id_: transcripts[id_] for id_ in val_ids} + test_ids_text = {id_: transcripts[id_] for id_ in test_ids} + train_ids_text = {id_: transcripts[id_] for id_ in transcripts + if id_ not in test_ids and id_ not in val_ids} + + prefix = Path(args.output_dir, "sf_audio_pitch_text_") + generate(str(prefix) + "val.txt", val_ids_text) + generate(str(prefix) + "test.txt", test_ids_text) + generate(str(prefix) + "train.txt", train_ids_text) + + prefix = Path(args.output_dir, "sf_audio_") + generate(str(prefix) + "val.txt", val_ids_text, False, False) + generate(str(prefix) + "test.txt", test_ids_text, False, False) + generate(str(prefix) + "train.txt", train_ids_text, False, False) + + # train + val + test for pre-processing + generate(Path(args.output_dir, "sf_audio_text.txt"), + {**val_ids_text, **test_ids_text, **train_ids_text}, False, True) + + generate_inference_tsv(Path(args.output_dir, "sf_test.tsv"), test_ids_text) + + +if __name__ == '__main__': + main() diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/train.sh b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/train.sh new file mode 100644 index 000000000..757f2d956 --- /dev/null +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/mandarin_chinese/train.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -a + +PYTHONIOENCODING=utf-8 + +# Mandarin & English bilingual +ARGS+=" --symbol-set english_mandarin_basic" + +# Initialize weights with a pre-trained English model +bash scripts/download_models.sh fastpitch +ARGS+=" --init-from-checkpoint pretrained_models/fastpitch/nvidia_fastpitch_210824.pt" + +AMP=false # FP32 training for better stability + +: ${DATASET_PATH:=data/SF_bilingual} +: ${TRAIN_FILELIST:=filelists/sf_audio_pitch_text_train.txt} +: ${VAL_FILELIST:=filelists/sf_audio_pitch_text_val.txt} +: ${OUTPUT_DIR:=./output_sf} + +bash scripts/train.sh $ARGS "$@" diff --git a/PyTorch/SpeechSynthesis/FastPitch/scripts/train.sh b/PyTorch/SpeechSynthesis/FastPitch/scripts/train.sh index 9ac75758a..cd22150b8 100755 --- a/PyTorch/SpeechSynthesis/FastPitch/scripts/train.sh +++ b/PyTorch/SpeechSynthesis/FastPitch/scripts/train.sh @@ -42,7 +42,7 @@ GBS=$(($NUM_GPUS * $BATCH_SIZE * $GRAD_ACCUMULATION)) echo -e "\nAMP=$AMP, ${NUM_GPUS}x${BATCH_SIZE}x${GRAD_ACCUMULATION}" \ "(global batch size ${GBS})\n" -ARGS="" +# ARGS="" ARGS+=" --cuda" ARGS+=" -o $OUTPUT_DIR" ARGS+=" --log-file $LOG_FILE" @@ -54,7 +54,7 @@ ARGS+=" --grad-accumulation $GRAD_ACCUMULATION" ARGS+=" --optimizer lamb" ARGS+=" --epochs $EPOCHS" ARGS+=" --epochs-per-checkpoint $EPOCHS_PER_CHECKPOINT" -ARGS+=" --resume" + ARGS+=" --warmup-steps $WARMUP_STEPS" ARGS+=" -lr $LEARNING_RATE" ARGS+=" --weight-decay 1e-6" @@ -70,16 +70,17 @@ ARGS+=" --kl-loss-warmup-epochs $KL_LOSS_WARMUP" ARGS+=" --text-cleaners $TEXT_CLEANERS" ARGS+=" --n-speakers $NSPEAKERS" -[ "$AMP" = "true" ] && ARGS+=" --amp" -[ "$PHONE" = "true" ] && ARGS+=" --p-arpabet 1.0" -[ "$ENERGY" = "true" ] && ARGS+=" --energy-conditioning" -[ "$SEED" != "" ] && ARGS+=" --seed $SEED" -[ "$LOAD_MEL_FROM_DISK" = true ] && ARGS+=" --load-mel-from-disk" -[ "$LOAD_PITCH_FROM_DISK" = true ] && ARGS+=" --load-pitch-from-disk" -[ "$PITCH_ONLINE_DIR" != "" ] && ARGS+=" --pitch-online-dir $PITCH_ONLINE_DIR" # e.g., /dev/shm/pitch -[ "$PITCH_ONLINE_METHOD" != "" ] && ARGS+=" --pitch-online-method $PITCH_ONLINE_METHOD" -[ "$APPEND_SPACES" = true ] && ARGS+=" --prepend-space-to-text" -[ "$APPEND_SPACES" = true ] && ARGS+=" --append-space-to-text" +[ "$AMP" = "true" ] && ARGS+=" --amp" +[ "$PHONE" = "true" ] && ARGS+=" --p-arpabet 1.0" +[ "$ENERGY" = "true" ] && ARGS+=" --energy-conditioning" +[ "$SEED" != "" ] && ARGS+=" --seed $SEED" +[ "$LOAD_MEL_FROM_DISK" = true ] && ARGS+=" --load-mel-from-disk" +[ "$LOAD_PITCH_FROM_DISK" = true ] && ARGS+=" --load-pitch-from-disk" +[ "$PITCH_ONLINE_DIR" != "" ] && ARGS+=" --pitch-online-dir $PITCH_ONLINE_DIR" # e.g., /dev/shm/pitch +[ "$PITCH_ONLINE_METHOD" != "" ] && ARGS+=" --pitch-online-method $PITCH_ONLINE_METHOD" +[ "$APPEND_SPACES" = true ] && ARGS+=" --prepend-space-to-text" +[ "$APPEND_SPACES" = true ] && ARGS+=" --append-space-to-text" +[[ "$ARGS" != *"--checkpoint-path"* ]] && ARGS+=" --resume" if [ "$SAMPLING_RATE" == "44100" ]; then ARGS+=" --sampling-rate 44100" diff --git a/PyTorch/SpeechSynthesis/FastPitch/train.py b/PyTorch/SpeechSynthesis/FastPitch/train.py index 20b7032f2..bd79b4bf1 100644 --- a/PyTorch/SpeechSynthesis/FastPitch/train.py +++ b/PyTorch/SpeechSynthesis/FastPitch/train.py @@ -47,9 +47,10 @@ from common.repeated_dataloader import (RepeatedDataLoader, RepeatedDistributedSampler) from common.text import cmudict -from common.utils import BenchmarkStats, Checkpointer, prepare_tmp +from common.utils import (BenchmarkStats, Checkpointer, + load_pretrained_weights, prepare_tmp) from fastpitch.attn_loss_function import AttentionBinarizationLoss -from fastpitch.data_function import batch_to_gpu, TTSCollate, TTSDataset +from fastpitch.data_function import batch_to_gpu, ensure_disjoint, TTSCollate, TTSDataset from fastpitch.loss_function import FastPitchLoss @@ -95,6 +96,8 @@ def parse_args(parser): help='Number of epochs for calculating final stats') train.add_argument('--validation-freq', type=int, default=1, help='Validate every N epochs to use less compute') + train.add_argument('--init-from-checkpoint', type=str, default=None, + help='Initialize model weights with a pre-trained ckpt') opt = parser.add_argument_group('optimization setup') opt.add_argument('--optimizer', type=str, default='lamb', @@ -326,6 +329,9 @@ def main(): model_config = models.get_model_config('FastPitch', args) model = models.get_model('FastPitch', model_config, device) + if args.init_from_checkpoint is not None: + load_pretrained_weights(model, args.init_from_checkpoint) + attention_kl_loss = AttentionBinarizationLoss() # Store pitch mean/std as params to translate from Hz during inference @@ -374,6 +380,7 @@ def main(): trainset = TTSDataset(audiopaths_and_text=args.training_files, **vars(args)) valset = TTSDataset(audiopaths_and_text=args.validation_files, **vars(args)) + ensure_disjoint(trainset, valset) if distributed_run: train_sampler = RepeatedDistributedSampler(args.trainloader_repeats, diff --git a/PyTorch/SpeechSynthesis/HiFiGAN/common/utils.py b/PyTorch/SpeechSynthesis/HiFiGAN/common/utils.py index c6ee86e48..be2afa728 100644 --- a/PyTorch/SpeechSynthesis/HiFiGAN/common/utils.py +++ b/PyTorch/SpeechSynthesis/HiFiGAN/common/utils.py @@ -51,8 +51,6 @@ import matplotlib -matplotlib.use("Agg") -import matplotlib.pylab as plt import numpy as np import torch import torch.distributed as dist @@ -173,6 +171,8 @@ def print_once(*msg): def plot_spectrogram(spectrogram): + matplotlib.use("Agg") + import matplotlib.pylab as plt fig, ax = plt.subplots(figsize=(10, 2)) im = ax.imshow(spectrogram, aspect="auto", origin="lower", interpolation='none') diff --git a/PyTorch/SpeechSynthesis/HiFiGAN/fastpitch/__init__.py b/PyTorch/SpeechSynthesis/HiFiGAN/fastpitch/__init__.py new file mode 100644 index 000000000..b40ee480b --- /dev/null +++ b/PyTorch/SpeechSynthesis/HiFiGAN/fastpitch/__init__.py @@ -0,0 +1 @@ +from .entrypoints import nvidia_fastpitch, nvidia_textprocessing_utils \ No newline at end of file diff --git a/PyTorch/SpeechSynthesis/HiFiGAN/fastpitch/entrypoints.py b/PyTorch/SpeechSynthesis/HiFiGAN/fastpitch/entrypoints.py new file mode 100644 index 000000000..e2d55742a --- /dev/null +++ b/PyTorch/SpeechSynthesis/HiFiGAN/fastpitch/entrypoints.py @@ -0,0 +1,203 @@ +# ***************************************************************************** +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the NVIDIA CORPORATION nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ***************************************************************************** + +import urllib.request +import torch +import os +import sys + +#from https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/SpeechSynthesis/Tacotron2/inference.py +def checkpoint_from_distributed(state_dict): + """ + Checks whether checkpoint was generated by DistributedDataParallel. DDP + wraps model in additional "module.", it needs to be unwrapped for single + GPU inference. + :param state_dict: model's state dict + """ + ret = False + for key, _ in state_dict.items(): + if key.find('module.') != -1: + ret = True + break + return ret + + +# from https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/SpeechSynthesis/Tacotron2/inference.py +def unwrap_distributed(state_dict): + """ + Unwraps model from DistributedDataParallel. + DDP wraps model in additional "module.", it needs to be removed for single + GPU inference. + :param state_dict: model's state dict + """ + new_state_dict = {} + for key, value in state_dict.items(): + new_key = key.replace('module.1.', '') + new_key = new_key.replace('module.', '') + new_state_dict[new_key] = value + return new_state_dict + +def _download_checkpoint(checkpoint, force_reload): + model_dir = os.path.join(torch.hub._get_torch_home(), 'checkpoints') + if not os.path.exists(model_dir): + os.makedirs(model_dir) + ckpt_file = os.path.join(model_dir, os.path.basename(checkpoint)) + if not os.path.exists(ckpt_file) or force_reload: + sys.stderr.write('Downloading checkpoint from {}\n'.format(checkpoint)) + urllib.request.urlretrieve(checkpoint, ckpt_file) + return ckpt_file + + +def nvidia_fastpitch(pretrained=True, **kwargs): + """TODO + """ + + from fastpitch import model as fastpitch + + force_reload = "force_reload" in kwargs and kwargs["force_reload"] + fp16 = "model_math" in kwargs and kwargs["model_math"] == "fp16" + + if pretrained: + checkpoint = 'https://api.ngc.nvidia.com/v2/models/nvidia/dle/fastpitch__pyt_ckpt/versions/21.12.1_amp/files/nvidia_fastpitch_210824+cfg.pt' + ckpt_file = _download_checkpoint(checkpoint, force_reload) + ckpt = torch.load(ckpt_file) + state_dict = ckpt['state_dict'] + if checkpoint_from_distributed(state_dict): + state_dict = unwrap_distributed(state_dict) + config = ckpt['config'] + train_setup = ckpt.get('train_setup', {}) + else: + config = {'n_mel_channels': 80, 'n_symbols': 148, 'padding_idx': 0, 'symbols_embedding_dim': 384, + 'in_fft_n_layers': 6, 'in_fft_n_heads': 1, 'in_fft_d_head': 64, 'in_fft_conv1d_kernel_size': 3, + 'in_fft_conv1d_filter_size': 1536, 'in_fft_output_size': 384, 'p_in_fft_dropout': 0.1, + 'p_in_fft_dropatt': 0.1, 'p_in_fft_dropemb': 0.0, 'out_fft_n_layers': 6, 'out_fft_n_heads': 1, + 'out_fft_d_head': 64, 'out_fft_conv1d_kernel_size': 3, 'out_fft_conv1d_filter_size': 1536, + 'out_fft_output_size': 384, 'p_out_fft_dropout': 0.1, 'p_out_fft_dropatt': 0.1, 'p_out_fft_dropemb': 0.0, + 'dur_predictor_kernel_size': 3, 'dur_predictor_filter_size': 256, 'p_dur_predictor_dropout': 0.1, + 'dur_predictor_n_layers': 2, 'pitch_predictor_kernel_size': 3, 'pitch_predictor_filter_size': 256, + 'p_pitch_predictor_dropout': 0.1, 'pitch_predictor_n_layers': 2, 'pitch_embedding_kernel_size': 3, + 'n_speakers': 1, 'speaker_emb_weight': 1.0, 'energy_predictor_kernel_size': 3, + 'energy_predictor_filter_size': 256, 'p_energy_predictor_dropout': 0.1, 'energy_predictor_n_layers': 2, + 'energy_conditioning': True, 'energy_embedding_kernel_size': 3} + for k,v in kwargs.items(): + if k in config.keys(): + config[k] = v + train_setup = {} + + model = fastpitch.FastPitch(**config) + + if pretrained: + model.load_state_dict(state_dict) + + if fp16: + model.half() + + model.forward = model.infer + + return model, train_setup + + +def nvidia_textprocessing_utils(cmudict_path, heteronyms_path, **kwargs): + + from common.text.text_processing import TextProcessing + import numpy as np + from torch.nn.utils.rnn import pad_sequence + from common.text import cmudict + + + class TextPreProcessing: + @staticmethod + def prepare_input_sequence(texts, batch_size=1, device='cpu'): + cmudict.initialize(cmudict_path, heteronyms_path) + tp = TextProcessing(symbol_set='english_basic', cleaner_names=['english_cleaners_v2'], p_arpabet=1.0) + fields={} + + fields['text'] = [torch.LongTensor(tp.encode_text(text)) + for text in texts] + order = np.argsort([-t.size(0) for t in fields['text']]) + + fields['text'] = [fields['text'][i] for i in order] + fields['text_lens'] = torch.LongTensor([t.size(0) for t in fields['text']]) + + for t in fields['text']: + print(tp.sequence_to_text(t.numpy())) + + # cut into batches & pad + batches = [] + for b in range(0, len(order), batch_size): + batch = {f: values[b:b+batch_size] for f, values in fields.items()} + for f in batch: + if f == 'text': + batch[f] = pad_sequence(batch[f], batch_first=True) + + if type(batch[f]) is torch.Tensor: + batch[f] = batch[f].to(device) + batches.append(batch) + + return batches + + return TextPreProcessing() + + + +# # from tacotron2.text import text_to_sequence + +# @staticmethod +# def pad_sequences(batch): +# # Right zero-pad all one-hot text sequences to max input length +# input_lengths, ids_sorted_decreasing = torch.sort( +# torch.LongTensor([len(x) for x in batch]), +# dim=0, descending=True) +# max_input_len = input_lengths[0] + +# text_padded = torch.LongTensor(len(batch), max_input_len) +# text_padded.zero_() +# for i in range(len(ids_sorted_decreasing)): +# text = batch[ids_sorted_decreasing[i]] +# text_padded[i, :text.size(0)] = text + +# return text_padded, input_lengths + +# @staticmethod +# def prepare_input_sequence(texts, cpu_run=False): + +# d = [] +# # for i,text in enumerate(texts): +# # d.append(torch.IntTensor( +# # Processing.text_to_sequence(text, ['english_cleaners'])[:])) + +# text_padded, input_lengths = Processing.pad_sequences(d) +# if not cpu_run: +# text_padded = text_padded.cuda().long() +# input_lengths = input_lengths.cuda().long() +# else: +# text_padded = text_padded.long() +# input_lengths = input_lengths.long() + +# return text_padded, input_lengths + +# return Processing() diff --git a/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/__init__.py b/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/__init__.py new file mode 100644 index 000000000..52275b775 --- /dev/null +++ b/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/__init__.py @@ -0,0 +1 @@ +from .entrypoints import nvidia_hifigan diff --git a/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/entrypoints.py b/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/entrypoints.py new file mode 100644 index 000000000..a9266f547 --- /dev/null +++ b/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/entrypoints.py @@ -0,0 +1,112 @@ +# ***************************************************************************** +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the NVIDIA CORPORATION nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# ***************************************************************************** + +import urllib.request +import torch +import os +import sys + +#from https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/SpeechSynthesis/Tacotron2/inference.py +def checkpoint_from_distributed(state_dict): + """ + Checks whether checkpoint was generated by DistributedDataParallel. DDP + wraps model in additional "module.", it needs to be unwrapped for single + GPU inference. + :param state_dict: model's state dict + """ + ret = False + for key, _ in state_dict.items(): + if key.find('module.') != -1: + ret = True + break + return ret + + +# from https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/SpeechSynthesis/Tacotron2/inference.py +def unwrap_distributed(state_dict): + """ + Unwraps model from DistributedDataParallel. + DDP wraps model in additional "module.", it needs to be removed for single + GPU inference. + :param state_dict: model's state dict + """ + new_state_dict = {} + for key, value in state_dict.items(): + new_key = key.replace('module.1.', '') + new_key = new_key.replace('module.', '') + new_state_dict[new_key] = value + return new_state_dict + +def _download_checkpoint(checkpoint, force_reload): + model_dir = os.path.join(torch.hub._get_torch_home(), 'checkpoints') + if not os.path.exists(model_dir): + os.makedirs(model_dir) + ckpt_file = os.path.join(model_dir, os.path.basename(checkpoint)) + if not os.path.exists(ckpt_file) or force_reload: + sys.stderr.write('Downloading checkpoint from {}\n'.format(checkpoint)) + urllib.request.urlretrieve(checkpoint, ckpt_file) + return ckpt_file + + +def nvidia_hifigan(pretrained=True, **kwargs): + """TODO + """ + from hifigan import models as vocoder + + force_reload = "force_reload" in kwargs and kwargs["force_reload"] + fp16 = "model_math" in kwargs and kwargs["model_math"] == "fp16" + + if pretrained: + checkpoint = 'https://api.ngc.nvidia.com/v2/models/nvidia/dle/hifigan__pyt_ckpt_mode-finetune_ds-ljs22khz/versions/21.08.0_amp/files/hifigan_gen_checkpoint_10000_ft.pt' + ckpt_file = _download_checkpoint(checkpoint, force_reload) + ckpt = torch.load(ckpt_file) + state_dict = ckpt['generator'] + if checkpoint_from_distributed(state_dict): + state_dict = unwrap_distributed(state_dict) + config = ckpt['config'] + train_setup = ckpt.get('train_setup', {}) + else: + config = {'upsample_rates': [8, 8, 2, 2], 'upsample_kernel_sizes': [16, 16, 4, 4], + 'upsample_initial_channel': 512, 'resblock': '1', 'resblock_kernel_sizes': [3, 7, 11], + 'resblock_dilation_sizes': [[1, 3, 5], [1, 3, 5], [1, 3, 5]]} + for k,v in kwargs.items(): + if k in config.keys(): + config[k] = v + train_setup = {} + + hifigan = vocoder.Generator(config) + denoiser = None + if pretrained: + hifigan.load_state_dict(state_dict) + hifigan.remove_weight_norm() + denoiser = vocoder.Denoiser(hifigan, win_length=1024) + + if fp16: + hifigan.half() + denoiser.half() + + return hifigan, train_setup, denoiser \ No newline at end of file diff --git a/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/logging.py b/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/logging.py index a20cc3bad..ab047e44c 100644 --- a/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/logging.py +++ b/PyTorch/SpeechSynthesis/HiFiGAN/hifigan/logging.py @@ -123,7 +123,7 @@ class Metrics(dict): def __init__(self, scopes=['train', 'train_avg'], dll_keys=['loss_gen', 'loss_discrim', 'loss_mel', 'frames/s', 'took', 'lrate_gen', 'lrate_discrim'], - benchmark_epochs=0): + benchmark_epochs=0, cuda=True): super().__init__() self.dll_keys = dll_keys @@ -133,6 +133,7 @@ def __init__(self, scopes=['train', 'train_avg'], self.benchmark_epochs = benchmark_epochs if benchmark_epochs > 0: self.metrics['train_benchmark'] = defaultdict(list) + self.cuda = cuda def __setitem__(self, key, val): if type(val) is dict: @@ -182,15 +183,21 @@ def start_iter(self, iter, start_timer=True): self.start_accumulating(iter, start_timer, 'train') def start_epoch(self, epoch, start_timer=True): + if self.cuda: + torch.cuda.synchronize() self.start_accumulating(epoch, start_timer, 'train_avg') def start_val(self, start_timer=True): + if self.cuda: + torch.cuda.synchronize() self.start_accumulating(None, start_timer, 'val') def finish_iter(self, stop_timer=True): self.finish_accumulating(stop_timer, 'train') def finish_epoch(self, stop_timer=True): + if self.cuda: + torch.cuda.synchronize() self.finish_accumulating(stop_timer, 'train_avg') metr = self.metrics['train_benchmark'] @@ -201,6 +208,8 @@ def finish_epoch(self, stop_timer=True): metr[k].pop(0) def finish_val(self, stop_timer=True): + if self.cuda: + torch.cuda.synchronize() self.finish_accumulating(stop_timer, 'val') def get_metrics(self, scope='train', target='dll'): diff --git a/PyTorch/SpeechSynthesis/HiFiGAN/train.py b/PyTorch/SpeechSynthesis/HiFiGAN/train.py index c40d34874..18b070925 100644 --- a/PyTorch/SpeechSynthesis/HiFiGAN/train.py +++ b/PyTorch/SpeechSynthesis/HiFiGAN/train.py @@ -237,8 +237,9 @@ def main(): init_distributed(args, args.world_size, args.local_rank) metrics = Metrics(scopes=['train', 'train_avg'], - benchmark_epochs=args.benchmark_epochs_num) - val_metrics = Metrics(scopes=['val']) + benchmark_epochs=args.benchmark_epochs_num, + cuda=args.cuda) + val_metrics = Metrics(scopes=['val'], cuda=args.cuda) init_logger(args.output, args.log_file, args.ema_decay) logger.parameters(vars(args), tb_subset='train') diff --git a/PyTorch/SpeechSynthesis/Tacotron2/inference.py b/PyTorch/SpeechSynthesis/Tacotron2/inference.py index 11aa4105d..36dd20f71 100644 --- a/PyTorch/SpeechSynthesis/Tacotron2/inference.py +++ b/PyTorch/SpeechSynthesis/Tacotron2/inference.py @@ -106,13 +106,15 @@ def unwrap_distributed(state_dict): return new_state_dict -def load_and_setup_model(model_name, parser, checkpoint, fp16_run, cpu_run, forward_is_infer=False): +def load_and_setup_model(model_name, parser, checkpoint, fp16_run, cpu_run, + forward_is_infer=False, jittable=False): model_parser = models.model_parser(model_name, parser, add_help=False) model_args, _ = model_parser.parse_known_args() model_config = models.get_model_config(model_name, model_args) model = models.get_model(model_name, model_config, cpu_run=cpu_run, - forward_is_infer=forward_is_infer) + forward_is_infer=forward_is_infer, + jittable=jittable) if checkpoint is not None: if cpu_run: @@ -207,11 +209,14 @@ def main(): tacotron2 = load_and_setup_model('Tacotron2', parser, args.tacotron2, args.fp16, args.cpu, forward_is_infer=True) waveglow = load_and_setup_model('WaveGlow', parser, args.waveglow, - args.fp16, args.cpu, forward_is_infer=True) + args.fp16, args.cpu, forward_is_infer=True, + jittable=True) denoiser = Denoiser(waveglow) if not args.cpu: denoiser.cuda() + waveglow.make_ts_scriptable() + jitted_waveglow = torch.jit.script(waveglow) jitted_tacotron2 = torch.jit.script(tacotron2) texts = [] @@ -231,7 +236,7 @@ def main(): for i in range(3): with torch.no_grad(): mel, mel_lengths, _ = jitted_tacotron2(sequence, input_lengths) - _ = waveglow(mel) + _ = jitted_waveglow(mel) measurements = {} @@ -241,7 +246,7 @@ def main(): mel, mel_lengths, alignments = jitted_tacotron2(sequences_padded, input_lengths) with torch.no_grad(), MeasureTime(measurements, "waveglow_time", args.cpu): - audios = waveglow(mel, sigma=args.sigma_infer) + audios = jitted_waveglow(mel, sigma=args.sigma_infer) audios = audios.float() with torch.no_grad(), MeasureTime(measurements, "denoiser_time", args.cpu): audios = denoiser(audios, strength=args.denoising_strength).squeeze(1) diff --git a/PyTorch/SpeechSynthesis/Tacotron2/models.py b/PyTorch/SpeechSynthesis/Tacotron2/models.py index 0d79a3d75..c4b496fc9 100644 --- a/PyTorch/SpeechSynthesis/Tacotron2/models.py +++ b/PyTorch/SpeechSynthesis/Tacotron2/models.py @@ -63,7 +63,8 @@ def init_bn(module): def get_model(model_name, model_config, cpu_run, - uniform_initialize_bn_weight=False, forward_is_infer=False): + uniform_initialize_bn_weight=False, forward_is_infer=False, + jittable=False): """ Code chooses a model based on name""" model = None if model_name == 'Tacotron2': @@ -75,13 +76,11 @@ def forward(self, inputs, input_lengths): else: model = Tacotron2(**model_config) elif model_name == 'WaveGlow': + + model = WaveGlow(**model_config) if forward_is_infer: - class WaveGlow__forward_is_infer(WaveGlow): - def forward(self, spect, sigma=1.0): - return self.infer(spect, sigma) - model = WaveGlow__forward_is_infer(**model_config) - else: - model = WaveGlow(**model_config) + model.forward = model.infer + else: raise NotImplementedError(model_name) diff --git a/PyTorch/SpeechSynthesis/Tacotron2/waveglow/model.py b/PyTorch/SpeechSynthesis/Tacotron2/waveglow/model.py index 5635276bd..e336d259e 100644 --- a/PyTorch/SpeechSynthesis/Tacotron2/waveglow/model.py +++ b/PyTorch/SpeechSynthesis/Tacotron2/waveglow/model.py @@ -26,13 +26,14 @@ # ***************************************************************************** import torch torch._C._jit_set_autocast_mode(False) -from torch.autograd import Variable +import torch.nn as nn import torch.nn.functional as F +from torch.autograd import Variable @torch.jit.script -def fused_add_tanh_sigmoid_multiply(input_a, input_b, n_channels): - n_channels_int = n_channels[0] +def fused_add_tanh_sigmoid_multiply(input_a, input_b, n_channels : int): + n_channels_int = n_channels in_act = input_a + input_b t_act = torch.tanh(in_act[:, :n_channels_int, :]) s_act = torch.sigmoid(in_act[:, n_channels_int:, :]) @@ -73,22 +74,14 @@ def forward(self, z): z = self.conv(z) return z, log_det_W - def infer(self, z): - # shape - batch_size, group_size, n_of_groups = z.size() - - W = self.conv.weight.squeeze() + self._invert() + return F.conv1d(z, self.W_inverse, bias=None, stride=1, padding=0) + def _invert(self): if not hasattr(self, 'W_inverse'): - # Reverse computation - W_inverse = W.float().inverse() - W_inverse = Variable(W_inverse[..., None]) - if z.type() == 'torch.cuda.HalfTensor' or z.type() == 'torch.HalfTensor': - W_inverse = W_inverse.half() - self.W_inverse = W_inverse - z = F.conv1d(z, self.W_inverse, bias=None, stride=1, padding=0) - return z + W = self.conv.weight.squeeze() + self.W_inverse = W.float().inverse().unsqueeze(-1).to(W.dtype) class WN(torch.nn.Module): @@ -142,27 +135,25 @@ def __init__(self, n_in_channels, n_mel_channels, n_layers, n_channels, res_skip_layer, name='weight') self.res_skip_layers.append(res_skip_layer) - def forward(self, forward_input): - audio, spect = forward_input + def forward(self, audio, spect): audio = self.start(audio) - for i in range(self.n_layers): + output = 0 + for i, (in_layer, cond_layer, res_skip_layer) in enumerate( + zip(self.in_layers, self.cond_layers, self.res_skip_layers)): acts = fused_add_tanh_sigmoid_multiply( - self.in_layers[i](audio), - self.cond_layers[i](spect), - torch.IntTensor([self.n_channels])) + in_layer(audio), + cond_layer(spect), + self.n_channels) - res_skip_acts = self.res_skip_layers[i](acts) + res_skip_acts = res_skip_layer(acts) if i < self.n_layers - 1: audio = res_skip_acts[:, :self.n_channels, :] + audio skip_acts = res_skip_acts[:, self.n_channels:, :] else: skip_acts = res_skip_acts - if i == 0: - output = skip_acts - else: - output = skip_acts + output + output += skip_acts return self.end(output) @@ -229,7 +220,7 @@ def forward(self, forward_input): audio_0 = audio[:, :n_half, :] audio_1 = audio[:, n_half:, :] - output = self.WN[k]((audio_0, spect)) + output = self.WN[k](audio_0, spect) log_s = output[:, n_half:, :] b = output[:, :n_half, :] audio_1 = torch.exp(log_s) * audio_1 + b @@ -262,7 +253,7 @@ def infer(self, spect, sigma=1.0): audio_0 = audio[:, :n_half, :] audio_1 = audio[:, n_half:, :] - output = self.WN[k]((audio_0, spect)) + output = self.WN[k](audio_0, spect) s = output[:, n_half:, :] b = output[:, :n_half, :] audio_1 = (audio_1 - b) / torch.exp(s) @@ -308,7 +299,7 @@ def infer_onnx(self, spect, z, sigma=0.9): audio_0 = audio[:, :n_half, :] audio_1 = audio[:, n_half:(n_half+n_half), :] - output = self.WN[k]((audio_0, spect)) + output = self.WN[k](audio_0, spect) s = output[:, n_half:(n_half+n_half), :] b = output[:, :n_half, :] audio_1 = (audio_1 - b) / torch.exp(s) @@ -323,6 +314,53 @@ def infer_onnx(self, spect, z, sigma=0.9): return audio + def _infer_ts(self, spect, sigma : float=1.0): + + spect = self.upsample(spect) + # trim conv artifacts. maybe pad spec to kernel multiple + time_cutoff = self.upsample.kernel_size[0] - self.upsample.stride[0] + spect = spect[:, :, :-time_cutoff] + + spect = spect.unfold(2, self.n_group, self.n_group).permute(0, 2, 1, 3) + spect = spect.contiguous().view(spect.size(0), spect.size(1), -1) + spect = spect.permute(0, 2, 1) + + audio = torch.randn(spect.size(0), self.n_remaining_channels, + spect.size(2), device=spect.device, + dtype=spect.dtype) + audio *= sigma + + for kk, (wn, convinv) in enumerate(zip(self.WN_rev, self.convinv_rev)): + k = self.n_flows - kk - 1 + n_half = int(audio.size(1) / 2) + audio_0 = audio[:, :n_half, :] + audio_1 = audio[:, n_half:, :] + + output = wn(audio_0, spect) + s = output[:, n_half:, :] + b = output[:, :n_half, :] + audio_1 = (audio_1 - b) / torch.exp(s) + audio = torch.cat([audio_0, audio_1], 1) + + audio = convinv.infer(audio) + + if k % self.n_early_every == 0 and k > 0: + z = torch.randn(spect.size(0), self.n_early_size, + spect.size(2), device=spect.device, + dtype=spect.dtype) + audio = torch.cat((sigma * z, audio), 1) + + return audio.permute(0, 2, 1).contiguous().view(audio.size(0), -1).data + + def make_ts_scriptable(self, forward_is_infer=True): + self.WN_rev = torch.nn.ModuleList(reversed(self.WN)) + self.convinv_rev = torch.nn.ModuleList(reversed(self.convinv)) + for conv in self.convinv_rev: + conv._invert() + + self.infer = self._infer_ts + if forward_is_infer: + self.forward = self._infer_ts @staticmethod def remove_weightnorm(model): diff --git a/PyTorch/Translation/GNMT/seq2seq/inference/translator.py b/PyTorch/Translation/GNMT/seq2seq/inference/translator.py index 45e913d74..e13956767 100644 --- a/PyTorch/Translation/GNMT/seq2seq/inference/translator.py +++ b/PyTorch/Translation/GNMT/seq2seq/inference/translator.py @@ -182,6 +182,8 @@ def evaluate(self, loader, epoch=0, iteration=0, warmup=0, summary=False): output = [] for i, (src, indices) in enumerate(loader): + if device.type == 'cuda': + torch.cuda.synchronize() translate_timer = time.time() src, src_length = src stats['total_enc_len'] = int(src_length.sum()) @@ -207,12 +209,14 @@ def evaluate(self, loader, epoch=0, iteration=0, warmup=0, summary=False): detok = self.tokenizer.detokenize(pred) output.append(detok) + if device.type == 'cuda': + torch.cuda.synchronize() elapsed = time.time() - translate_timer batch_time.update(elapsed, batch_size) total_tokens = stats['total_dec_len'] + stats['total_enc_len'] ttps = total_tokens / elapsed - tot_tok_per_sec.update(ttps, batch_size) + tot_tok_per_sec.update(ttps, elapsed) iterations.update(stats['iters']) enc_seq_len.update(stats['total_enc_len'] / batch_size, batch_size) diff --git a/PyTorch/Translation/GNMT/seq2seq/train/trainer.py b/PyTorch/Translation/GNMT/seq2seq/train/trainer.py index 304e1a136..71f2deed7 100644 --- a/PyTorch/Translation/GNMT/seq2seq/train/trainer.py +++ b/PyTorch/Translation/GNMT/seq2seq/train/trainer.py @@ -222,6 +222,8 @@ def feed_data(self, data_loader, training=True): batch_size = data_loader.batch_size + if self.device.type == 'cuda': + torch.cuda.synchronize() end = time.time() for i, (src, tgt) in enumerate(data_loader): self.save_counter += 1 @@ -241,12 +243,14 @@ def feed_data(self, data_loader, training=True): losses_per_sentence.update(loss_per_sentence, batch_size) # measure elapsed time + if self.device.type == 'cuda': + torch.cuda.synchronize() elapsed = time.time() - end batch_time.update(elapsed) - src_tok_time.update(num_toks['src'] / elapsed) - tgt_tok_time.update(num_toks['tgt'] / elapsed) + src_tok_time.update(num_toks['src'] / elapsed, elapsed) + tgt_tok_time.update(num_toks['tgt'] / elapsed, elapsed) tot_num_toks = num_toks['tgt'] + num_toks['src'] - tot_tok_time.update(tot_num_toks / elapsed) + tot_tok_time.update(tot_num_toks / elapsed, elapsed) self.loss = losses_per_token.avg if training and i in eval_iters: @@ -298,6 +302,8 @@ def feed_data(self, data_loader, training=True): if rank == 0: self.save(identifier=identifier) + if self.device.type == 'cuda': + torch.cuda.synchronize() end = time.time() tot_tok_time.reduce('sum') diff --git a/PyTorch/Translation/GNMT/seq2seq/utils.py b/PyTorch/Translation/GNMT/seq2seq/utils.py index 7380ead0a..2164dd39b 100644 --- a/PyTorch/Translation/GNMT/seq2seq/utils.py +++ b/PyTorch/Translation/GNMT/seq2seq/utils.py @@ -132,10 +132,13 @@ def setup_seeds(master_seed, epochs, device): def barrier(): """ - Call torch.distributed.barrier() if distritubed is in use + Call torch.distributed.barrier() if distritubed is in use, else calls + torch.cuda.synchronize() if CUDA is initialized. """ if torch.distributed.is_available() and torch.distributed.is_initialized(): torch.distributed.barrier() + elif torch.cuda.is_available() and torch.cuda.is_initialized(): + torch.cuda.synchronize() def get_rank(): diff --git a/PyTorch/Translation/GNMT/train.py b/PyTorch/Translation/GNMT/train.py index b49dbbd1e..e78510e21 100644 --- a/PyTorch/Translation/GNMT/train.py +++ b/PyTorch/Translation/GNMT/train.py @@ -634,7 +634,7 @@ def main(): logging.info(f'Total training time {training_time:.0f} s') table = TrainingTable() - avg_training_perf = sum(training_perf) / len(training_perf) + avg_training_perf = len(training_perf) / sum(1 / v for v in training_perf) table.add(utils.get_world_size(), args.train_batch_size, test_bleu, avg_training_perf, training_time) if utils.get_rank() == 0: diff --git a/PyTorch/Translation/GNMT/translate.py b/PyTorch/Translation/GNMT/translate.py index 1f4586273..b0639104d 100644 --- a/PyTorch/Translation/GNMT/translate.py +++ b/PyTorch/Translation/GNMT/translate.py @@ -352,12 +352,10 @@ def main(): latency_table.write('Inference latency', 'fp16', relative=relative, reverse_speedup=True) - avg_throughput = np.array(stats['throughputs']).mean() - avg_latency = np.array(stats['runtimes']).mean() summary = { - 'eval_throughput': avg_throughput, + 'eval_throughput': stats['tokens_per_sec'], 'eval_bleu': stats['bleu'], - 'eval_avg_latency': avg_latency, + 'eval_avg_latency': np.array(stats['runtimes']).mean(), } for p in args.percentiles: summary[f'eval_{p}%_latency'] = np.percentile(stats['runtimes'], p) diff --git a/PyTorch/Translation/Transformer/fairseq/log_helper.py b/PyTorch/Translation/Transformer/fairseq/log_helper.py index 8b66afd9c..b991980a8 100644 --- a/PyTorch/Translation/Transformer/fairseq/log_helper.py +++ b/PyTorch/Translation/Transformer/fairseq/log_helper.py @@ -8,6 +8,7 @@ import dllogger from dllogger import Backend, JSONStreamBackend from tensorboardX import SummaryWriter +import torch class AverageMeter(): @@ -43,6 +44,7 @@ def __init__(self): def reset(self): self.updated = False + torch.cuda.synchronize() self.start = time.time() self.n = 0 @@ -56,6 +58,7 @@ def value(self): @property def elapsed_time(self): + torch.cuda.synchronize() return time.time() - self.start @@ -70,6 +73,7 @@ def __init__(self, verbosity, agg_dict): self.metrics.flushed = True self.step = 0 self.epoch = 0 + torch.cuda.synchronize() self.start_time = time.time() @property @@ -115,6 +119,7 @@ def flush(self): result_string += _name + ' {:.3f} |'.format(agg.value) agg.reset() + torch.cuda.synchronize() result_string += 'walltime {:.3f} |'.format(time.time() - self.start_time) self.metrics.flushed = True print(result_string) diff --git a/PyTorch/Translation/Transformer/fairseq/meters.py b/PyTorch/Translation/Transformer/fairseq/meters.py index 8b3753ecb..8360a79d7 100644 --- a/PyTorch/Translation/Transformer/fairseq/meters.py +++ b/PyTorch/Translation/Transformer/fairseq/meters.py @@ -6,6 +6,7 @@ # can be found in the PATENTS file in the same directory. import time +import torch class AverageMeter(object): @@ -33,12 +34,14 @@ def __init__(self, init=0): def reset(self, init=0): self.init = init + torch.cuda.synchronize() self.start = time.time() self.n = 0 self.last_update = time.time() def update(self, val=1): self.n += val + torch.cuda.synchronize() self.last_update = time.time() @property @@ -47,6 +50,7 @@ def avg(self): @property def elapsed_time(self): + torch.cuda.synchronize() return self.init + (time.time() - self.start) @property @@ -61,9 +65,11 @@ def __init__(self): self.intervals = [] def start(self): + torch.cuda.synchronize() self.start_time = time.time() def stop(self, n=1): + torch.cuda.synchronize() if self.start_time is not None: delta = time.time() - self.start_time self.intervals.append(delta) diff --git a/PyTorch/Translation/Transformer/inference.py b/PyTorch/Translation/Transformer/inference.py index 8b3023d08..5a6815d33 100644 --- a/PyTorch/Translation/Transformer/inference.py +++ b/PyTorch/Translation/Transformer/inference.py @@ -151,6 +151,7 @@ def main(args): use_cuda = torch.cuda.is_available() and not args.cpu + torch.cuda.synchronize() processing_start = time.time() # Load ensemble @@ -185,6 +186,7 @@ def main(args): translator.cuda() # Load BPE codes file + bpe = None if args.bpe_codes: codes = open(args.bpe_codes, 'r') bpe = BPE(codes) @@ -229,7 +231,9 @@ def process_batch(batch): tokens = tokens.cuda() lengths = lengths.cuda() + torch.cuda.synchronize() translation_start = time.time() + gen_timer.start() translations = translator.generate( tokens, @@ -237,6 +241,8 @@ def process_batch(batch): maxlen=int(args.max_len_a * tokens.size(1) + args.max_len_b), ) gen_timer.stop(sum(len(h[0]['tokens']) for h in translations)) + + torch.cuda.synchronize() dllogger.log(step='infer', data={'latency': time.time() - translation_start}) return [make_result(batch.srcs[i], t) for i, t in enumerate(translations)] @@ -262,6 +268,7 @@ def process_batch(batch): if args.file: data_descriptor.close() + torch.cuda.synchronize() log_dict = { 'throughput': 1./gen_timer.avg, 'latency_avg': sum(gen_timer.intervals)/len(gen_timer.intervals), diff --git a/PyTorch/Translation/Transformer/train.py b/PyTorch/Translation/Transformer/train.py index f54decd96..1d2897719 100644 --- a/PyTorch/Translation/Transformer/train.py +++ b/PyTorch/Translation/Transformer/train.py @@ -164,6 +164,7 @@ def train(args, trainer, epoch_itr): max_update = args.max_update or math.inf num_batches = len(epoch_itr) + torch.cuda.synchronize() begin = time.time() # reset meters @@ -189,6 +190,7 @@ def train(args, trainer, epoch_itr): if trainer.get_num_updates() >= max_update: break + torch.cuda.synchronize() print('Epoch time:', time.time() - begin) # Print epoch stats and reset training meters @@ -235,6 +237,7 @@ def validate(args, trainer, datasets, subsets): def score(args, trainer, dataset, src_dict, tgt_dict, ref_file): + torch.cuda.synchronize() begin = time.time() src_dict = deepcopy(src_dict) # This is necessary, generation of translations @@ -324,6 +327,7 @@ def score(args, trainer, dataset, src_dict, tgt_dict, ref_file): float(args.distributed_world_size)/gen_timer.avg )) + torch.cuda.synchronize() print('| Eval completed in: {:.2f}s | {}CASED BLEU {:.2f}'.format( time.time()-begin, '' if args.test_cased_bleu else 'UN', diff --git a/README.md b/README.md index 9bc053e69..fb2b6b841 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repository provides State-of-the-Art Deep Learning examples that are easy to train and deploy, achieving the best reproducible accuracy and performance with NVIDIA CUDA-X software stack running on NVIDIA Volta, Turing and Ampere GPUs. ## NVIDIA GPU Cloud (NGC) Container Registry -These examples, along with our NVIDIA deep learning software stack, are provided in a monthly updated Docker container on the NGC container registry (https://ngc.nvidia.com). These containers include: +These examples, along with our NVIDIA deep learning software stack, are provided in a monthly updated Docker container on the NGC container registry (https://ngc.nvidia.com). These containers include: - The latest NVIDIA examples from this repository - The latest NVIDIA contributions shared upstream to the respective framework @@ -13,112 +13,105 @@ These examples, along with our NVIDIA deep learning software stack, are provided ## Computer Vision -| Models | Framework | A100 | AMP | Multi-GPU | Multi-Node | TRT | ONNX | Triton | DLC | NB | -|-------------------------------------------------------------------------------------------------------------------------------------|--------------|------| ------------- | ------------- | ------------- |-----|------------- |------------- |------------- |------------- | -| [EfficientNet-B0](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [EfficientNet-B4](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [EfficientNet-WideSE-B0](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [EfficientNet-WideSE-B4](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [EfficientNet v1-B0](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Classification/ConvNets/efficientnet_v1) | TensorFlow2 | Yes | Yes | Yes | Yes | - |- | - | Yes | - | -| [EfficientNet v1-B4](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Classification/ConvNets/efficientnet_v1) | TensorFlow2 | Yes | Yes | Yes | Yes | - |- | - | Yes | - | -| [EfficientNet v2-S](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Classification/ConvNets/efficientnet_v2) | TensorFlow2 | Yes | Yes | Yes | Yes | - |- | - | Yes | - | -| [GPUNet](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/GPUNet) | PyTorch | Yes | Yes | Yes | - | Yes | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/GPUNet/triton/) | Yes | - | -| [Mask R-CNN](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Segmentation/MaskRCNN) | PyTorch | Yes | Yes | Yes | - | - | - | - | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/Segmentation/MaskRCNN/pytorch/notebooks/pytorch_MaskRCNN_pyt_train_and_inference.ipynb) | -| [Mask R-CNN](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Segmentation/MaskRCNN) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [Mask R-CNN](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Segmentation/MaskRCNN) | TensorFlow2 | Yes | Yes | Yes | - | - |- | - | Yes | - | -| [nnUNet](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Segmentation/nnUNet) | PyTorch | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/MxNet/Classification/RN50v1.5) | MXNet | - | Yes | Yes | - | - | - | - | - | - | -| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PaddlePaddle/Classification/RN50v1.5) | PaddlePaddle | Yes | Yes | Yes | - | Yes | - | - | - | - | -| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/resnet50v1.5) | PyTorch | Yes | Yes | Yes | - | Yes | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/triton/resnet50) | Yes | - | -| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Classification/ConvNets/resnet50v1.5) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/resnext101-32x4d) | PyTorch | Yes | Yes | Yes | - | Yes | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/triton/resnext101-32x4d) | Yes | - | -| [ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Classification/ConvNets/resnext101-32x4d) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [SE-ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/se-resnext101-32x4d) | PyTorch | Yes | Yes | Yes | - | Yes | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/triton/se-resnext101-32x4d) | Yes | - | -| [SE-ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Classification/ConvNets/se-resnext101-32x4d) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [SSD](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Detection/SSD) | PyTorch | Yes | Yes | Yes | - | - | - | - | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/Detection/SSD/examples/inference.ipynb) | -| [SSD](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Detection/SSD) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/blob/master/TensorFlow/Detection/SSD/models/research/object_detection/object_detection_tutorial.ipynb) | -| [U-Net Ind](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Segmentation/UNet_Industrial) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Segmentation/UNet_Industrial/notebooks) | -| [U-Net Med](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Segmentation/UNet_Medical) | TensorFlow | Yes | Yes | Yes | - | - |- | - | Yes | - | -| [U-Net 3D](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Segmentation/UNet_3D_Medical) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [U-Net Med](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Segmentation/UNet_Medical) | TensorFlow2 | Yes | Yes | Yes | - | - |- | - | Yes | - | -| [V-Net Med](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Segmentation/VNet) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | +| Models | Framework | AMP | Multi-GPU | Multi-Node | TensorRT | ONNX | Triton | DLC | NB | +|----------------------------------------------------------------------------------------------------------------------------------------|--------------|----------------|-----------|------------|----------|------|------------------------------------------------------------------------------------------------------------------------------|------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [EfficientNet-B0](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [EfficientNet-B4](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [EfficientNet-WideSE-B0](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [EfficientNet-WideSE-B4](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/efficientnet) | PyTorch | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [EfficientNet v1-B0](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Classification/ConvNets/efficientnet_v1) | TensorFlow2 | Yes | Yes | Yes | [Example](https://github.com/NVIDIA/TensorRT/tree/main/samples/python/efficientnet) | - | Supported | Yes | - | +| [EfficientNet v1-B4](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Classification/ConvNets/efficientnet_v1) | TensorFlow2 | Yes | Yes | Yes | [Example](https://github.com/NVIDIA/TensorRT/tree/main/samples/python/efficientnet) | - | Supported | Yes | - | +| [EfficientNet v2-S](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Classification/ConvNets/efficientnet_v2) | TensorFlow2 | Yes | Yes | Yes | [Example](https://github.com/NVIDIA/TensorRT/tree/main/samples/python/efficientnet) | - | Supported | Yes | - | +| [GPUNet](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/GPUNet) | PyTorch | Yes | Yes | - | Example | Yes | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/GPUNet/triton/) | Yes | - | +| [Mask R-CNN](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Segmentation/MaskRCNN) | PyTorch | Yes | Yes | - | [Example](https://github.com/NVIDIA/TensorRT/tree/main/samples/python/detectron2) | - | Supported | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/Segmentation/MaskRCNN/pytorch/notebooks/pytorch_MaskRCNN_pyt_train_and_inference.ipynb) | +| [Mask R-CNN](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Segmentation/MaskRCNN) | TensorFlow2 | Yes | Yes | - | [Example](https://github.com/NVIDIA/TensorRT/tree/main/samples/python/detectron2) | - | Supported | Yes | - | +| [nnUNet](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Segmentation/nnUNet) | PyTorch | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/MxNet/Classification/RN50v1.5) | MXNet | Yes | Yes | - | Supported | - | Supported | - | - | +| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PaddlePaddle/Classification/RN50v1.5) | PaddlePaddle | Yes | Yes | - | Example | - | Supported | - | - | +| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/resnet50v1.5) | PyTorch | Yes | Yes | - | Example | - | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/triton/resnet50) | Yes | - | +| [ResNet-50](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Classification/ConvNets/resnet50v1.5) | TensorFlow | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/resnext101-32x4d) | PyTorch | Yes | Yes | - | Example | - | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/triton/resnext101-32x4d) | Yes | - | +| [ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Classification/ConvNets/resnext101-32x4d) | TensorFlow | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [SE-ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/se-resnext101-32x4d) | PyTorch | Yes | Yes | - | Example | - | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Classification/ConvNets/triton/se-resnext101-32x4d) | Yes | - | +| [SE-ResNeXt-101](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Classification/ConvNets/se-resnext101-32x4d) | TensorFlow | Yes | Yes | - | Supported | - | Supported | Yes | - | +| [SSD](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Detection/SSD) | PyTorch | Yes | Yes | - | Supported | - | Supported | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/Detection/SSD/examples/inference.ipynb) | +| [SSD](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Detection/SSD) | TensorFlow | Yes | Yes | - | Supported | - | Supported | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/blob/master/TensorFlow/Detection/SSD/models/research/object_detection/object_detection_tutorial.ipynb) | +| [U-Net Med](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Segmentation/UNet_Medical) | TensorFlow2 | Yes | Yes | - | Example | - | Supported | Yes | - | ## Natural Language Processing -| Models | Framework | A100 | AMP | Multi-GPU | Multi-Node | TRT | ONNX | Triton | DLC | NB | -| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |------------- |------------- |------------- |------------- |------------- | -| [BERT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/LanguageModeling/BERT) |PyTorch | Yes | Yes | Yes | Yes | - | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/LanguageModeling/BERT/triton) | Yes | - | -| [TransformerXL](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/LanguageModeling/Transformer-XL) |PyTorch | Yes | Yes | Yes | Yes | - | - | - | Yes | - | -| [GNMT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Translation/GNMT) |PyTorch | Yes | Yes | Yes | - | - | - | - | - | - | -| [Transformer](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Translation/Transformer) |PyTorch | Yes | Yes | Yes | - | - | - | - | - | - | -| [ELECTRA](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/LanguageModeling/ELECTRA) | TensorFlow2 | Yes | Yes | Yes | Yes | - | - | - | Yes | - | -| [BERT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT) |TensorFlow | Yes | Yes | Yes | Yes | Yes | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/triton) | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/notebooks) | -| [BERT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/LanguageModeling/BERT) |TensorFlow2 | Yes | Yes | Yes | Yes | - | - | - | Yes | - | -| [BioBert](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/biobert) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/blob/master/TensorFlow/LanguageModeling/BERT/notebooks/biobert_ner_tf_inference.ipynb) | -| [TransformerXL](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/Transformer-XL) |TensorFlow | Yes | Yes | Yes | - | - | - | - | - | - | -| [GNMT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Translation/GNMT) | TensorFlow | Yes | Yes | Yes | - | - | - | - | - | - | -| [Faster Transformer](https://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer) | Tensorflow | - | - | - | - | Yes | - | - | - | - | +| Models | Framework | AMP | Multi-GPU | Multi-Node | TensorRT | ONNX | Triton | DLC | NB | +|------------------------------------------------------------------------------------------------------------------------|-------------|------|-----------|------------|----------|------|-----------------------------------------------------------------------------------------------------------|------|---------------------------------------------------------------------------------------------------------------------------------------------| +| [BERT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/LanguageModeling/BERT) | PyTorch | Yes | Yes | Yes | [Example](https://github.com/NVIDIA/TensorRT/tree/main/demo/BERT) | - | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/LanguageModeling/BERT/triton) | Yes | - | +| [GNMT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Translation/GNMT) | PyTorch | Yes | Yes | - | Supported | - | Supported | - | - | +| [ELECTRA](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/LanguageModeling/ELECTRA) | TensorFlow2 | Yes | Yes | Yes | Supported | - | Supported | Yes | - | +| [BERT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT) | TensorFlow | Yes | Yes | Yes | Example | - | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/triton) | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/LanguageModeling/BERT/notebooks) | +| [BERT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/LanguageModeling/BERT) | TensorFlow2 | Yes | Yes | Yes | Supported | - | Supported | Yes | - | +| [GNMT](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Translation/GNMT) | TensorFlow | Yes | Yes | - | Supported | - | Supported | - | - | +| [Faster Transformer](https://github.com/NVIDIA/DeepLearningExamples/tree/master/FasterTransformer) | Tensorflow | - | - | - | Example | - | Supported | - | - | ## Recommender Systems -| Models | Framework | A100 | AMP | Multi-GPU | Multi-Node | TRT | ONNX | Triton | DLC | NB | -| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |------------- |------------- |------------- |------------- |------------- | -| [DLRM](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/DLRM) |PyTorch | Yes | Yes | Yes | - | - | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/DLRM/triton) | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/DLRM/notebooks) | -| [DLRM](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Recommendation/DLRM) | TensorFlow2 | Yes | Yes | Yes | Yes | - | - | - | Yes | - | -| [NCF](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/NCF) | PyTorch | Yes | Yes | Yes | - | - |- | - | - | - | -| [Wide&Deep](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Recommendation/WideAndDeep) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [Wide&Deep](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Recommendation/WideAndDeep) | TensorFlow2 | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [NCF](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Recommendation/NCF) | TensorFlow | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [VAE-CF](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Recommendation/VAE-CF) | TensorFlow | Yes | Yes | Yes | - | - | - | - | - | - | -| [SIM](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Recommendation/SIM) | TensorFlow2 | Yes | Yes | Yes | - | - | - | - | Yes | - | +| Models | Framework | AMP | Multi-GPU | Multi-Node | ONNX | Triton | DLC | NB | +|----------------------------------------------------------------------------------------------------------------|-------------|-------|-----------|--------------|--------|------------------------------------------------------------------------------------------------------|------|--------------------------------------------------------------------------------------------------------| +| [DLRM](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/DLRM) | PyTorch | Yes | Yes | - | Yes | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/DLRM/triton) | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/DLRM/notebooks) | +| [DLRM](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Recommendation/DLRM) | TensorFlow2 | Yes | Yes | Yes | - | Supported | Yes | - | +| [NCF](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Recommendation/NCF) | PyTorch | Yes | Yes | - | - | Supported | - | - | +| [Wide&Deep](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Recommendation/WideAndDeep) | TensorFlow | Yes | Yes | - | - | Supported | Yes | - | +| [Wide&Deep](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Recommendation/WideAndDeep) | TensorFlow2 | Yes | Yes | - | - | Supported | Yes | - | +| [NCF](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Recommendation/NCF) | TensorFlow | Yes | Yes | - | - | Supported | Yes | - | +| [VAE-CF](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Recommendation/VAE-CF) | TensorFlow | Yes | Yes | - | - | Supported | - | - | +| [SIM](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Recommendation/SIM) | TensorFlow2 | Yes | Yes | - | - | Supported | Yes | - | ## Speech to Text -| Models | Framework | A100 | AMP | Multi-GPU | Multi-Node | TRT | ONNX | Triton | DLC | NB | -| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |------------- |------------- |------------- |------------- |------------- | -| [Jasper](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/Jasper) |PyTorch | Yes | Yes | Yes | - | Yes | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/Jasper/trtis) | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/Jasper/notebooks) | -| [Hidden Markov Model](https://github.com/NVIDIA/DeepLearningExamples/tree/master/Kaldi/SpeechRecognition) | Kaldi | - | - | Yes | - | - | - | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/Kaldi/SpeechRecognition) | - | - | +| Models | Framework | AMP | Multi-GPU | Multi-Node | TensorRT | ONNX | Triton | DLC | NB | +|--------------------------------------------------------------------------------------------------------------|-------------|------|------------|--------------|----------|--------|----------------------------------------------------------------------------------------------------------|-------|--------------------------------------------------------------------------------------------------------------| +| [Jasper](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/Jasper) | PyTorch | Yes | Yes | - | Example | Yes | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/Jasper/trtis) | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/Jasper/notebooks) | +| [QuartzNet](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/QuartzNet) | PyTorch | Yes | Yes | - | Supported | - | Supported | Yes | - | ## Text to Speech -| Models | Framework | A100 | AMP | Multi-GPU | Multi-Node | TRT | ONNX | Triton | DLC | NB | -| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |------------- |------------- |------------- |------------- |------------- | -| [FastPitch](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/FastPitch) | PyTorch | Yes | Yes | Yes | - | - | - | - | Yes | - | -| [FastSpeech](https://github.com/NVIDIA/DeepLearningExamples/tree/master/CUDA-Optimized/FastSpeech) | PyTorch | - | Yes | Yes | - | Yes | - | - | - | - | -| [Tacotron 2 and WaveGlow](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2) | PyTorch | Yes | Yes | Yes | - | Yes | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2/trtis_cpp) | Yes | - | +| Models | Framework | AMP | Multi-GPU | Multi-Node | TensorRT | ONNX | Triton | DLC | NB | +|-------------------------------------------------------------------------------------------------------------------------|-------------|------|------------|-------------|----------|--------|---------------------------------------------------------------------------------------------------------------|-------|-----| +| [FastPitch](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/FastPitch) | PyTorch | Yes | Yes | - | Example | - | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/FastPitch/triton) | Yes | Yes | +| [FastSpeech](https://github.com/NVIDIA/DeepLearningExamples/tree/master/CUDA-Optimized/FastSpeech) | PyTorch | Yes | Yes | - | Example | - | Supported | - | - | +| [Tacotron 2 and WaveGlow](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2) | PyTorch | Yes | Yes | - | Example | Yes | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/Tacotron2/trtis_cpp) | Yes | - | +| [HiFi-GAN](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechSynthesis/HiFiGAN) | PyTorch | Yes | Yes | - | Supported | - | Supported | Yes | - | ## Graph Neural Networks -| Models | Framework | A100 | AMP | Multi-GPU | Multi-Node | TRT | ONNX | Triton | DLC | NB | -| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |------------- |------------- |------------- |------------- |------------- | -| [SE(3)-Transformer](https://github.com/NVIDIA/DeepLearningExamples/tree/master/DGLPyTorch/DrugDiscovery/SE3Transformer) | PyTorch | Yes | Yes | Yes | - | - | - | - | - | - | +| Models | Framework | AMP | Multi-GPU | Multi-Node | ONNX | Triton | DLC | NB | +|-------------------------------------------------------------------------------------------------------------------------|------------|------|------------|--------------|--------|----------|------|------| +| [SE(3)-Transformer](https://github.com/NVIDIA/DeepLearningExamples/tree/master/DGLPyTorch/DrugDiscovery/SE3Transformer) | PyTorch | Yes | Yes | - | - | Supported | - | - | +| [MoFlow](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/DrugDiscovery/MoFlow) | PyTorch | Yes | Yes | - | - | Supported | - | - | ## Time-Series Forecasting -| Models | Framework | A100 | AMP | Multi-GPU | Multi-Node | TRT | ONNX | Triton | DLC | NB | -| ------------- | ------------- | ------------- | ------------- | ------------- | ------------- |------------- |------------- |------------- |------------- |------------- | -| [Temporal Fusion Transformer](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Forecasting/TFT) | PyTorch | Yes | Yes | Yes | - | Yes | Yes | [Yes](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Forecasting/TFT/triton) | Yes | - | +| Models | Framework | AMP | Multi-GPU | Multi-Node | TensorRT | ONNX | Triton | DLC | NB | +|-------------------------------------------------------------------------------------------------------------------|------------|------|-------------|--------------|----------|--------|--------------------------------------------------------------------------------------------------|-------|-----| +| [Temporal Fusion Transformer](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Forecasting/TFT) | PyTorch | Yes | Yes | - | Example | Yes | [Example](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Forecasting/TFT/triton) | Yes | - | ## NVIDIA support In each of the network READMEs, we indicate the level of support that will be provided. The range is from ongoing updates and improvements to a point-in-time release for thought leadership. ## Glossary - -**Multinode Training** + +**Multinode Training** Supported on a pyxis/enroot Slurm cluster. -**Deep Learning Compiler (DLC)** +**Deep Learning Compiler (DLC)** TensorFlow XLA and PyTorch JIT and/or TorchScript -**Accelerated Linear Algebra (XLA)** +**Accelerated Linear Algebra (XLA)** XLA is a domain-specific compiler for linear algebra that can accelerate TensorFlow models with potentially no source code changes. The results are improvements in speed and memory usage. -**PyTorch JIT and/or TorchScript** +**PyTorch JIT and/or TorchScript** TorchScript is a way to create serializable and optimizable models from PyTorch code. TorchScript, an intermediate representation of a PyTorch model (subclass of nn.Module) that can then be run in a high-performance environment such as C++. -**Automatic Mixed Precision (AMP)** +**Automatic Mixed Precision (AMP)** Automatic Mixed Precision (AMP) enables mixed precision training on Volta, Turing, and NVIDIA Ampere GPU architectures automatically. -**TensorFloat-32 (TF32)** +**TensorFloat-32 (TF32)** TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on Volta GPUs. TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by default. -**Jupyter Notebooks (NB)** +**Jupyter Notebooks (NB)** The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. diff --git a/TensorFlow/Classification/ConvNets/README.md b/TensorFlow/Classification/ConvNets/README.md index 1d51a3e8e..636e1fa96 100644 --- a/TensorFlow/Classification/ConvNets/README.md +++ b/TensorFlow/Classification/ConvNets/README.md @@ -1,7 +1,7 @@ # Resnet-family Convolutional Neural Networks for Image Classification in Tensorflow -In this repository you will find implementation of Resnet and its variations for image -classification +In this repository you will find implementation of Resnet and its variations for image classification. +Convolutional Network models for TensorFlow1 are no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents @@ -84,6 +84,10 @@ three classification models side-by-side. ## Release notes ### Changelog + +April 2021 + - Ceased maintenance of ConvNets in TensorFlow1 + June 2020 - ConvNets repo restructurization - Initial release of ResNext and SE-Resnext diff --git a/TensorFlow/Classification/ConvNets/resnet50v1.5/README.md b/TensorFlow/Classification/ConvNets/resnet50v1.5/README.md index aeb4ad894..5916ef0ad 100644 --- a/TensorFlow/Classification/ConvNets/resnet50v1.5/README.md +++ b/TensorFlow/Classification/ConvNets/resnet50v1.5/README.md @@ -1,6 +1,7 @@ # ResNet-50 v1.5 for TensorFlow This repository provides a script and recipe to train the ResNet-50 v1.5 model to achieve state-of-the-art accuracy, and is tested and maintained by NVIDIA. +ResNet-50 model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents * [Model overview](#model-overview) @@ -858,5 +859,8 @@ on NVIDIA T4 with (1x T4 16G) GPU. * Added support for syntetic dataset with different image size 9. January, 2022 * Added barrier at the end of multiprocess run +10. April, 2023 + * Ceased maintenance of ConvNets in TensorFlow1 + ### Known issues Performance without XLA enabled is low due to BN + ReLU fusion bug. diff --git a/TensorFlow/Classification/ConvNets/resnext101-32x4d/README.md b/TensorFlow/Classification/ConvNets/resnext101-32x4d/README.md index f17e513c1..197c8ba12 100644 --- a/TensorFlow/Classification/ConvNets/resnext101-32x4d/README.md +++ b/TensorFlow/Classification/ConvNets/resnext101-32x4d/README.md @@ -1,6 +1,7 @@ # ResNext101-32x4d for TensorFlow This repository provides a script and recipe to train the ResNext101-32x4d model to achieve state-of-the-art accuracy, and is tested and maintained by NVIDIA. +ResNext101-32x4d model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents * [Model overview](#model-overview) @@ -791,6 +792,8 @@ on NVIDIA T4 with (1x T4 16G) GPU. ### Changelog +April 2023 + - Ceased maintenance of ConvNets in TensorFlow1 June 2020 - Initial release August 2020 diff --git a/TensorFlow/Classification/ConvNets/se-resnext101-32x4d/README.md b/TensorFlow/Classification/ConvNets/se-resnext101-32x4d/README.md index 4de00134a..d2cbd35f7 100644 --- a/TensorFlow/Classification/ConvNets/se-resnext101-32x4d/README.md +++ b/TensorFlow/Classification/ConvNets/se-resnext101-32x4d/README.md @@ -1,6 +1,7 @@ # SE-ResNext101-32x4d for TensorFlow This repository provides a script and recipe to train the SE-ResNext101-32x4d model to achieve state-of-the-art accuracy, and is tested and maintained by NVIDIA. +SE-ResNext101-32x4d model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents * [Model overview](#model-overview) @@ -784,6 +785,8 @@ on NVIDIA T4 with (1x T4 16G) GPU. ### Changelog +April 2023 + - Ceased maintenance of ConvNets in TensorFlow1 April 2020 - Initial release August 2020 diff --git a/TensorFlow/Detection/SSD/README.md b/TensorFlow/Detection/SSD/README.md index 8f51fa48a..c01a3bea6 100644 --- a/TensorFlow/Detection/SSD/README.md +++ b/TensorFlow/Detection/SSD/README.md @@ -1,6 +1,7 @@ # SSD320 v1.2 For TensorFlow This repository provides a script and recipe to train SSD320 v1.2 to achieve state of the art accuracy, and is tested and maintained by NVIDIA. +SSD model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider a PyTorch version or EfficientDet TensorFlow2 model as a substitute for your requirements. ## Table Of Contents * [Model overview](#model-overview) @@ -614,6 +615,9 @@ To achieve same results, follow the [Quick start guide](#quick-start-guide) outl ### Changelog +April 2023 + * Ceased maintenance of this model in TensorFlow1 + June 2020 * Updated performance tables to include A100 results diff --git a/TensorFlow/LanguageModeling/BERT/Dockerfile b/TensorFlow/LanguageModeling/BERT/Dockerfile index 13f3575eb..7ad4404ca 100644 --- a/TensorFlow/LanguageModeling/BERT/Dockerfile +++ b/TensorFlow/LanguageModeling/BERT/Dockerfile @@ -15,13 +15,8 @@ RUN git clone https://github.com/titipata/pubmed_parser RUN pip3 install /workspace/pubmed_parser -#Copy the perf_client over -ARG TRTIS_CLIENTS_URL=https://github.com/NVIDIA/triton-inference-server/releases/download/v2.2.0/v2.2.0_ubuntu1804.clients.tar.gz -RUN mkdir -p /workspace/install \ - && curl -L ${TRTIS_CLIENTS_URL} | tar xvz -C /workspace/install - -#Install the python wheel with pip -RUN pip install /workspace/install/python/triton*.whl +#Install tritonclient +RUN pip install tritonclient[all]==2.5.0 WORKDIR /workspace/bert COPY . . diff --git a/TensorFlow/LanguageModeling/BERT/README.md b/TensorFlow/LanguageModeling/BERT/README.md index c0d04d6f7..62c096920 100644 --- a/TensorFlow/LanguageModeling/BERT/README.md +++ b/TensorFlow/LanguageModeling/BERT/README.md @@ -1,6 +1,7 @@ # BERT For TensorFlow This repository provides a script and recipe to train the BERT model for TensorFlow to achieve state-of-the-art accuracy, and is tested and maintained by NVIDIA. +BERT model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents @@ -1201,6 +1202,10 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ## Release notes ### Changelog + +April 2023 +- Ceased maintenance of this model in TensorFlow1 + June 2020 - Results obtained using 20.06 and on DGX A100 40GB diff --git a/TensorFlow/LanguageModeling/BERT/triton/scripts/run_perf_client.sh b/TensorFlow/LanguageModeling/BERT/triton/scripts/run_perf_client.sh index cfbc30015..2e756e45b 100755 --- a/TensorFlow/LanguageModeling/BERT/triton/scripts/run_perf_client.sh +++ b/TensorFlow/LanguageModeling/BERT/triton/scripts/run_perf_client.sh @@ -69,4 +69,4 @@ ARGS="\ echo "Using args: $(echo "$ARGS" | sed -e 's/ -/\n-/g')" -bash scripts/docker/launch.sh /workspace/install/bin/perf_client $ARGS +bash scripts/docker/launch.sh perf_client $ARGS diff --git a/TensorFlow/LanguageModeling/Transformer-XL/README.md b/TensorFlow/LanguageModeling/Transformer-XL/README.md index 42f6c6171..7246bf3a4 100755 --- a/TensorFlow/LanguageModeling/Transformer-XL/README.md +++ b/TensorFlow/LanguageModeling/Transformer-XL/README.md @@ -2,6 +2,7 @@ This repository provides a script and recipe to train the Transformer-XL model to achieve state-of-the-art accuracy and is tested and maintained by NVIDIA. +Transformer-XL model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider other PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents @@ -1050,6 +1051,9 @@ To achieve these same results, follow the steps in the [Quick Start Guide](#quic ### Changelog +April 2023 + * Ceased maintenance of this model in TensorFlow1 + June 2020 * upgrade the TensorFlow container to 20.06 * update performance tables to include A100 results diff --git a/TensorFlow/Recommendation/NCF/README.md b/TensorFlow/Recommendation/NCF/README.md index e2a85e001..bd025ad6c 100644 --- a/TensorFlow/Recommendation/NCF/README.md +++ b/TensorFlow/Recommendation/NCF/README.md @@ -2,6 +2,7 @@ This repository provides a script and recipe to train Neural Collaborative Filtering to achieve state of the art accuracy, and is tested and maintained by NVIDIA. +NCF model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider DLRM and Wide & Deep models in TensorFlow2 as a substitute for your requirements. ## Table of Contents @@ -519,6 +520,9 @@ FP16 ### Changelog +April 2023 +- Ceased maintenance of this model in TensorFlow1 + June 2020 - Updated performance tables to include A100 results diff --git a/TensorFlow/Recommendation/VAE-CF/README.md b/TensorFlow/Recommendation/VAE-CF/README.md index 873961cfc..67f5934a9 100644 --- a/TensorFlow/Recommendation/VAE-CF/README.md +++ b/TensorFlow/Recommendation/VAE-CF/README.md @@ -1,6 +1,7 @@ # Variational Autoencoder for Collaborative Filtering for TensorFlow This repository provides a script and recipe to train the Variational Autoencoder model for TensorFlow to achieve state-of-the-art accuracy on a Collaborative Filtering task and is tested and maintained by NVIDIA. +VAE-CF model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider other PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents @@ -447,6 +448,9 @@ FP16 ### Changelog +April 2023 +- Ceased maintenance of this model in TensorFlow1 + July 2020 - Updated with Ampere convergence and performance results diff --git a/TensorFlow/Recommendation/WideAndDeep/README.md b/TensorFlow/Recommendation/WideAndDeep/README.md index 52f20dfae..18c3a26b0 100644 --- a/TensorFlow/Recommendation/WideAndDeep/README.md +++ b/TensorFlow/Recommendation/WideAndDeep/README.md @@ -1,6 +1,7 @@ # Wide & Deep Recommender Model Training For TensorFlow This repository provides a script and recipe to train the Wide and Deep Recommender model to achieve state-of-the-art accuracy and is tested and maintained by NVIDIA. +Wide & Deep model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents @@ -469,6 +470,9 @@ Our results were obtained by running the benchmark scripts from the `scripts` di ### Changelog +April 2023 +- Ceased maintenance of this model in TensorFlow1 + November 2020 - Updated performance tables to include numbers from 20.10-tf1-py3 NGC container diff --git a/TensorFlow/Segmentation/MaskRCNN/README.md b/TensorFlow/Segmentation/MaskRCNN/README.md index 4286bc8c4..e26a5a22d 100644 --- a/TensorFlow/Segmentation/MaskRCNN/README.md +++ b/TensorFlow/Segmentation/MaskRCNN/README.md @@ -1 +1,3 @@ Both TensorFlow 1.x and TensorFlow 2.x versions of Mask-RCNN are located in [TensorFlow2/Segmentation/MaskRCNN folder](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow2/Segmentation/MaskRCNN). +Mask-RCNN model for TensorFlow1 is no longer maintained. + diff --git a/TensorFlow/Segmentation/UNet_3D_Medical/README.md b/TensorFlow/Segmentation/UNet_3D_Medical/README.md index db7ca856d..cba1aba9c 100644 --- a/TensorFlow/Segmentation/UNet_3D_Medical/README.md +++ b/TensorFlow/Segmentation/UNet_3D_Medical/README.md @@ -2,6 +2,7 @@ This repository provides a script and recipe to train the 3D-UNet model to achieve state-of-the-art accuracy. The content of this repository is tested and maintained by NVIDIA. +3D-UNet model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider other PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table of Contents @@ -593,6 +594,9 @@ To achieve these same results, follow the steps in the [Inference performance be ### Changelog +April 2023 +* Ceased maintenance of this model in TensorFlow1 + November 2021 * Updated README tables diff --git a/TensorFlow/Segmentation/UNet_Industrial/README.md b/TensorFlow/Segmentation/UNet_Industrial/README.md index e7da52202..1e63e7307 100644 --- a/TensorFlow/Segmentation/UNet_Industrial/README.md +++ b/TensorFlow/Segmentation/UNet_Industrial/README.md @@ -2,6 +2,7 @@ This repository provides a script and recipe to train UNet Industrial to achieve state of the art accuracy on the dataset DAGM2007, and is tested and maintained by NVIDIA. +UNet model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider other PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table of Contents @@ -519,6 +520,9 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ### Changelog +April 2023 +* Ceased maintenance of this model + June 2020 * Updated training and inference accuracy with A100 results diff --git a/TensorFlow/Segmentation/UNet_Medical/README.md b/TensorFlow/Segmentation/UNet_Medical/README.md index 2ff3a8a5e..b5953102f 100644 --- a/TensorFlow/Segmentation/UNet_Medical/README.md +++ b/TensorFlow/Segmentation/UNet_Medical/README.md @@ -1,6 +1,7 @@ # UNet Medical Image Segmentation for TensorFlow 1.x This repository provides a script and recipe to train UNet Medical to achieve state of the art accuracy, and is tested and maintained by NVIDIA. +UNet model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider other PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table of Contents @@ -600,6 +601,9 @@ Throughput is reported in images per second. Latency is reported in milliseconds ### Changelog +April 2023 +* Ceased maintenance of this model in TensorFlow1 + June 2020 * Updated training and inference accuracy with A100 results * Updated training and inference performance with A100 results diff --git a/TensorFlow/Segmentation/VNet/README.md b/TensorFlow/Segmentation/VNet/README.md index 69f4d46fc..59535f12d 100644 --- a/TensorFlow/Segmentation/VNet/README.md +++ b/TensorFlow/Segmentation/VNet/README.md @@ -1,6 +1,7 @@ # V-Net Medical For Tensorflow -This repository provides a script and recipe to train the V-Net model to achieve state of the art accuracy, and is tested and maintained by NVIDIA. V-Net model for TensorFlow is no longer maintained and will soon become unavailable, please consider [UNet for 3D image segmentation in TensorFlow](https://github.com/NVIDIA/DeepLearningExamples/tree/master/TensorFlow/Segmentation/UNet_3D_Medical) or [nnU-Net for PyTorch](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Segmentation/nnUNet) as a substitute for your requirements. +This repository provides a script and recipe to train the V-Net model to achieve state of the art accuracy, and is tested and maintained by NVIDIA. +V-Net model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider [nnU-Net for PyTorch](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Segmentation/nnUNet) as a substitute for your requirements. ## Table of Contents diff --git a/TensorFlow/Translation/GNMT/README.md b/TensorFlow/Translation/GNMT/README.md index fad60304e..df031a811 100644 --- a/TensorFlow/Translation/GNMT/README.md +++ b/TensorFlow/Translation/GNMT/README.md @@ -1,6 +1,7 @@ # GNMT v2 For TensorFlow This repository provides a script and recipe to train the GNMT v2 model to achieve state-of-the-art accuracy and is tested and maintained by NVIDIA. +GNMT model for TensorFlow1 is no longer maintained and will soon become unavailable, please consider PyTorch or TensorFlow2 models as a substitute for your requirements. ## Table Of Contents - [Model overview](#model-overview) @@ -828,6 +829,8 @@ Reported mixed precision speedups are relative to FP32 numbers for corresponding * Performance improvements 3. June, 2020 * Updated performance tables to include A100 results +4. April 2023 + * Ceased maintenance of this model in TensorFlow1 ### Known issues There are no known issues in this release. diff --git a/TensorFlow2/Classification/ConvNets/dataloader/augment.py b/TensorFlow2/Classification/ConvNets/dataloader/augment.py index 4146613bc..f71828626 100644 --- a/TensorFlow2/Classification/ConvNets/dataloader/augment.py +++ b/TensorFlow2/Classification/ConvNets/dataloader/augment.py @@ -26,7 +26,11 @@ import tensorflow as tf from typing import Any, Dict, List, Optional, Text, Tuple -from keras.layers.preprocessing import image_preprocessing as image_ops +try: + from keras.layers.preprocessing import image_preprocessing as image_ops +except (ImportError, ModuleNotFoundError): + import keras.src.layers.preprocessing.image_preprocessing as image_ops + # This signifies the max integer that the controller RNN could predict for the # augmentation scheme. diff --git a/TensorFlow2/Classification/ConvNets/utils/setup.py b/TensorFlow2/Classification/ConvNets/utils/setup.py index 1f7e05e6a..99e92a100 100644 --- a/TensorFlow2/Classification/ConvNets/utils/setup.py +++ b/TensorFlow2/Classification/ConvNets/utils/setup.py @@ -44,8 +44,10 @@ def set_flags(params): # we set tf_xla_async_io_level=0 for 2 reasons: 1) It turns out that XLA doesn't like # hvd.allreduce ops used in the custom train_step. Because of this issue, training never started. # 2) XLA doesn't like the tf.cond used in conditional mixing (model module). - os.environ['TF_XLA_FLAGS'] = TF_XLA_FLAGS + " --tf_xla_auto_jit=1 --tf_xla_async_io_level=0" + # remove async flag since it's obsolete + #os.environ['TF_XLA_FLAGS'] = TF_XLA_FLAGS + " --tf_xla_auto_jit=1 --tf_xla_async_io_level=0" + os.environ['TF_XLA_FLAGS'] = TF_XLA_FLAGS + " --tf_xla_auto_jit=1" os.environ['TF_EXTRA_PTXAS_OPTIONS'] = "-sw200428197=true" tf.keras.backend.clear_session() tf.config.optimizer.set_jit(True) diff --git a/TensorFlow2/LanguageModeling/BERT/README.md b/TensorFlow2/LanguageModeling/BERT/README.md index 72a3d023b..f5e580336 100644 --- a/TensorFlow2/LanguageModeling/BERT/README.md +++ b/TensorFlow2/LanguageModeling/BERT/README.md @@ -713,7 +713,7 @@ The following tables compare `F1` scores across 5 different training runs with d ##### Pre-training training performance: Single-node on NVIDIA DGX-2 V100 (16x V100 32GB) -Our results were obtained by running the `scripts/run_pretraining_lamb.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-2 with 16x V100 32GB GPUs. Performance (in sentences per second) is the steady state throughput. +Our results were obtained by running the `scripts/run_pretraining_lamb.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-2 with 16x V100 32GB GPUs. Performance (in sequences per second) is the steady state throughput. | **GPUs** | **Sequence Length** | **Batch size / GPU: mixed precision, FP32** | **Gradient Accumulation: mixed precision, FP32** | **Global Batch Size: mixed precision, FP32** | **Throughput - mixed precision** | **Throughput - FP32** | **Throughput speedup (FP32 - mixed precision)** | **Weak scaling - mixed precision** | **Weak scaling - FP32** | |:--------:|:-------------------:|:-------------------------------------------:|--------------------------------------------------|:--------------------------------------------:|:--------------------------------:|:---------------------:|-------------------------------------------------|------------------------------------|-------------------------| @@ -730,7 +730,7 @@ Note: The respective values for FP32 runs that use a batch size of 60 and 10 in ##### Pre-training training performance: Multi-node on NVIDIA DGX-2H V100 (16x V100 32GB) -Our results were obtained by running the `run.sub` training script in the TensorFlow 21.02-py3 NGC container using multiple NVIDIA DGX-2 with 16x V100 32GB GPUs. Performance (in sentences per second) is the steady state throughput. +Our results were obtained by running the `run.sub` training script in the TensorFlow 21.02-py3 NGC container using multiple NVIDIA DGX-2 with 16x V100 32GB GPUs. Performance (in sequences per second) is the steady state throughput. | **Num Nodes** | **Sequence Length** | **Batch size / GPU: mixed precision, FP32** | **Gradient Accumulation: mixed precision, FP32** | **Global Batch Size: mixed precision, FP32** | **Throughput - mixed precision** | **Throughput - FP32** | **Throughput speedup (FP32 - mixed precision)** | **Weak scaling - mixed precision** | **Weak scaling - FP32** | |:-------------:|:-------------------:|:-------------------------------------------:|--------------------------------------------------|:--------------------------------------------:|:--------------------------------:|:---------------------:|-------------------------------------------------|------------------------------------|-------------------------| @@ -747,7 +747,7 @@ Note: The respective values for FP32 runs that use a batch size of 60 and 10 in ##### Pre-training training performance: Single-node on NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `scripts/run_pretraining_lamb.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX A100 with 8x A100 80GB GPUs. Performance (in sentences per second) is the steady state throughput. +Our results were obtained by running the `scripts/run_pretraining_lamb.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX A100 with 8x A100 80GB GPUs. Performance (in sequences per second) is the steady state throughput. | **GPUs** | **Sequence Length** | **Batch size / GPU: mixed precision, TF32** | **Gradient Accumulation: mixed precision, TF32** | **Global Batch Size: mixed precision, FP32** | **Throughput - mixed precision** | **Throughput - TF32** | **Throughput speedup (TF32 - mixed precision)** | **Weak scaling - mixed precision** | **Weak scaling -TF32** | |:--------:|:-------------------:|:-------------------------------------------:|--------------------------------------------------|:--------------------------------------------:|:--------------------------------:|:---------------------:|-------------------------------------------------|------------------------------------|------------------------| @@ -760,7 +760,7 @@ Note: The respective values for TF32 runs that use a batch size of 312 and 40 in ##### Pre-training training performance: Multi-node on NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `scripts/run_pretraining_lamb.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX A100 with 8x A100 40GB GPUs. Performance (in sentences per second) is the steady state throughput. +Our results were obtained by running the `scripts/run_pretraining_lamb.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX A100 with 8x A100 40GB GPUs. Performance (in sequences per second) is the steady state throughput. | **Num Nodes** | **Sequence Length** | **Batch size / GPU: mixed precision, TF32** | **Gradient Accumulation: mixed precision, TF32** | **Global Batch Size: mixed precision, FP32** | **Throughput - mixed precision** | **Throughput - TF32** | **Throughput speedup (TF32 - mixed precision)** | **Weak scaling - mixed precision** | **Weak scaling -TF32** | |:-------------:|:-------------------:|:-------------------------------------------:|--------------------------------------------------|:--------------------------------------------:|:--------------------------------:|:---------------------:|-------------------------------------------------|------------------------------------|------------------------| @@ -777,7 +777,7 @@ Note: The respective values for TF32 runs that use a batch size of 312 and 40 in ##### Fine-tuning training performance for SQuAD v1.1 on NVIDIA DGX-1 V100 (8x V100 16GB) -Our results were obtained by running the `scripts/run_squad.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 8x V100 16GB GPUs. Performance (in sentences per second) is the mean throughput from 2 epochs. +Our results were obtained by running the `scripts/run_squad.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 8x V100 16GB GPUs. Performance (in sequences per second) is the mean throughput from 2 epochs. | **GPUs** | **Batch size / GPU: mixed precision, FP32** | **Throughput - mixed precision** | **Throughput - FP32** | **Throughput speedup (FP32 to mixed precision)** | **Weak scaling - FP32** | **Weak scaling - mixed precision** | |:---:|:---:|:------:|:-----:|:----:|:----:|:----:| @@ -791,7 +791,7 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ##### Fine-tuning training performance for SQuAD v1.1 on NVIDIA DGX-1 V100 (8x V100 32GB) -Our results were obtained by running the `scripts/run_squad.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 8x V100 32GB GPUs. Performance (in sentences per second) is the mean throughput from 2 epochs. +Our results were obtained by running the `scripts/run_squad.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 8x V100 32GB GPUs. Performance (in sequences per second) is the mean throughput from 2 epochs. | **GPUs** | **Batch size / GPU: mixed precision, FP32** | **Throughput - mixed precision** | **Throughput - FP32** | **Throughput speedup (FP32 to mixed precision)** | **Weak scaling - FP32** | **Weak scaling - mixed precision** | @@ -806,7 +806,7 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ##### Fine-tuning training performance for SQuAD v1.1 on NVIDIA DGX A100 (8x A100 80GB) -Our results were obtained by running the `scripts/run_squad.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-2 with 16x V100 32GB GPUs. Performance (in sentences per second) is the mean throughput from 2 epochs. +Our results were obtained by running the `scripts/run_squad.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-2 with 16x V100 32GB GPUs. Performance (in sequences per second) is the mean throughput from 2 epochs. | **GPUs** | **Batch size / GPU: mixed precision, TF32** | **Throughput - mixed precision** | **Throughput - FP32** | **Throughput speedup (FP32 to mixed precision)** | **Weak scaling - FP32** | **Weak scaling - mixed precision** | |---|---|------|------|----|-----|-----| @@ -823,11 +823,11 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ##### Fine-tuning inference performance for SQuAD v1.1 on NVIDIA DGX-1 V100 (1x V100 16GB) -Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 1x V100 16GB GPUs. Performance numbers (throughput in sentences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. +Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 1x V100 16GB GPUs. Performance numbers (throughput in sequences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. BERT-LARGE FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 105.04 | 1.277237354 | 9.52 | 9.67 | 9.77 | 10.16 | | 128 | 2 | 184.9 | 1.671487977 | 10.82 | 11.15 | 11.27 | 11.8 | @@ -840,7 +840,7 @@ BERT-LARGE FP16 BERT-Large FP32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 82.24 | 12.16 | 12.28 | 12.33 | 12.92 | | 128 | 2 | 110.62 | 18.08 | 18.22 | 18.28 | 18.88 | @@ -853,7 +853,7 @@ BERT-Large FP32 BERT-Base FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 236.26 | 1.179589595 | 4.23 | 4.37 | 4.49 | 4.59 | | 128 | 2 | 425.1 | 1.441554478 | 4.7 | 4.84 | 4.97 | 5.26 | @@ -866,7 +866,7 @@ BERT-Base FP16 BERT-Base FP32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 200.29 | 4.99 | 5.08 | 5.16 | 5.53 | | 128 | 2 | 294.89 | 6.78 | 6.89 | 6.93 | 7.37 | @@ -881,11 +881,11 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ##### Fine-tuning inference performance for SQuAD v1.1 on NVIIDA DGX-1 V100 (1x V100 32GB) -Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 1x V100 32GB GPUs. Performance numbers (throughput in sentences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. +Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-1 with 1x V100 32GB GPUs. Performance numbers (throughput in sequences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. BERTLarge FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 101.58 | 1.242112986 | 9.84 | 9.99 | 10.06 | 10.39 | | 128 | 2 | 181.89 | 1.651593571 | 11 | 11.14 | 11.2 | 11.87 | @@ -898,7 +898,7 @@ BERTLarge FP16 BERT-Large FP32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 81.78 | 12.23 | 12.37 | 12.43 | 13.2 | | 128 | 2 | 110.13 | 18.16 | 18.29 | 18.37 | 19.27 | @@ -911,7 +911,7 @@ BERT-Large FP32 BERT-Base FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 234.85 | 1.217533309 | 4.26 | 4.33 | 4.37 | 4.62 | | 128 | 2 | 415.86 | 1.435782351 | 4.81 | 4.92 | 5.06 | 5.55 | @@ -924,7 +924,7 @@ BERT-Base FP16 BERT-Base FP32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 192.89 | 5.18 | 5.3 | 5.36 | 5.65 | | 128 | 2 | 289.64 | 6.91 | 7 | 7.22 | 7.83 | @@ -940,11 +940,11 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ##### Fine-tuning inference performance for SQuAD v1.1 on NVIDIA DGX A100 (1x A100 80GB) -Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-2 with 1x V100 32GB GPUs. Performance numbers (throughput in sentences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. +Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA DGX-2 with 1x V100 32GB GPUs. Performance numbers (throughput in sequences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. BERT-Large FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 145.21 | 0.9435347628 | 6.89 | 7.14 | 7.4 | 8.35 | | 128 | 2 | 272.81 | 1.093953003 | 7.33 | 7.61 | 7.77 | 8.35 | @@ -957,7 +957,7 @@ BERT-Large FP16 BERT-Large TF32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 153.9 | 6.5 | 6.76 | 6.86 | 7.4 | | 128 | 2 | 249.38 | 8.02 | 8.22 | 8.34 | 9.45 | @@ -970,7 +970,7 @@ BERT-Large TF32 BERT-Base FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 295.01 | 1.014023992 | 3.39 | 3.59 | 3.65 | 3.73 | | 128 | 2 | 594.81 | 1.048455898 | 3.36 | 3.59 | 3.68 | 4.19 | @@ -983,7 +983,7 @@ BERT-Base FP16 BERT-Base TF32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 290.93 | 3.44 | 3.61 | 3.73 | 4.69 | | 128 | 2 | 567.32 | 3.53 | 3.64 | 3.96 | 5.01 | @@ -998,11 +998,11 @@ To achieve these same results, follow the [Quick Start Guide](#quick-start-guide ##### Fine-tuning inference performance for SQuAD v1.1 on NVIDIA Tesla T4 (1x T4 16GB) -Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA Tesla T4 with 1x T4 16GB GPUs. Performance numbers (throughput in sentences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. +Our results were obtained by running the `scripts/finetune_inference_benchmark.sh` training script in the TensorFlow 21.02-py3 NGC container on NVIDIA Tesla T4 with 1x T4 16GB GPUs. Performance numbers (throughput in sequences per second and latency in milliseconds) were averaged from 1000 iterations. Latency is computed as the time taken for a batch to process as they are fed in one after another in the model ie no pipelining. BERT-Large FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 57.6 | 1.364605544 | 17.36 | 18.16 | 19.02 | 21.67 | | 128 | 2 | 102.76 | 2.17988969 | 19.46 | 20.68 | 21.27 | 22.2 | @@ -1015,7 +1015,7 @@ BERT-Large FP16 BERT-Large FP32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 42.21 | 23.69 | 24.8 | 25.02 | 25.48 | | 128 | 2 | 47.14 | 42.42 | 43.48 | 43.63 | 44.32 | @@ -1028,7 +1028,7 @@ BERT-Large FP32 BERT-Base FP16 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Throughput speedup (FP32 to mixed precision) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|----------------------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 116.56 | 1.039878669 | 8.58 | 9.53 | 10.84 | 11.74 | | 128 | 2 | 238.62 | 1.675937632 | 8.38 | 9.09 | 9.27 | 12.33 | @@ -1042,7 +1042,7 @@ BERT-Base FP16 BERT-Base FP32 -| Sequence Length | Batch Size | Throughput-Average(sent/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | +| Sequence Length | Batch Size | Throughput-Average(seq/sec) | Latency-Average(ms) | Latency-90%(ms) | Latency-95%(ms) | Latency-99%(ms) | |-----------------|------------|------------------------------|---------------------|-----------------|-----------------|-----------------| | 128 | 1 | 112.09 | 8.92 | 9.12 | 9.49 | 10.93 | | 128 | 2 | 142.38 | 14.05 | 14.34 | 14.48 | 15.03 | diff --git a/TensorFlow2/LanguageModeling/BERT/official/modeling/model_training_utils.py b/TensorFlow2/LanguageModeling/BERT/official/modeling/model_training_utils.py index 66eb266d0..f5d080fa0 100644 --- a/TensorFlow2/LanguageModeling/BERT/official/modeling/model_training_utils.py +++ b/TensorFlow2/LanguageModeling/BERT/official/modeling/model_training_utils.py @@ -598,11 +598,11 @@ def _run_callbacks_on_batch_end(batch): if hvd: logging.info("Multi-GPU training with TF Horovod") logging.info("hvd.size() = %d", hvd.size()) - logging.info("Total Training Time = %0.2f for Sentences = %d", total_time, total_sentences) + logging.info("Total Training Time = %0.2f for Sequences = %d", total_time, total_sentences) if total_time != 0: - logging.info("Throughput Average (sentences/sec) with overhead = %0.2f", total_sentences/total_time) + logging.info("Throughput Average (sequences/sec) with overhead = %0.2f", total_sentences/total_time) if perf_wo_n != 0: - logging.info("Throughput Average (sentences/sec) = %0.2f", perf_wo/perf_wo_n) + logging.info("Throughput Average (sequences/sec) = %0.2f", perf_wo/perf_wo_n) logging.info("-----------------------------") if dllogging and perf_wo_n != 0: diff --git a/TensorFlow2/LanguageModeling/BERT/run_squad.py b/TensorFlow2/LanguageModeling/BERT/run_squad.py index 48c661f86..87f5f019c 100644 --- a/TensorFlow2/LanguageModeling/BERT/run_squad.py +++ b/TensorFlow2/LanguageModeling/BERT/run_squad.py @@ -295,7 +295,7 @@ def tuple_fun(x): cf_100 = max(time_list[:int(len(time_list) * 1)]) ss_sentences_per_second = num_sentences * 1.0 / eval_time_wo_overhead - logging.info("Total Inference Time W/O Overhead = %0.2f for Sentences = %d", eval_time_wo_overhead, + logging.info("Total Inference Time W/O Overhead = %0.2f for Sequences = %d", eval_time_wo_overhead, (num_steps - 4) * FLAGS.predict_batch_size) logging.info("Latency Confidence Level 50 (ms) = %0.2f", cf_50 * 1000) logging.info("Latency Confidence Level 90 (ms) = %0.2f", cf_90 * 1000) @@ -303,7 +303,7 @@ def tuple_fun(x): logging.info("Latency Confidence Level 99 (ms) = %0.2f", cf_99 * 1000) logging.info("Latency Confidence Level 100 (ms) = %0.2f", cf_100 * 1000) logging.info("Latency Average (ms) = %0.2f", avg * 1000) - logging.info("Throughput Average (sentences/sec) = %0.2f", ss_sentences_per_second) + logging.info("Throughput Average (sequences/sec) = %0.2f", ss_sentences_per_second) dllogging = input_meta_data['dllogging'] dllogging.logger.log(step=(), data={"throughput_val": ss_sentences_per_second}, verbosity=Verbosity.DEFAULT) diff --git a/TensorFlow2/LanguageModeling/ELECTRA/Dockerfile b/TensorFlow2/LanguageModeling/ELECTRA/Dockerfile index 5c095c420..88decd29b 100644 --- a/TensorFlow2/LanguageModeling/ELECTRA/Dockerfile +++ b/TensorFlow2/LanguageModeling/ELECTRA/Dockerfile @@ -13,45 +13,9 @@ # limitations under the License. ARG FROM_IMAGE_NAME=nvcr.io/nvidia/tensorflow:20.07-tf2-py3 - -###### -# Tokenizers is only available pre-built on x86 -# -FROM ${FROM_IMAGE_NAME} AS tokenizers_amd64 -WORKDIR /wheelhouse -RUN pip download tokenizers==0.7.0 - -FROM quay.io/pypa/manylinux2014_aarch64 as tokenizers_arm64 -ARG PYVER=38 -RUN yum install -y openssl-devel -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2019-11-01 -y -ENV PATH="/root/.cargo/bin:$PATH" -ENV PYBIN=/opt/python/cp${PYVER}-cp${PYVER}/bin -ENV PYTHON_SYS_EXECUTABLE="$PYBIN/python" -RUN git clone -b python-v0.8.0 https://github.com/huggingface/tokenizers.git /opt/tokenizers -WORKDIR /opt/tokenizers/bindings/python -RUN "${PYBIN}/pip" install setuptools-rust \ - && "${PYBIN}/python" setup.py bdist_wheel \ - && rm -rf build/* \ - && for whl in dist/*.whl; do \ - auditwheel repair "$whl" -w dist/; \ - done \ - && rm dist/*-linux_* \ - && mkdir -p /wheelhouse \ - && mv dist/*.whl /wheelhouse - -ARG TARGETARCH -FROM tokenizers_${TARGETARCH} AS tokenizers -# -##### - - FROM ${FROM_IMAGE_NAME} RUN apt-get update && apt-get install -y pbzip2 pv bzip2 cabextract -RUN --mount=from=tokenizers,source=/wheelhouse,target=/tmp/wheelhouse \ - pip install --no-cache-dir /tmp/wheelhouse/tokenizers*.whl - ENV DATA_PREP_WORKING_DIR /workspace/electra/data WORKDIR /workspace RUN git clone https://github.com/attardi/wikiextractor.git && cd wikiextractor && git checkout 6408a430fc504a38b04d37ce5e7fc740191dee16 && cd .. @@ -61,7 +25,7 @@ WORKDIR /workspace/electra RUN pip install --no-cache-dir tqdm boto3 requests six ipdb h5py nltk progressbar filelock \ git+https://github.com/NVIDIA/dllogger \ - nvidia-ml-py3==7.352.0 + nvidia-ml-py3==7.352.0 tokenizers==0.11.0 RUN apt-get install -y iputils-ping COPY . . diff --git a/TensorFlow2/Recommendation/DLRM/README.md b/TensorFlow2/Recommendation/DLRM/README.md deleted file mode 100644 index 35d3e442f..000000000 --- a/TensorFlow2/Recommendation/DLRM/README.md +++ /dev/null @@ -1,999 +0,0 @@ -# DLRM For TensorFlow 2 - -This repository provides a script and recipe to train the Deep Learning Recommendation Model (DLRM) to achieve state-of-the-art accuracy is tested and maintained by NVIDIA. - -## Table Of Contents - - * [Model overview](#model-overview) - * [Model architecture](#model-architecture) - * [Default configuration](#default-configuration) - * [Feature support matrix](#feature-support-matrix) - * [Features](#features) - * [Mixed precision training](#mixed-precision-training) - * [Enabling mixed precision](#enabling-mixed-precision) - * [Enabling TF32](#enabling-tf32) - * [Hybrid-parallel training with Merlin Distributed Embeddings](#hybrid-parallel-training-with-merlin-distributed-embeddings) - * [Training very large embedding tables](#training-very-large-embedding-tables) - * [Multi-node training](#multi-node-training) - * [Preprocessing on GPU with Spark 3](#preprocessing-on-gpu-with-spark-3) - * [BYO dataset functionality overview](#byo-dataset-functionality-overview) - * [Glossary](#glossary) - * [Dataset feature specification](#dataset-feature-specification) - * [Data flow in NVIDIA Deep Learning Examples recommendation models](#data-flow-in-nvidia-deep-learning-examples-recommendation-models) - * [Example of dataset feature specification](#example-of-dataset-feature-specification) - * [BYO dataset functionality](#byo-dataset-functionality) - * [Setup](#setup) - * [Requirements](#requirements) - * [Quick Start Guide](#quick-start-guide) - * [Advanced](#advanced) - * [Scripts and sample code](#scripts-and-sample-code) - * [Parameters](#parameters) - * [Command-line options](#command-line-options) - * [Getting the data](#getting-the-data) - * [Dataset guidelines](#dataset-guidelines) - * [BYO dataset](#byo-dataset) - * [Channel definitions and requirements](#channel-definitions-and-requirements) - * [BYO dataset constraints for the model](#BYO-dataset-constraints-for-the-model) - * [Preprocess with Spark](#preprocess-with-spark) - * [Training process](#training-process) - * [Performance](#performance) - * [Benchmarking](#benchmarking) - * [Training performance benchmark](#training-performance-benchmark) - * [Inference performance benchmark](#inference-performance-benchmark) - * [Results](#results) - * [Training accuracy results](#training-accuracy-results) - * [Training accuracy: NVIDIA DGX A100 (8x A100 80GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-80gb) - * [Training accuracy: NVIDIA DGX-1 (8x V100 32GB)](#training-accuracy-nvidia-dgx-1-8x-v100-32gb) - * [Training accuracy: NVIDIA DGX-2 (16x V100 32GB)](#training-accuracy-nvidia-dgx-2-16x-v100-32gb) - * [Training stability test](#training-stability-test) - * [Training performance results](#training-performance-results) - * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-dgx-a100-8x-a100-80gb) - * [Training performance: NVIDIA DGX-1 (8x V100 32GB)](#training-performance-nvidia-dgx-1-8x-v100-32gb) - * [Training performance: NVIDIA DGX-2 (16x V100 32GB)](#training-performance-nvidia-dgx-2-16x-v100-32gb) - * [Inference performance results](#inference-performance-results) - * [Inference performance: NVIDIA DGX A100 (8x A100 80GB)](#inference-performance-nvidia-dgx-a100-8x-a100-80gb) - * [Inference performance: NVIDIA DGX1V-32GB (8x V100 32GB)](#inference-performance-nvidia-dgx1v-32gb-8x-v100-32gb) - * [Inference performance: NVIDIA DGX2 (16x V100 16GB)](#inference-performance-nvidia-dgx2-16x-v100-16gb) - * [Release notes](#release-notes) - * [Changelog](#changelog) - * [Known issues](#known-issues) - * [Horovod issues](#horovod-issues) - * [Checkpointing](#checkpointing) - - -## Model overview - -The Deep Learning Recommendation Model (DLRM) is a recommendation model designed to make use of both categorical and numerical inputs. -It was first described in [Deep Learning Recommendation Model for Personalization and Recommendation Systems](https://arxiv.org/abs/1906.00091). -This repository provides a reimplementation of the code-base provided originally [here](https://github.com/facebookresearch/dlrm). -The scripts enable you to train DLRM on the [Criteo Terabyte Dataset](https://labs.criteo.com/2013/12/download-terabyte-click-logs/). - -Using the scripts provided here, you can efficiently train models that are too large to fit into a single GPU. -This is because we use a hybrid-parallel approach, which combines model parallelism with data parallelism for -different parts of the neural network. -This is explained in details in the [next section](#hybrid-parallel-multi-gpu-with-all-2-all-communication). - -This model uses a slightly different preprocessing procedure than the one found in the original implementation. -Most importantly, we use a technique called frequency thresholding to demonstrate models of different size. -The smallest model can be trained on a single V100-32GB GPU, while the largest one needs 8xA100-80GB GPUs. -The table below summarizes the model sizes and frequency thresholds used in this repository: - -| Name | Frequency threshold | Number of parameters | Model size| -|:--------------|:---|:-------------|:-------------------| -| Small | 15| 4.2B | 15.6 GiB | -| Large | 3 | 22.8B | 84.9 GiB | -| Extra large | 0 | 113B | 421 GiB | - -You can find a detailed description of the preprocessing steps in the [Dataset guidelines](#dataset-guidelines) section. - -Using DLRM, you can train a high-quality general model for recommendations. - -This model is trained with mixed precision using Tensor Cores on Volta, Turing and NVIDIA Ampere GPU architectures. -Therefore, researchers can get results 2x faster than training without Tensor Cores while experiencing the -benefits of mixed precision training. This model is tested against each NGC monthly container -release to ensure consistent accuracy and performance over time. - - -### Model architecture - -DLRM accepts two types of features: categorical and numerical. For each categorical feature, an embedding table is used to provide dense representation to each unique value. The dense features enter the model and are transformed by a simple neural network referred to as "bottom MLP". - -This part of the network consists of a series -of linear layers with ReLU activations. The output of the bottom MLP and the embedding vectors are then fed into the "dot interaction" operation. The output of "dot interaction" is then concatenated with the features resulting from bottom MLP and fed into the "top MLP" which is a series of dense layers with activations. -The model outputs a single number which can be interpreted as a likelihood of a certain user clicking an ad. - -

- -
-Figure 1. The architecture of DLRM. -

- -### Default configuration - -The following features were implemented in this model: -- general - - static loss scaling for Tensor Cores (mixed precision) training - - hybrid-parallel multi-GPU training -- preprocessing - - dataset preprocessing using Spark 3 on GPUs - -### Feature support matrix - -The following features are supported by this model: - -| Feature | DLRM -|----------------------|-------------------------- -|Automatic mixed precision (AMP) | Yes -|XLA | Yes -|Hybrid-parallel training with Merlin Distributed Embeddings | Yes -|Preprocessing on GPU with Spark 3| Yes -|Multi-node training | Yes - -#### Features - -**Automatic Mixed Precision (AMP)** -Enables mixed precision training without any changes to the code-base by performing automatic graph rewrites and loss scaling controlled by an environmental variable. - -**XLA** - -The training script supports a `--xla` flag. It can be used to enable XLA JIT compilation. Currently, we use [XLA Lite](https://docs.nvidia.com/deeplearning/frameworks/tensorflow-user-guide/index.html#xla-lite). It delivers a steady 10-30% performance boost depending on your hardware platform, precision, and the number of GPUs. It is turned off by default. - -**Horovod** -Horovod is a distributed training framework for TensorFlow, Keras, PyTorch, and MXNet. The goal of Horovod is to make distributed deep learning fast and easy to use. For more information about how to get started with Horovod, see the Horovod [official repository](https://github.com/horovod/horovod). - -**Hybrid-parallel training with Merlin Distributed Embeddings** -Our model uses Merlin Distributed Embeddings to implement efficient multi-GPU training. -For details, see example sources in this repository or see the TensorFlow tutorial. -For the detailed description of our multi-GPU approach, visit this [section](#hybrid-parallel-training-with-merlin-distributed-embeddings). - -**Multi-node training** -This repository supports multinode training. For more information refer to the [multinode section](#multi-node-training) - - -### Mixed precision training - -Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in Volta, and following with both the Turing and Ampere architectures, significant training speedups are experienced by switching to mixed precision -- up to 3.4x overall speedup on the most arithmetically intense model architectures. Using mixed precision training requires two steps: -1. Porting the model to use the FP16 data type where appropriate. -2. Adding loss scaling to preserve small gradient values. - -The ability to train deep learning networks with lower precision was introduced in the Pascal architecture and first supported in [CUDA 8](https://devblogs.nvidia.com/parallelforall/tag/fp16/) in the NVIDIA Deep Learning SDK. - -For information about: -- How to train using mixed precision, see the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) documentation. -- Techniques used for mixed precision training, see the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. - -#### Enabling mixed precision - -Mixed precision training is turned off by default. To turn it on, issue the `--amp` flag to the `main.py` script. - - -#### Enabling TF32 - -TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on Volta GPUs. - -TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require high dynamic range for weights or activations. - -For more information, refer to the [TensorFloat-32 in the A100 GPU Accelerates AI Training, HPC up to 20x](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) blog post. - -TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by default. - - -### Hybrid-parallel training with Merlin Distributed Embeddings - -Many recommendation models contain very large embedding tables. As a result, the model is often too large to fit onto a single device. -This could be easily solved by training in a model-parallel way, using either the CPU or other GPUs as "memory donors". -However, this approach is suboptimal as the "memory donor" devices' compute is not utilized. -In this repository, we use the model-parallel approach for the Embedding Tables while employing a usual data parallel approach -for the more compute-intensive MLPs and Dot Interaction layer. This way, we can train models much larger than what would normally fit into -a single GPU while at the same time making the training faster by using multiple GPUs. We call this approach hybrid-parallel training. - -To implement this approach we use the [Merlin Distributed Embeddings](https://github.com/NVIDIA-Merlin/distributed-embeddings) library. -It provides a scalable model parallel wrapper called `distributed_embeddings.dist_model_parallel`. This wrapper automatically distributes embedding tables to multiple GPUs. -This way embeddings can be scaled beyond single GPU’s memory capacity without -complex code to handle cross-worker communication. - -Under the hood, Merlin Distributed Embeddings uses a -specific multi-GPU communication pattern called -[all-2-all](https://en.wikipedia.org/wiki/All-to-all_\(parallel_pattern\)) to transition from model-parallel to data-parallel -paradigm. In the [original DLRM whitepaper](https://arxiv.org/abs/1906.00091) this has been referred to as "butterfly shuffle". - -An example model using Hybrid Parallelism is shown in Figure 2. The compute intensive dense layers are run in data-parallel -mode. The smaller embedding tables are run model-parallel, such that each smaller table is placed entirely on a single device. -This is not suitable for larger tables that need more memory than can be provided by a single device. Therefore, -those large tables are split into multiple parts and each part is run on a different GPU. - -

- -
-Figure 2. Hybrid parallelism with Merlin Distributed Embeddings. -

- -In this repository we train models of three sizes: "small" (15.6 GiB), "large" (84.9 GiB) and "extra large" (421 GiB). -The "small" model can be trained on a single V100-32GB GPU. The "large" model needs at least 8xV100-32GB GPUs, -but each of the tables it uses can fit on a singleGPU. - -The "extra large" model, on the other hand, contains tables that do not fit into a singledevice, and will be automatically -split and stored across multiple GPUs by Merlin Distributed Embeddings. - -#### Training very large embedding tables - -We tested this approach by training a DLRM model on the Criteo Terabyte dataset with the frequency limiting option turned off (set to zero). -The weights of the resulting model take 421 GiB. The largest table weighs 140 GiB. -Here are the commands you can use to reproduce this: - -``` -# build and run the preprocessing container as in the Quick Start Guide -# then when preprocessing set the frequency limit to 0: -./prepare_dataset.sh DGX2 0 - -# build and run the training container same as in the Quick Start Guide -# then append options necessary for training very large embedding tables: -horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --amp --xla -``` - -When using this method on a DGX A100 with 8 A100-80GB GPUs and a large-enough dataset, it is possible to train a single embedding table of up to 600 GB. You can also use multi-node training (described below) to train even larger recommender systems. - -This mode was used to train the 421GiB "extra large" model in [the DGX A100-80G performance section](#training-performance-nvidia-dgx-a100-8x-a100-80gb). - -#### Multi-node training - -Multi-node training is supported. Depending on the exact interconnect hardware and model configuration, -you might experience only a modest speedup with multi-node. -Multi-node training can also be used to train larger models. -For example, to train a 1.68 TB variant of DLRM on multi-node, you can run: - -``` -cmd='numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/full_criteo_data --amp --xla\ ---embedding_dim 512 --bottom_mlp_dims 512,256,512' \ -srun_flags='--mpi=pmix' \ -cont=nvidia_dlrm_tf \ -mounts=/data/dlrm:/data/dlrm \ -sbatch -n 32 -N 4 -t 00:20:00 slurm_multinode.sh -``` - -### Preprocessing on GPU with Spark 3 - -Refer to the ["Preprocessing with Spark" section](#preprocess-with-spark) for a detailed description of the Spark 3 GPU functionality. - -### BYO dataset functionality overview - -This section describes how you can train the DeepLearningExamples RecSys models on your own datasets without changing -the model or data loader and with similar performance to the one published in each repository. -This can be achieved thanks to Dataset Feature Specification, which describes how the dataset, data loader and model -interact with each other during training, inference and evaluation. -Dataset Feature Specification has a consistent format across all recommendation models in NVIDIA’s DeepLearningExamples -repository, regardless of dataset file type and the data loader, -giving you the flexibility to train RecSys models on your own datasets. - -- [Glossary](#glossary) -- [Dataset Feature Specification](#dataset-feature-specification) -- [Data Flow in Recommendation Models in DeepLearning examples](#data-flow-in-nvidia-deep-learning-examples-recommendation-models) -- [Example of Dataset Feature Specification](#example-of-dataset-feature-specification) -- [BYO dataset functionality](#byo-dataset-functionality) - -#### Glossary - -The Dataset Feature Specification consists of three mandatory and one optional section: - -feature_spec provides a base of features that may be referenced in other sections, along with their metadata. - Format: dictionary (feature name) => (metadata name => metadata value)
- -source_spec provides information necessary to extract features from the files that store them. - Format: dictionary (mapping name) => (list of chunks)
- -* Mappings are used to represent different versions of the dataset (think: train/validation/test, k-fold splits). A mapping is a list of chunks.
-* Chunks are subsets of features that are grouped together for saving. For example, some formats may constrain data saved in one file to a single data type. In that case, each data type would correspond to at least one chunk. Another example where this might be used is to reduce file size and enable more parallel loading. Chunk description is a dictionary of three keys:
- * type provides information about the format in which the data is stored. Not all formats are supported by all models.
- * features is a list of features that are saved in a given chunk. Order of this list may matter: for some formats, it is crucial for assigning read data to the proper feature.
- * files is a list of paths to files where the data is saved. For Feature Specification in yaml format, these paths are assumed to be relative to the yaml file’s directory (basename). Order of this list matters: It is assumed that rows 1 to i appear in the first file, rows i+1 to j in the next one, etc.
- -channel_spec determines how features are used. It is a mapping (channel name) => (list of feature names). - -Channels are model specific magic constants. In general, data within a channel is processed using the same logic. Example channels: model output (labels), categorical ids, numerical inputs, user data, and item data. - -metadata is a catch-all, wildcard section: If there is some information about the saved dataset that does not fit into the other sections, you can store it here. - -#### Dataset feature specification - -Data flow can be described abstractly: -Input data consists of a list of rows. Each row has the same number of columns; each column represents a feature. -The columns are retrieved from the input files, loaded, aggregated into channels and supplied to the model/training script. - -FeatureSpec contains metadata to configure this process and can be divided into three parts: - -* Specification of how data is organized on disk (source_spec). It describes which feature (from feature_spec) is stored in which file and how files are organized on disk. - -* Specification of features (feature_spec). Describes a dictionary of features, where key is feature name and values are features’ characteristics such as dtype and other metadata (for example, cardinalities for categorical features) - -* Specification of model’s inputs and outputs (channel_spec). Describes a dictionary of model’s inputs where keys specify model channel’s names and values specify lists of features to be loaded into that channel. Model’s channels are groups of data streams to which common model logic is applied, for example categorical/continuous data, user/item ids. Required/available channels depend on the model - - -The FeatureSpec is a common form of description regardless of underlying dataset format, dataset data loader form and model. - - -#### Data flow in NVIDIA Deep Learning Examples recommendation models - -The typical data flow is as follows: -* S.0. Original dataset is downloaded to a specific folder. -* S.1. Original dataset is preprocessed into Intermediary Format. For each model, the preprocessing is done differently, using different tools. The Intermediary Format also varies (for example, for DLRM PyTorch, the Intermediary Format is a custom binary one.) -* S.2. The Preprocessing Step outputs Intermediary Format with dataset split into training and validation/testing parts along with the Dataset Feature Specification yaml file. Metadata in the preprocessing step is automatically calculated. -* S.3. Intermediary Format data together with Dataset Feature Specification are fed into training/evaluation scripts. Data loader reads Intermediary Format and feeds the data into the model according to the description in the Dataset Feature Specification. -* S.4. The model is trained and evaluated - - - -

- -
- -Fig.1. Data flow in Recommender models in NVIDIA Deep Learning Examples repository. Channels of the model are drawn in green. -

- - -#### Example of dataset feature specification - -As an example, let’s consider a Dataset Feature Specification for a small CSV dataset for some abstract model. - -```yaml -feature_spec: - user_gender: - dtype: torch.int8 - cardinality: 3 #M,F,Other - user_age: #treated as numeric value - dtype: torch.int8 - user_id: - dtype: torch.int32 - cardinality: 2655 - item_id: - dtype: torch.int32 - cardinality: 856 - label: - dtype: torch.float32 - -source_spec: - train: - - type: csv - features: - - user_gender - - user_age - files: - - train_data_0_0.csv - - train_data_0_1.csv - - type: csv - features: - - user_id - - item_id - - label - files: - - train_data_1.csv - test: - - type: csv - features: - - user_id - - item_id - - label - - user_gender - - user_age - - files: - - test_data.csv - -channel_spec: - numeric_inputs: - - user_age - categorical_user_inputs: - - user_gender - - user_id - categorical_item_inputs: - - item_id - label_ch: - - label -``` - - -The data contains five features: (user_gender, user_age, user_id, item_id, label). Their data types and necessary metadata are described in the feature specification section. - -In the source mapping section, two mappings are provided: one describes the layout of the training data, the other of the testing data. The layout for training data has been chosen arbitrarily to showcase the flexibility. -The train mapping consists of two chunks. The first one contains user_gender and user_age, saved as a CSV, and is further broken down into two files. For specifics of the layout, refer to the following example and consult the glossary. The second chunk contains the remaining columns and is saved in a single file. Notice that the order of columns is different in the second chunk - this is alright, as long as the order matches the order in that file (that is, columns in the .csv are also switched) - - -Let’s break down the train source mapping. The table contains example data color-paired to the files containing it. - -

- -

- - - -The channel spec describes how the data will be consumed. Four streams will be produced and available to the script/model. -The feature specification does not specify what happens further: names of these streams are only lookup constants defined by the model/script. -Based on this example, we can speculate that the model has three input channels: numeric_inputs, categorical_user_inputs, -categorical_item_inputs, and one output channel: label. -Feature names are internal to the FeatureSpec and can be freely modified. - - -#### BYO dataset functionality - -In order to train any Recommendation model in NVIDIA Deep Learning Examples one can follow one of three possible ways: -* One delivers already preprocessed dataset in the Intermediary Format supported by data loader used by the training script -(different models use different data loaders) together with FeatureSpec yaml file describing at least specification of dataset, features and model channels - -* One uses a transcoding script - -* One delivers dataset in non-preprocessed form and uses preprocessing scripts that are a part of the model repository. -In order to use already existing preprocessing scripts, the format of the dataset needs to match the one of the original datasets. -This way, the FeatureSpec file will be generated automatically, but the user will have the same preprocessing as in the original model repository. - -## Setup - -The following section lists the requirements for training DLRM. - -### Requirements - -This repository contains Dockerfile which extends the TensorFlow 2 NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: -- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -- [TensorFlow 2 21.02-py3](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow/tags) NGC container -- Supported GPUs: - - [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) - - [NVIDIA Turing architecture](https://www.nvidia.com/en-us/geforce/turing/) - - [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) - - -For more information about how to get started with NGC containers, see the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: -- [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) -- [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) -- [Running TensorFlow](https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/running.html#running) - -For those unable to use the TensorFlow NGC container, to set up the required environment or create your own container, see the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). - -## Quick Start Guide - -To train your model using mixed or TF32 precision with Tensor Cores or using FP32, perform the following steps using -the default parameters of DLRM on the Criteo Terabyte dataset. For the specifics concerning training and inference, -see the [Advanced](#advanced) section. - -1. Clone the repository. -``` -git clone https://github.com/NVIDIA/DeepLearningExamples -cd DeepLearningExamples/TensorFlow2/Recommendation/DLRM -``` - -2. Build a DLRM Docker container. -```bash -docker build -t nvidia_dlrm_tf . -docker build -t nvidia_dlrm_spark -f Dockerfile_spark . -``` - -3. Start an interactive session in the NGC container to run preprocessing. -The DLRM TensorFlow container can be launched with: -```bash -mkdir -p data -docker run --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data nvidia_dlrm_spark bash -``` - -4. Download and preprocess the dataset. - -You can download the data by following the instructions at: http://labs.criteo.com/2013/12/download-terabyte-click-logs/. - -When you have successfully downloaded the dataset, put it in the `/data/dlrm/criteo/` directory in the container (`$PWD/data/dlrm/criteo` in the host system). - -Here are a few examples of different preprocessing commands. For the details on how those scripts work and detailed description of all the parameters, consult the [preprocess with spark section](#preprocess-with-spark). - -```bash -cd preproc - -# to run on a DGX-2 with a frequency limit of 3 (will need 8xV100-32GB to fit the model in GPU memory) -./prepare_dataset.sh DGX2 3 - -# to run on a DGX-2 with a frequency limit of 15 (should fit on a single V100-32GB): -./prepare_dataset.sh DGX2 15 -# -# to run on CPU with a frequency limit of 15: -./prepare_dataset.sh CPU 15 - -# to run on DGX-2 with no frequency limit: -./prepare_dataset.sh DGX2 0 -``` - -5. Start training. - -First, start the Docker container: -```bash -docker run --cap-add SYS_NICE --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data nvidia_dlrm_tf bash -``` - -- single-GPU A100-80GB: -```bash -horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --amp --xla --save_checkpoint_path /data/dlrm/checkpoint/dlrm -``` - -- single-GPU V100-32GB: -```bash -horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --xla --save_checkpoint_path /data/dlrm/checkpoint/dlrm -``` - -- multi-GPU for DGX A100 (model size 90GiB or 421GiB depending on the dataset passed) -```bash -horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --amp --xla --save_checkpoint_path /data/dlrm/checkpoint/dlrm -``` - -- multi-GPU for DGX2 (model size 90GiB): -```bash -horovodrun -np 16 -H localhost:16 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --amp --xla --column_slice_threshold 5000000000 --save_checkpoint_path /data/dlrm/checkpoint/dlrm -``` - -- multi-GPU for DGX1V-32GB (model size 90GiB): -```bash -horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --amp --xla --column_slice_threshold 5000000000 --save_checkpoint_path /data/dlrm/checkpoint/dlrm -``` - -6. Start evaluation. - -To evaluate a previously trained checkpoint, append `--restore_checkpoint_path --mode eval` to the command used for training. For example, to test a checkpoint trained on 8xA100 80GB, run: - -```bash -horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --amp --xla --restore_checkpoint_path /data/dlrm/checkpoint/dlrm --mode eval -``` - -## Advanced - -The following sections provide greater details of the dataset, running training and inference, and the training results. - -### Scripts and sample code - -These are the important modules in this repository: -- `main.py` - The main entrypoint script for training, evaluating, and benchmarking. -- `model.py` - Defines the DLRM model and some auxiliary functions used to train it. -- `dataloader.py` - Handles defining the dataset objects based on command-line flags. -- `datasets.py` - Defines the `TfRawBinaryDataset` class responsible for storing and loading the training data. -- `slurm_multinode.sh` - Example batch script for multi-node training on SLURM clusters. -- `lr_scheduler.py` - Defines a TensorFlow learning rate scheduler that supports both learning rate warmup and polynomial decay. -- `embedding.py` - Implementations of the embedding layers. -- `interaction.py` - Implementation of the dot-interaction layer using TensorFlow operations. -- `tensorflow-dot-based-interact` - A directory with a set of custom CUDA kernels. They provide fast implementations of the dot-interaction operation for various precisions and hardware platforms. -- `utils.py` - General utilities, such as a timer used for taking performance measurements. - - - -### Parameters - -The table below lists the most important command-line parameters of the `main.py` script. - -| Scope| parameter| Comment| Default Value | -| ----- | --- | ---- | ---- | -|datasets|dataset_path|Path to the JSON file with the sizes of embedding tables| -|function|mode| Choose "train" to train the model, "inference" to benchmark inference and "eval" to run validation| train| -|optimizations|amp| Enable automatic mixed precision| False -|optimizations|xla| Enable XLA| False| -|hyperparameters|batch_size| Batch size used for training|65536| -|hyperparameters|epochs| Number of epochs to train for|1| -|hyperparameters|optimizer| Optimization algorithm for training |SGD| -|hyperparameters|evals_per_epoch| Number of evaluations per epoch|1| -|hyperparameters|valid_batch_size| Batch size used for validation|65536| -|hyperparameters|max_steps| Stop the training/inference after this many optimization steps|-1| -|checkpointing|restore_checkpoint_path| Path from which to restore a checkpoint before training|None| -|checkpointing|save_checkpoint_path| Path to which to save a checkpoint file at the end of the training|None| -|debugging|run_eagerly| Disable all tf.function decorators for debugging|False| -|debugging|print_freq| Number of steps between debug prints|1000| - - -### Command-line options - -The `main.py` script supports a number of command-line flags. You can get the descriptions of those by running `python main.py --help`. - -### Getting the data - -This example uses the [Criteo Terabyte Dataset](https://labs.criteo.com/2013/12/download-terabyte-click-logs/). -The first 23 days are used as the training set. The last day is split in half. The first part is used as a validation set and the second set is used as a hold-out test set. - - -#### Dataset guidelines - -The preprocessing steps applied to the raw data include: -- Replacing the missing values with `0`. -- Replacing the categorical values that exist fewer than 15 times with a special value. -- Converting the hash values to consecutive integers. -- Adding 2 to all the numerical features so that all of them are greater or equal to 1. -- Taking a natural logarithm of all numerical features. - -#### BYO dataset - -This implementation supports using other datasets thanks to BYO dataset functionality. -The BYO dataset functionality allows users to plug in their dataset in a common fashion for all Recommender models -that support this functionality. Using BYO dataset functionality, the user does not have to modify the source code of -the model thanks to the Feature Specification file. For general information on how BYO dataset works, refer to the -[BYO dataset overview section](#byo-dataset-functionality-overview). - -There are three ways to plug in user's dataset: -
-1. Provide an unprocessed dataset in a format matching the one used by Criteo 1TB, then use Criteo 1TB's preprocessing. Feature Specification file is then generated automatically. -The required format of the user's dataset is: - -The data should be split into text files. Each line of those text files should contain a single training example. -An example should consist of multiple fields separated by tabulators: - -* The first field is the label – 1 for a positive example and 0 for negative. -* The next N tokens should contain the numerical features separated by tabs. -* The next M tokens should contain the hashed categorical features separated by tabs. - -The correct dataset files together with the Feature Specification yaml file will be generated automatically by preprocessing script. - -For an example of using this process, refer to the [Quick Start Guide](#quick-start-guide) - -
- -
-2. Provide a CSV containing preprocessed data and a simplified Feature Specification yaml file, then transcode the data with `transcode.py` script -This option should be used if the user has their own CSV file with a preprocessed dataset they want to train on. - -The required format of the user's dataset is: -* CSV files containing the data, already split into train and test sets. -* Feature Specification yaml file describing the layout of the CSV data - -For an example of a feature specification file, refer to the `tests/transcoding` folder. - -The CSV containing the data: -* should be already split into train and test -* should contain no header -* should contain one column per feature, in the order specified by the list of features for that chunk - in the source_spec section of the feature specification file -* categorical features should be non-negative integers in the range [0,cardinality-1] if cardinality is specified - -The Feature Specification yaml file: -* needs to describe the layout of data in CSV files -* may contain information about cardinalities. However, if set to `auto`, they will be inferred from the data by the transcoding script. - -Refer to `tests/transcoding/small_csv.yaml` for an example of the yaml Feature Specification. - -The following example shows how to use this way of plugging user's dataset: - -Prepare your data and save the path: -```bash -DATASET_PARENT_DIRECTORY=/raid/dlrm -``` - -Build the DLRM image with: -```bash -docker build -t nvidia_dlrm_tf . -``` -Launch the container with: -```bash -docker run --cap-add SYS_NICE --runtime=nvidia -it --rm --ipc=host -v ${DATASET_PARENT_DIRECTORY}/data:/data nvidia_dlrm_tf bash -``` - -If you are just testing the process, you can create synthetic csv data: -```bash -python gen_csv.py --feature_spec_in tests/transcoding/small_csv.yaml -``` - -Convert the data: -```bash -mkdir /data/conversion_output -cp tests/transcoding/small_csv.yaml /data/feature_spec.yaml -python transcode.py --input /data --output /data/converted -``` -You may need to tune the --chunk_size parameter. Higher values speed up the conversion but require more RAM. - -This will convert the data from `/data` and save the output in `/data/converted`. -A feature specification file describing the new data will be automatically generated. - -To run the training on 1 GPU: -```bash -horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla -``` - -- multi-GPU for DGX A100: -```bash -horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla -``` - -- multi-GPU for DGX-1 and DGX-2: -```bash -horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla -``` -
-
-3. Provide a fully preprocessed dataset, saved in split binary files, and a Feature Specification yaml file -This is the option to choose if you want full control over preprocessing and/or want to preprocess data directly to the target format. - -Your final output will need to contain a Feature Specification yaml describing data and file layout. -For an example feature specification file, refer to `tests/feature_specs/criteo_f15.yaml` - -For details, refer to the [BYO dataset overview section](#byo-dataset-functionality-overview). -
- - - -##### Channel definitions and requirements - -This model defines three channels: - -- categorical, accepting an arbitrary number of features -- numerical, accepting an arbitrary number of features -- label, accepting a single feature - - -The training script expects two mappings: - -- train -- test - -For performance reasons: -* The only supported dataset type is split binary -* Splitting chunks into multiple files is not supported. -* Each categorical feature has to be provided in a separate chunk -* All numerical features have to be provided in a single chunk -* All numerical features have to appear in the same order in channel_spec and source_spec -* Only integer types are supported for categorical features -* Only float16 is supported for numerical features - -##### BYO dataset constraints for the model - -There are the following constraints of BYO dataset functionality for this model: -1. The performance of the model depends on the dataset size. Generally, the model should scale better for datasets containing more data points. For a smaller dataset, you might experience slower performance than the one reported for Criteo -2. Using other datasets might require tuning some hyperparameters (for example, learning rate, beta1 and beta2) to reach desired accuracy. -3. The optimized cuda interaction kernels for FP16 and TF32 assume that the number of categorical variables is smaller than WARP_SIZE=32 and embedding size is <=128 - - -#### Preprocess with Spark - -The preprocessing scripts provided in this repository support running both on CPU and on DGX-2 using [Apache Spark 3.0](https://www.nvidia.com/en-us/deep-learning-ai/solutions/data-science/apache-spark-3/). -It should be possible to change the values in `preproc/dgx2_config.sh` -so that they'll work on other hardware platforms such as DGX-1. - -Note that the preprocessing will require about 4TB of disk storage. - -The syntax for the preprocessing script is as follows: -```bash -cd preproc -./prepare_dataset.sh -``` - -The first argument is the hardware platform to use (either DGX-2 or pure-CPU). The second argument means the frequency -threshold to apply to the categorical variables. For a frequency threshold `T`, the categorical values that occur less -often than `T` will be replaced with a special embedding. Thus, a larger value of `T` will require smaller embedding tables -and will substantially reduce the overall size of the model. - -For the Criteo Terabyte dataset we recommend a frequency threshold of `T=3` if you intend to run the hybrid-parallel mode -on multiple GPUs. If you want to make the model fit into a single NVIDIA Tesla V100-32GB, you can set `T=15`. - -The preprocessing scripts makes use of the following environment variables to configure the data directory paths: -- `download_dir` – this directory should contain the original Criteo Terabyte CSV files -- `spark_output_path` – directory to which the parquet data will be written -- `conversion_intermediate_dir` – directory used for storing intermediate data used to convert from parquet to train-ready format -- `final_output_dir` – directory to store the final results of the preprocessing which can then be used to train DLRM - -The script `spark_data_utils.py` is a PySpark application, which is used to preprocess the Criteo Terabyte Dataset. In the Docker image, we have installed Spark 3.0.1, which will start a standalone cluster of Spark. The scripts `run_spark_cpu.sh` and `run_spark_gpu.sh` start Spark, then runs several PySpark jobs with `spark_data_utils.py`, for example: -generates the dictionary -- transforms the train dataset -- transforms the test dataset -- transforms the validation dataset - - Change the variables in the `run-spark.sh` script according to your environment. - Configure the paths. -``` -export SPARK_LOCAL_DIRS=/data/spark-tmp -export INPUT_PATH=/data/criteo -export OUTPUT_PATH=/data/output -``` -Note that the Spark job requires about 3TB disk space used for data shuffle. - -Where: -`SPARK_LOCAL_DIRS` is the path where Spark uses to write shuffle data. -`INPUT_PATH` is the path of the Criteo Terabyte Dataset, including uncompressed files like day_0, day_1… -`OUTPUT_PATH` is where the script writes the output data. It will generate the following subdirectories of `models`, `train`, `test`, and `validation`. -- The `model` is the dictionary folder. -- The `train` is the train dataset transformed from day_0 to day_22. -- The `test` is the test dataset transformed from the prior half of day_23. -- The `validation` is the dataset transformed from the latter half of day_23. - -Configure the resources which Spark will use. -``` -export TOTAL_CORES=80 -export TOTAL_MEMORY=800 -``` - -Where: -`TOTAL_CORES` is the total CPU cores you want Spark to use. - -`TOTAL_MEMORY` is the total memory Spark will use. - -Configure frequency limit. -``` -USE_FREQUENCY_LIMIT=15 -``` -The frequency limit is used to filter out the categorical values which appear less than n times in the whole dataset, and make them be 0. Change this variable to 1 to enable it. The default frequency limit is 15 in the script. You also can change the number as you want by changing the line of `OPTS="--frequency_limit 8"`. - - -### Training process - -The main training script resides in `main.py`. The speed of training is measured by throughput i.e., the number -of samples processed per second. We use mixed precision training with static loss scaling for the bottom and top MLPs while embedding tables are stored in FP32 format. - -## Performance - -The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to [NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). - -### Benchmarking - -The following section shows how to run benchmarks measuring the model performance in training and inference modes. - -#### Training performance benchmark - -To benchmark the training performance on a specific batch size, follow the instructions -in the [Quick Start Guide](#quick-start-guide). You can also add the `--max_steps 1000` -if you want to get a reliable throughput measurement without running the entire training. - -You can also use synthetic data by running with the `--dataset_type synthetic` option if you haven't downloaded the dataset yet. - -#### Inference performance benchmark - -To benchmark the inference performance on a specific batch size, run: - -``` -horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/dlrm/ --amp --restore_checkpoint_path --mode inference -``` - -### Results - -The following sections provide details on how we achieved our performance and accuracy in training and inference. - -We used three model size variants to show memory scalability in multi-GPU setup: - -| Name | Dataset | Number of parameters | Model size | -|:-----|:--------|:---------------------|:------| -| small | Criteo 1TB, FL=15| 4.2B | 15.6 GiB | -| large | Criteo 1TB, FL=3 | 22.8B | 84.9 GiB | -| extra large | Criteo 1TB, FL=0 | 113B | 421 GiB | - -#### Training accuracy results - - -##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) - -Our results were obtained by running training scripts as described in the Quick Start Guide in the DLRM Docker container. - -| GPUs | Model size | Batch size / GPU | Accuracy (AUC) - TF32 | Accuracy (AUC) - mixed precision | Time to train - TF32 [minutes] | Time to train - mixed precision [minutes] | Time to train speedup (TF32 to mixed precision) | -|:-------|:-------------|:-------------------|:------------------------|:-----------------------------------|:---------------------------------|:--------------------------------------------|:--------------------------------------------------| -| 1 | small | 64k | 0.8025 | 0.8025 | 26.75 | 16.27 | 1.64 | -| 8 | large | 8k | 0.8027 | 0.8026 | 8.77 | 6.57 | 1.33 | -| 8 | extra large | 8k | 0.8026 | 0.8026 | 10.47 | 9.08 | 1.15 | - -##### Training accuracy: NVIDIA DGX-1 (8x V100 32GB) - -Our results were obtained by running training scripts as described in the Quick Start Guide in the DLRM Docker container. - -| GPUs | Model size | Batch size / GPU | Accuracy (AUC) - FP32 | Accuracy (AUC) - mixed precision | Time to train - FP32 [minutes] | Time to train - mixed precision [minutes] | Time to train speedup (FP32 to mixed precision) | -|:-------|:-------------|:-------------------|:------------------------|:-----------------------------------|:---------------------------------|:--------------------------------------------|:--------------------------------------------------| -| 1 | small | 64k | 0.8027 | 0.8025 | 109.63 | 34.83 | 3.15 | -| 8 | large | 8k | 0.8028 | 0.8026 | 26.01 | 13.73 | 1.89 | -##### Training accuracy: NVIDIA DGX-2 (16x V100 32GB) - -Our results were obtained by running training scripts as described in the Quick Start Guide in the DLRM Docker container. - -| GPUs | Model size | Batch size / GPU | Accuracy (AUC) - FP32 | Accuracy (AUC) - mixed precision | Time to train - FP32 [minutes] | Time to train - mixed precision [minutes] | Time to train speedup (FP32 to mixed precision) | -|:-------|:-------------|:-------------------|:------------------------|:-----------------------------------|:---------------------------------|:--------------------------------------------|:--------------------------------------------------| -| 1 | small | 64k | 0.8026 | 0.8026 | 105.13 | 33.37 | 3.15 | -| 8 | large | 8k | 0.8027 | 0.8027 | 21.21 | 11.43 | 1.86 | -| 16 | large | 4k | 0.8025 | 0.8026 | 15.52 | 10.88 | 1.43 | - -##### Training stability test - -The histograms below show the distribution of ROC AUC results achieved at the end of the training for each precision/hardware platform tested. There are no statistically significant differences between precision, number of GPUs or hardware platform. Using the larger dataset has a modest, positive impact on final AUC score. - - -

- -
-Figure 4. Results of stability tests for DLRM. -

- - -#### Training performance results - - -We used throughput in items processed per second as the performance metric. - - -##### Training performance: NVIDIA DGX A100 (8x A100 80GB) - -Our results were obtained by following the commands from the Quick Start Guide -in the DLRM Docker container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in items per second) were averaged over 1000 training steps. - -| GPUs | Model size | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 to mixed precision) | -|:-------|:-------------|:-------------------|:--------------------|:-------------------------------|:-----------------------------------------------| -| 1 | small | 64k | 2.68M | 4.47M | 1.67 | -| 8 | large | 8k | 9.39M | 13.31M | 1.42 | -| 8 | extra large | 8k | 9.93M | 12.1M | 1.22 - -To achieve these results, follow the steps in the [Quick Start Guide](#quick-start-guide). - -##### Training performance: comparison with CPU for the "extra large" model - -For the "extra large" model (113B parameters) we also obtained CPU results for comparison using the same source code -(using the `--cpu` command line flag for the CPU-only experiments). - -We compare three hardware setups: -- CPU only, -- a single GPU that uses CPU memory for the largest embedding tables, -- Hybrid-Parallel using the full DGX A100-80GB - -| Hardware | Throughput [samples / second]| Speedup over CPU| -|:---|:---|:---| -2xAMD EPYC 7742 | 17.7k | 1x | -1xA100-80GB + 2xAMD EPYC 7742 (large embeddings on CPU) | 768k |43x | -DGX A100 (8xA100-80GB) (hybrid parallel) | 12.1M | 683x | - - -##### Training performance: NVIDIA DGX-1 (8x V100 32GB) - -| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 to mixed precision) | -|:-------|:-------------|:-------------------|:--------------------|:-------------------------------|:-----------------------------------------------| -| 1 | small | 64k | 0.648M | 2.06M | 3.18 | -| 8 | large | 8k | 2.9M | 5.89M | 2.03 | - -To achieve the same results, follow the steps in the [Quick Start Guide](#quick-start-guide). - - -##### Training performance: NVIDIA DGX-2 (16x V100 32GB) - -| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 to mixed precision) | -|:-------|:-------------|:-------------------|:--------------------|:-------------------------------|:-----------------------------------------------| -| 1 | small | 64k | 0.675M | 2.16M | 3.2 | -| 8 | large | 8k | 3.75M | 7.72M | 2.06 | -| 16 | large | 4k | 5.74M | 9.39M | 1.64 | - - -To achieve the same results, follow the steps in the [Quick Start Guide](#quick-start-guide). - -#### Inference performance results - -##### Inference performance: NVIDIA DGX A100 (8x A100 80GB) - -| GPUs | Model size | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Average latency - TF32 [ms] | Average latency - mixed precision [ms] | Throughput speedup (mixed precision to TF32) | -|-------:|:-------------|-------------------:|:--------------------|:-------------------------------|------------------------------:|-----------------------------------------:|-----------------------------------------------:| -| 1 | small | 2048 | 1.43M | 1.54M | 1.48 | 1.33 | 1.08 | - - -##### Inference performance: NVIDIA DGX1V-32GB (8x V100 32GB) - -| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Average latency - FP32 [ms] | Average latency - mixed precision [ms] | Throughput speedup (mixed precision to FP32) | -|-------:|:-------------|-------------------:|:--------------------|:-------------------------------|------------------------------:|-----------------------------------------:|-----------------------------------------------:| -| 1 | small | 2048 | 0.765M | 1.05M | 2.90 | 1.95 | 1.37 | - -##### Inference performance: NVIDIA DGX2 (16x V100 16GB) - -| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Average latency - FP32 [ms] | Average latency - mixed precision [ms] | Throughput speedup (mixed precision to FP32) | -|-------:|:-------------|-------------------:|:--------------------|:-------------------------------|------------------------------:|-----------------------------------------:|-----------------------------------------------:| -| 1 | small | 2048 | 1.03M | 1.37M | 2.10 | 1.63 | 1.53 | - - -## Release notes -We’re constantly refining and improving our performance on AI and HPC workloads even on the same hardware with frequent updates to our software stack. For our latest performance data please refer to these pages for [AI](https://developer.nvidia.com/deep-learning-performance-training-inference) and [HPC](https://developer.nvidia.com/hpc-application-performance) benchmarks. - -### Changelog -July 2022 -- Start using Merlin Distributed Embeddings - -March 2022 -- Major performance improvements -- Support for BYO dataset - -March 2021 -- Initial release - -### Known issues - -#### Checkpointing -TensorFlow runs into issues when trying to save model checkpoints for extremely large variables. -We circumvent this by using a custom checkpoint format that splits the variables into pieces and stores each piece independently. -However, this custom format cannot be used by the standard inference deployment frameworks such as ONNX. - -#### Inference performance -Current inference performance was evaluated in python using TensorFlow 2.9.1. -This provides ease of use and flexibility but is suboptimal in terms of performance. -If you're interested in state-of-the-art performance for recommender system inference, -please review our results in [the MLPerf v0.7 benchmark](https://mlperf.org/inference-results/) -where we used [TensorRT](https://developer.nvidia.com/tensorrt). -You might also want to check [the source code of our MLPerf Inference submission](https://github.com/mlcommons/inference_results_v0.7/tree/master/closed/NVIDIA/code/dlrm/tensorrt). - diff --git a/TensorFlow2/Recommendation/DLRM/dataloader.py b/TensorFlow2/Recommendation/DLRM/dataloader.py deleted file mode 100644 index 87ce3f611..000000000 --- a/TensorFlow2/Recommendation/DLRM/dataloader.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# author: Tomasz Grel (tgrel@nvidia.com), Tomasz Cheda (tcheda@nvidia.com) - -import os -import horovod.tensorflow as hvd - -from defaults import TRAIN_MAPPING, TEST_MAPPING -from feature_spec import FeatureSpec -from datasets import TfRawBinaryDataset, DummyDataset, DatasetMetadata - - -def get_dataset_metadata(flags): - if flags.dataset_type == 'synthetic' and not flags.synthetic_dataset_use_feature_spec: - cardinalities = [int(d) for d in flags.synthetic_dataset_cardinalities] - feature_spec = FeatureSpec.get_default_feature_spec( - number_of_numerical_features=flags.synthetic_dataset_num_numerical_features, - categorical_feature_cardinalities=cardinalities) - else: # synthetic based on feature spec, or raw - fspec_path = os.path.join(flags.dataset_path, flags.feature_spec) - feature_spec = FeatureSpec.from_yaml(fspec_path) - - dataset_metadata = DatasetMetadata(num_numerical_features=feature_spec.get_number_of_numerical_features(), - categorical_cardinalities=feature_spec.get_categorical_sizes()) - return dataset_metadata - - -def create_input_pipelines(flags, table_ids): - if flags.dataset_type == 'synthetic' and not flags.synthetic_dataset_use_feature_spec: - cardinalities = [int(d) for d in flags.synthetic_dataset_cardinalities] - feature_spec = FeatureSpec.get_default_feature_spec( - number_of_numerical_features=flags.synthetic_dataset_num_numerical_features, - categorical_feature_cardinalities=cardinalities) - else: # synthetic based on feature spec, or raw - fspec_path = os.path.join(flags.dataset_path, flags.feature_spec) - feature_spec = FeatureSpec.from_yaml(fspec_path) - - dataset_metadata = DatasetMetadata(num_numerical_features=feature_spec.get_number_of_numerical_features(), - categorical_cardinalities=feature_spec.get_categorical_sizes()) - - if flags.dataset_type == 'synthetic': - local_table_sizes = [dataset_metadata.categorical_cardinalities[i] for i in table_ids] - train_dataset = DummyDataset(batch_size=flags.batch_size, - num_numerical_features=dataset_metadata.num_numerical_features, - categorical_feature_cardinalities=local_table_sizes, - num_batches=flags.synthetic_dataset_train_batches, - num_workers=hvd.size()) - - test_dataset = DummyDataset(batch_size=flags.batch_size, - num_numerical_features=dataset_metadata.num_numerical_features, - categorical_feature_cardinalities=local_table_sizes, - num_batches=flags.synthetic_dataset_valid_batches, - num_workers=hvd.size()) - - elif flags.dataset_type == 'tf_raw': - local_categorical_feature_names = feature_spec.cat_positions_to_names(table_ids) - train_dataset = TfRawBinaryDataset(feature_spec=feature_spec, - instance=TRAIN_MAPPING, - batch_size=flags.batch_size, - numerical_features_enabled=True, - local_categorical_feature_names=local_categorical_feature_names, - rank=hvd.rank(), - world_size=hvd.size()) - - test_dataset = TfRawBinaryDataset(feature_spec=feature_spec, - instance=TEST_MAPPING, - batch_size=flags.batch_size, - numerical_features_enabled=True, - local_categorical_feature_names=local_categorical_feature_names, - rank = hvd.rank(), - world_size = hvd.size()) - - else: - raise ValueError(f'Unsupported dataset type: {flags.dataset_type}') - - return train_dataset, test_dataset diff --git a/TensorFlow2/Recommendation/DLRM/interaction.py b/TensorFlow2/Recommendation/DLRM/interaction.py deleted file mode 100644 index 4714c70cd..000000000 --- a/TensorFlow2/Recommendation/DLRM/interaction.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2020 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the 'License'); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an 'AS IS' BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -# -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - - -import tensorflow as tf - - -def dot_interact(concat_features, bottom_mlp_out=None, skip_gather=False): - # Interact features, select lower-triangular portion, and re-shape. - interactions = tf.matmul(concat_features, concat_features, transpose_b=True) - - ones = tf.ones_like(interactions, dtype=tf.float32) - upper_tri_mask = tf.linalg.band_part(ones, 0, -1) - - feature_dim = tf.shape(interactions)[-1] - - if skip_gather: - upper_tri_bool = tf.cast(upper_tri_mask, tf.bool) - activations = tf.where( - condition=upper_tri_bool, x=tf.zeros_like(interactions), y=interactions) - out_dim = feature_dim * feature_dim - else: - lower_tri_mask = ones - upper_tri_mask - activations = tf.boolean_mask(interactions, lower_tri_mask) - out_dim = feature_dim * (feature_dim - 1) // 2 - - activations = tf.reshape(activations, shape=[-1, out_dim]) - - if bottom_mlp_out is not None: - bottom_mlp_out = tf.squeeze(bottom_mlp_out) - activations = tf.concat([activations, bottom_mlp_out], axis=1) - - return activations - - -def dummy_dot_interact(concat_features, bottom_mlp_out=None): - batch_size = tf.shape(concat_features)[0] - num_features = tf.shape(concat_features)[1] - concat_features = tf.math.reduce_mean(concat_features, axis=[2], keepdims=True) - return dot_interact(concat_features, bottom_mlp_out) diff --git a/TensorFlow2/Recommendation/DLRM/model.py b/TensorFlow2/Recommendation/DLRM/model.py deleted file mode 100644 index 24f454ae3..000000000 --- a/TensorFlow2/Recommendation/DLRM/model.py +++ /dev/null @@ -1,543 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# author: Tomasz Grel (tgrel@nvidia.com) - -import tensorflow as tf -from embedding import DualEmbeddingGroup, EmbeddingInitializer -from distributed_embeddings.python.layers import embedding -import interaction -import tensorflow.keras.initializers as initializers -import math -import horovod.tensorflow as hvd -import numpy as np -import time -import os -from utils import dist_print, get_variable_path -from tensorflow.python.keras.saving.saving_utils import model_input_signature -from collections import OrderedDict -from distributed_embeddings.python.layers import dist_model_parallel as dmp - -try: - from tensorflow_dot_based_interact.python.ops import dot_based_interact_ops -except ImportError: - print('WARNING: Could not import the custom dot-interaction kernels') - -# wrap metric computations in tf.function -@tf.function -def update_auc_metric(auc_metric, labels, y_pred): - auc_metric.update_state(labels, y_pred) - -@tf.function -def compute_bce_loss(bce_op, labels, y_pred): - return bce_op(labels, y_pred) - -def scale_grad(grad, factor): - if isinstance(grad, tf.IndexedSlices): - # sparse gradient - grad._values = grad._values * factor - return grad - else: - # dense gradient - return grad * factor - -def _create_inputs_dict(numerical_features, categorical_features): - # Passing inputs as (numerical_features, categorical_features) changes the model - # input signature to (). - # This leads to errors while loading the saved model. - # TF flattens the inputs while loading the model, - # so the inputs are converted from () -> [list of tensors] - # see _set_inputs function in training_v1.py: - # https://github.com/tensorflow/tensorflow/blob/7628750678786f1b65e8905fb9406d8fbffef0db/tensorflow/python/keras/engine/training_v1.py#L2588) - inputs = OrderedDict() - inputs['numerical_features'] = numerical_features - inputs['categorical_features'] = categorical_features - return inputs - - -class DlrmTrainer: - def __init__(self, dlrm, embedding_optimizer, mlp_optimizer, amp, lr_scheduler, pipe, cpu): - self.dlrm = dlrm - self.embedding_optimizer = embedding_optimizer - self.mlp_optimizer = mlp_optimizer - self.amp = amp - self.lr_scheduler = lr_scheduler - self.bce = tf.keras.losses.BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE, - from_logits=True) - self.cpu = cpu - self.pipe = iter(pipe.op()) - - @tf.function - def train_step(self): - device = '/CPU:0' if self.cpu else '/GPU:0' - with tf.device(device): - self.lr_scheduler() - with tf.name_scope("dataloading"): - (numerical_features, categorical_features), labels = self.pipe.get_next() - - inputs = _create_inputs_dict(numerical_features, categorical_features) - with tf.GradientTape() as tape: - predictions = self.dlrm(inputs=inputs, training=True) - unscaled_loss = self.bce(labels, predictions) - # tf keras doesn't reduce the loss when using a Custom Training Loop - unscaled_loss = tf.math.reduce_mean(unscaled_loss) - scaled_loss = self.mlp_optimizer.get_scaled_loss(unscaled_loss) if self.amp else unscaled_loss - - if hvd.size() > 1: - tape = dmp.DistributedGradientTape(tape) - gradients = tape.gradient(scaled_loss, self.dlrm.trainable_variables) - - if self.amp: - gradients = self.mlp_optimizer.get_unscaled_gradients(gradients) - - self.mlp_optimizer.apply_gradients(zip(gradients, self.dlrm.trainable_variables)) - if hvd.size() > 1: - # compute mean loss for all workers for reporting - mean_loss = hvd.allreduce(unscaled_loss, name="mean_loss", op=hvd.Average) - else: - mean_loss = unscaled_loss - - return mean_loss - - -def evaluate(validation_pipeline, dlrm, timer, auc_thresholds, max_steps=None, cast_dtype=None): - - auc, test_loss = 0, 0 - latencies, all_test_losses = [], [] - distributed = hvd.size() != 1 - - pipe = iter(validation_pipeline.op()) - - auc_metric = tf.keras.metrics.AUC(num_thresholds=auc_thresholds, - curve='ROC', summation_method='interpolation', - from_logits=True) - bce_op = tf.keras.losses.BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE, - from_logits=True) - for eval_step in range(len(validation_pipeline)): - begin = time.time() - - (numerical_features, categorical_features), labels = pipe.get_next() - - if cast_dtype is not None: - numerical_features = tf.cast(numerical_features, cast_dtype) - - if max_steps is not None and eval_step >= max_steps: - break - - inputs = _create_inputs_dict(numerical_features, categorical_features) - y_pred = dlrm(inputs, sigmoid=False, training=False) - end = time.time() - latency = end - begin - latencies.append(latency) - - if distributed: - y_pred = hvd.allgather(y_pred) - labels = hvd.allgather(labels) - - timer.step_test() - if hvd.rank() == 0 and auc_metric is not None: - update_auc_metric(auc_metric, labels, y_pred) - test_loss = compute_bce_loss(bce_op, labels, y_pred) - all_test_losses.append(test_loss) - - if hvd.rank() == 0 and dlrm.auc_metric is not None: - auc = auc_metric.result().numpy().item() - test_loss = tf.reduce_mean(all_test_losses).numpy().item() - - auc_metric.reset_state() - return auc, test_loss, latencies - - -class Dlrm(tf.keras.Model): - def __init__(self, FLAGS, dataset_metadata): - super(Dlrm, self).__init__() - - self.global_table_sizes = dataset_metadata.categorical_cardinalities - - self.distributed = hvd.size() > 1 - self.batch_size = FLAGS.batch_size - self.num_all_categorical_features = len(dataset_metadata.categorical_cardinalities) - - self.amp = FLAGS.amp - self.fp16 = FLAGS.fp16 - - self.use_merlin_de_embeddings = FLAGS.use_merlin_de_embeddings - - self.dataset_metadata = dataset_metadata - - self.embedding_dim = FLAGS.embedding_dim - self.column_slice_threshold = FLAGS.column_slice_threshold - - self.dot_interaction = FLAGS.dot_interaction - if FLAGS.dot_interaction == 'custom_cuda': - self.interact_op = dot_based_interact_ops.dot_based_interact - elif FLAGS.dot_interaction == 'tensorflow': - self.interact_op = interaction.dot_interact - elif FLAGS.dot_interaction == 'dummy': - self.interact_op = interaction.dummy_dot_interact - else: - raise ValueError(f'Unknown dot-interaction implementation {FLAGS.dot_interaction}') - - self.embedding_trainable = FLAGS.embedding_trainable - - self.bottom_mlp_dims = [int(d) for d in FLAGS.bottom_mlp_dims] - self.top_mlp_dims = [int(d) for d in FLAGS.top_mlp_dims] - - self.num_numerical_features = dataset_metadata.num_numerical_features - - self._create_bottom_mlp() - self._create_embeddings() - - self._create_top_mlp() - - # create once to avoid tf.function recompilation at each eval - self.create_eval_metrics(FLAGS) - - def _get_bottom_mlp_padding(self, batch_size, multiple=8): - num_features = self.dataset_metadata.num_numerical_features - pad_to = tf.math.ceil(num_features / multiple) * multiple - pad_to = tf.cast(pad_to, dtype=tf.int32) - padding_features = pad_to - num_features - - padding_shape = [batch_size, padding_features] - dtype=tf.float16 if self.amp or self.fp16 else tf.float32 - return tf.zeros(shape=padding_shape, dtype=dtype) - - def _get_top_mlp_padding(self, batch_size, multiple=8): - num_features = self.num_all_categorical_features - if self.num_numerical_features != 0: - num_features += 1 - num_features = num_features * (num_features - 1) - num_features = num_features // 2 - num_features = num_features + self.embedding_dim - - pad_to = tf.math.ceil(num_features / multiple) * multiple - pad_to = tf.cast(pad_to, dtype=tf.int32) - padding_features = pad_to - num_features - - padding_shape = [batch_size, padding_features] - dtype=tf.float16 if self.amp or self.fp16 else tf.float32 - return tf.zeros(shape=padding_shape, dtype=dtype) - - def _create_bottom_mlp(self): - self.bottom_mlp_layers = [] - for dim in self.bottom_mlp_dims: - kernel_initializer = initializers.GlorotNormal() - bias_initializer = initializers.RandomNormal(stddev=math.sqrt(1. / dim)) - - l = tf.keras.layers.Dense(dim, activation='relu', - kernel_initializer=kernel_initializer, - bias_initializer=bias_initializer) - self.bottom_mlp_layers.append(l) - - def _create_top_mlp(self): - self.top_mlp = [] - for i, dim in enumerate(self.top_mlp_dims): - if i == len(self.top_mlp_dims) - 1: - # final layer - activation = 'linear' - else: - activation = 'relu' - - kernel_initializer = initializers.GlorotNormal() - bias_initializer = initializers.RandomNormal(stddev=math.sqrt(1. / dim)) - - l = tf.keras.layers.Dense(dim, activation=activation, - kernel_initializer=kernel_initializer, - bias_initializer=bias_initializer) - self.top_mlp.append(l) - - def _create_embeddings(self): - if self.distributed: - self.embedding_layers = [] - for table_size in self.global_table_sizes: - if self.use_merlin_de_embeddings: - e = embedding.Embedding(input_dim=table_size, - output_dim=self.embedding_dim, - embeddings_initializer=EmbeddingInitializer()) - else: - e = tf.keras.layers.Embedding(input_dim=table_size, - output_dim=self.embedding_dim, - embeddings_initializer=EmbeddingInitializer()) - self.embedding_layers.append(e) - - self.embedding = dmp.DistributedEmbedding(self.embedding_layers, - strategy='memory_balanced', - dp_input=False, - column_slice_threshold=self.column_slice_threshold) - - self.local_table_ids = self.embedding.strategy.input_ids_list[hvd.rank()] - else: - self.local_table_ids = list(range(len(self.global_table_sizes))) - feature_names = [f'feature_{i}' for i in self.local_table_ids] - - self.embedding = DualEmbeddingGroup(cardinalities=self.global_table_sizes, output_dim=self.embedding_dim, - memory_threshold=70, - dtype=tf.float16 if self.fp16 else tf.float32, - feature_names=feature_names, - trainable=self.embedding_trainable) - - def create_eval_metrics(self, FLAGS): - if FLAGS.auc_thresholds is not None: - self.auc_metric = tf.keras.metrics.AUC(num_thresholds=FLAGS.auc_thresholds, - curve='ROC', summation_method='interpolation', - from_logits=True) - else: - self.auc_metric = None - - self.bce_op = tf.keras.losses.BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE, - from_logits=True) - - def force_initialization(self): - numerical_features = tf.zeros(shape=[self.batch_size // hvd.size(), - self.dataset_metadata.num_numerical_features]) - - categorical_features = tf.zeros(shape=[self.batch_size, len(self.local_table_ids)], dtype=tf.int32) - inputs = _create_inputs_dict(numerical_features, categorical_features) - self(inputs=inputs, training=True) - - @tf.function - def call(self, inputs, sigmoid=False, training=False): - vals = list(inputs.values()) - numerical_features, cat_features = vals[0], vals[1] - - cat_features = tf.split(cat_features, num_or_size_splits=len(self.local_table_ids), axis=1) - cat_features = [tf.reshape(f, shape=[self.batch_size]) for f in cat_features] - - embedding_outputs = self._call_embeddings(cat_features, training=training) - - bottom_mlp_out = self._call_bottom_mlp(numerical_features, training=training) - bottom_part_output = tf.concat([bottom_mlp_out, embedding_outputs], axis=1) - - num_categorical_features = len(self.dataset_metadata.categorical_cardinalities) - interaction_input = tf.reshape(bottom_part_output, - [-1, num_categorical_features + 1, - self.embedding_dim]) - - x = self.interact_op(interaction_input, tf.squeeze(bottom_mlp_out)) - x = self._call_top_mlp(x, training=training) - - if sigmoid: - x = tf.math.sigmoid(x) - - x = tf.cast(x, tf.float32) - return x - - def _call_bottom_mlp(self, numerical_features, training=False): - if self.amp: - numerical_features = tf.cast(numerical_features, dtype=tf.float16) - - if training: - batch_size = self.batch_size // hvd.size() - else: - batch_size = tf.shape(numerical_features)[0] - - padding = self._get_bottom_mlp_padding(batch_size=batch_size) - x = tf.concat([numerical_features, padding], axis=1) - - with tf.name_scope('bottom_mlp'): - for l in self.bottom_mlp_layers: - x = l(x) - x = tf.expand_dims(x, axis=1) - bottom_mlp_out = x - return bottom_mlp_out - - def _call_embeddings(self, cat_features, training=False): - x = self.embedding(cat_features) - if self.distributed: - x = tf.concat([tf.expand_dims(z, axis=1) for z in x], axis=1) - - if self.amp: - x = tf.cast(x, dtype=tf.float16) - return x - - def _call_top_mlp(self, x, training=False): - if self.dot_interaction != 'custom_cuda': - batch_size = self.batch_size // hvd.size() if training else tf.shape(x)[0] - padding = self._get_top_mlp_padding(batch_size=batch_size) - x = tf.concat([x, padding], axis=1) - - with tf.name_scope('top_mlp'): - for i, l in enumerate(self.top_mlp): - x = l(x) - x = tf.cast(x, dtype=tf.float32) - return x - - @staticmethod - def _save_mlp_checkpoint(checkpoint_path, layers, prefix): - for i, layer in enumerate(layers): - for varname in ['kernel', 'bias']: - filename = get_variable_path(checkpoint_path, name=f'{prefix}/layer_{i}/{varname}') - print(f'saving: {varname} to {filename}') - variable = layer.__dict__[varname] - np.save(arr=variable.numpy(), file=filename) - - @staticmethod - def _restore_mlp_checkpoint(checkpoint_path, layers, prefix): - for i, layer in enumerate(layers): - for varname in ['kernel', 'bias']: - filename = get_variable_path(checkpoint_path, name=f'{prefix}/layer_{i}/{varname}') - print(f'loading: {varname} from {filename}') - variable = layer.__dict__[varname] - - numpy_var = np.load(file=filename) - variable.assign(numpy_var) - - @staticmethod - def _save_embeddings_checkpoint(checkpoint_path, embedding_weights): - for i, weight in enumerate(embedding_weights): - filename = get_variable_path(checkpoint_path, f'feature_{i}') - np.save(file=filename, arr=weight) - - @staticmethod - def _restore_weights_checkpoint(checkpoint_path, num_weights, name): - result = [] - for i in range(num_weights): - filename = os.path.join(checkpoint_path, f'{name}_{i}.npy') - print(f'loading: {name}_{i} from {filename}') - result.append(np.load(file=filename)) - return result - - - def save_checkpoint_if_path_exists(self, checkpoint_path): - if checkpoint_path is None: - return - - begin_save = time.time() - os.makedirs(checkpoint_path, exist_ok=True) - - dist_print('Saving a checkpoint...') - - if hvd.rank() == 0: - self._save_mlp_checkpoint(checkpoint_path, self.bottom_mlp_layers, prefix='bottom_mlp') - self._save_mlp_checkpoint(checkpoint_path, self.top_mlp, prefix='top_mlp') - - begin = time.time() - full_embedding_weights = self.embedding.get_weights() - end = time.time() - print(f'get weights took: {end - begin:.3f} seconds') - - if hvd.rank() == 0 and self.distributed: - self._save_embeddings_checkpoint(checkpoint_path, full_embedding_weights) - elif not self.distributed: - self.embedding.save_checkpoint(checkpoint_path=checkpoint_path) - - end_save = time.time() - dist_print('Saved a checkpoint to ', checkpoint_path) - dist_print(f'Saving a checkpoint took {end_save - begin_save:.3f}') - - def restore_checkpoint_if_path_exists(self, checkpoint_path): - begin = time.time() - if checkpoint_path is None: - return self - - dist_print('Restoring a checkpoint...') - self.force_initialization() - - self._restore_mlp_checkpoint(checkpoint_path, self.bottom_mlp_layers, prefix='bottom_mlp') - self._restore_mlp_checkpoint(checkpoint_path, self.top_mlp, prefix='top_mlp') - - paths = [] - for i in range(self.num_all_categorical_features): - path = get_variable_path(checkpoint_path, f'feature_{i}') - paths.append(path) - - if self.distributed: - self.embedding.set_weights(weights=paths) - else: - self.embedding.restore_checkpoint(checkpoint_path=checkpoint_path) - - end = time.time() - print('Restored a checkpoint from', checkpoint_path) - print(f'Restoring a checkpoint took: {end-begin:.3f} seconds') - return self - - def save_model_if_path_exists(self, path, save_input_signature=False): - if not path: - return - - if hvd.size() > 1: - raise ValueError('SavedModel conversion not supported in HybridParallel mode') - - if save_input_signature: - input_sig = model_input_signature(self, keep_original_batch_size=True) - call_graph = tf.function(self) - signatures = call_graph.get_concrete_function(input_sig[0]) - else: - signatures = None - - options = tf.saved_model.SaveOptions( - experimental_variable_policy=tf.saved_model.experimental.VariablePolicy.SAVE_VARIABLE_DEVICES) - - tf.keras.models.save_model( - model=self, - filepath=path, - overwrite=True, - signatures=signatures, - options=options) - - @staticmethod - def load_model_if_path_exists(path): - if not path: - return None - - if hvd.size() > 1: - raise ValueError('Loading a SavedModel not supported in HybridParallel mode') - - print('Loading a saved model from', path) - - loaded = tf.keras.models.load_model(path) - return loaded - - -# dummy model for profiling and debugging -class DummyDlrm(tf.keras.Model): - def __init__(self, FLAGS, dataset_metadata): - super(DummyDlrm, self).__init__() - self.dense = tf.keras.layers.Dense(1, activation='sigmoid', - kernel_initializer='glorot_normal', - bias_initializer=initializers.RandomNormal(stddev=math.sqrt(1. / 1)) - ) - self.dataset_metadata = dataset_metadata - self.top_variables = [v for v in self.trainable_variables if 'model_parallel' not in v.name] - self.variables_partitioned = False - self.batch_size = FLAGS.batch_size - - def call(self, inputs, sigmoid=False): - x = tf.zeros(shape=[self.batch_size // hvd.size(), - self.dataset_metadata.num_numerical_features], - dtype=tf.float32) - x = self.dense(x) - x = tf.cast(x, dtype=tf.float32) - if sigmoid: - x = tf.math.sigmoid(x) - return x - - def _partition_variables(self): - self.bottom_variables = [v for v in self.trainable_variables if 'model_parallel' in v.name] - self.bottom_variable_indices = [i for i,v in enumerate(self.trainable_variables) if 'model_parallel' in v.name] - - self.top_variables = [v for v in self.trainable_variables if 'model_parallel' not in v.name] - self.top_variable_indices = [i for i, v in enumerate(self.trainable_variables) if 'model_parallel' not in v.name] - self.variables_partitioned = True - - def extract_bottom_gradients(self, all_gradients): - if not self.variables_partitioned: - self._partition_variables() - return [all_gradients[i] for i in self.bottom_variable_indices] - - def extract_top_gradients(self, all_gradients): - if not self.variables_partitioned: - self._partition_variables() - return [all_gradients[i] for i in self.top_variable_indices] diff --git a/TensorFlow2/Recommendation/DLRM/preproc/gpu/get_gpu_resources.sh b/TensorFlow2/Recommendation/DLRM/preproc/gpu/get_gpu_resources.sh deleted file mode 100644 index b6411dbff..000000000 --- a/TensorFlow2/Recommendation/DLRM/preproc/gpu/get_gpu_resources.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/bash - -ADDRS=`nvidia-smi --query-gpu=index --format=csv,noheader | sed -e ':a' -e 'N' -e'$!ba' -e 's/\n/","/g'` -echo {\"name\": \"gpu\", \"addresses\":[\"$ADDRS\"]} diff --git a/TensorFlow2/Recommendation/DLRM/tests/test_fspecs.sh b/TensorFlow2/Recommendation/DLRM/tests/test_fspecs.sh deleted file mode 100644 index 67ca21b0b..000000000 --- a/TensorFlow2/Recommendation/DLRM/tests/test_fspecs.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -NAMES=${1:-'*.yaml'} -COMMON_OPTS="--xla --amp" - -bash test_with_opts.sh "${NAMES}" "${COMMON_OPTS}" - -# -# usage: -# docker build . -t nvidia_dlrm_tf -# docker run --security-opt seccomp=unconfined --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data nvidia_dlrm_tf bash -# cd tests -# bash test_fspecs.sh \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM/Dockerfile b/TensorFlow2/Recommendation/DLRM_and_DCNv2/Dockerfile similarity index 68% rename from TensorFlow2/Recommendation/DLRM/Dockerfile rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/Dockerfile index b3808ac41..f7592b9f5 100644 --- a/TensorFlow2/Recommendation/DLRM/Dockerfile +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/Dockerfile @@ -14,12 +14,16 @@ # # author: Tomasz Grel (tgrel@nvidia.com) +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/tensorflow:23.06-tf2-py3 +FROM nvcr.io/nvidia/tritonserver:23.06-py3-sdk as clientsdk +FROM ${FROM_IMAGE_NAME} as base -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/tensorflow:22.06-tf2-py3 -FROM ${FROM_IMAGE_NAME} +ARG DISTRIBUTED_EMBEDDINGS_COMMIT=45cffaa8 WORKDIR /dlrm +RUN apt update && apt install -y libb64-dev tree + ADD requirements.txt . RUN pip install --upgrade pip && pip install -r requirements.txt @@ -27,7 +31,7 @@ RUN pip install --upgrade pip && pip install -r requirements.txt RUN rm -rf distributed-embeddings &&\ git clone https://github.com/NVIDIA-Merlin/distributed-embeddings.git &&\ cd distributed-embeddings &&\ - git checkout v0.2 &&\ + git checkout ${DISTRIBUTED_EMBEDDINGS_COMMIT} &&\ git submodule init && git submodule update &&\ pip uninstall -y distributed-embeddings &&\ make clean &&\ @@ -35,10 +39,8 @@ RUN rm -rf distributed-embeddings &&\ pip install artifacts/*.whl &&\ cd .. -ADD . . - +ADD tensorflow-dot-based-interact tensorflow-dot-based-interact RUN mkdir -p /usr/local/lib/python3.8/dist-packages/tensorflow/include/third_party/gpus/cuda/ &&\ - ln -s -f /usr/local/cuda/include /usr/local/lib/python3.8/dist-packages/tensorflow/include/third_party/gpus/cuda/ &&\ cd tensorflow-dot-based-interact &&\ make clean &&\ pip uninstall -y tensorflow-dot-based-interact &&\ @@ -47,5 +49,13 @@ RUN mkdir -p /usr/local/lib/python3.8/dist-packages/tensorflow/include/third_par pip install ./artifacts/tensorflow_dot_based_interact-*.whl &&\ cd .. +COPY --from=clientsdk /workspace/install/python/tritonclient-2.35.0-py3-*.whl /dlrm/ +RUN if [[ "$(uname -m)" == "x86_64" ]]; \ + then echo x86; pip install tritonclient-2.35.0-py3-none-manylinux1_x86_64.whl[all]; \ + else echo arm; pip install tritonclient-2.35.0-py3-none-manylinux2014_aarch64.whl[all]; \ + fi + +ADD . . + ENV HOROVOD_CYCLE_TIME=0.2 ENV HOROVOD_ENABLE_ASYNC_COMPLETION=1 diff --git a/TensorFlow2/Recommendation/DLRM/Dockerfile_spark b/TensorFlow2/Recommendation/DLRM_and_DCNv2/Dockerfile_spark similarity index 100% rename from TensorFlow2/Recommendation/DLRM/Dockerfile_spark rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/Dockerfile_spark diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/LICENCE b/TensorFlow2/Recommendation/DLRM_and_DCNv2/LICENSE similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/LICENCE rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/LICENSE diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/NOTICE b/TensorFlow2/Recommendation/DLRM_and_DCNv2/NOTICE new file mode 100644 index 000000000..11786f3e3 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/NOTICE @@ -0,0 +1,4 @@ +DLRM and DCNv2 TensorFlow2 + +This repository includes software from https://github.com/tensorflow/recommenders +licensed under the Apache License, Version 2.0 (the "License") diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/README.md b/TensorFlow2/Recommendation/DLRM_and_DCNv2/README.md new file mode 100644 index 000000000..a3e21f5bf --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/README.md @@ -0,0 +1,325 @@ +# DLRM and DCNv2 for TensorFlow 2 + +This repository provides recipes to train and deploy two ranking models – DLRM and DCNv2. +This document provides instructions on how to run those models and a description of the features implemented. +Detailed instructions for reproducing, as well as benchmark results and descriptions of the respective architectures, can be found in: + +* [doc/DLRM.md](doc/DLRM.md) for DLRM +* [doc/DCNv2.md](doc/DCNv2.md) for DCNv2 + + +## Table Of Contents + + * [Overview](#overview) + * [Default configuration](#default-configuration) + * [Feature support matrix](#feature-support-matrix) + * [Features](#features) + * [Mixed precision training](#mixed-precision-training) + * [Enabling mixed precision](#enabling-mixed-precision) + * [Enabling TF32](#enabling-tf32) + * [Hybrid-parallel training with Merlin Distributed Embeddings](#hybrid-parallel-training-with-merlin-distributed-embeddings) + * [Training very large embedding tables](#training-very-large-embedding-tables) + * [Multi-node training](#multi-node-training) + * [Preprocessing on GPU with Spark 3](#preprocessing-on-gpu-with-spark-3) + * [BYO dataset functionality overview](#byo-dataset-functionality-overview) + * [Setup](#setup) + * [Requirements](#requirements) + * [Advanced](#advanced) + * [Scripts and sample code](#scripts-and-sample-code) + * [Parameters](#parameters) + * [Command-line options](#command-line-options) + * [Getting the Data](#getting-the-data) + * [Inference deployment](#inference-deployment) + * [Release notes](#release-notes) + * [Changelog](#changelog) + + +## Overview + +This directory contains Deep Learning Recommendation Model (DLRM) and Deep Cross Network version 2 (DCNv2). +Both are recommendation models designed to use categorical and numerical inputs. + +Using the scripts provided here, you can efficiently train models too large to fit into a single GPU. +This is because we use a hybrid-parallel approach, which combines model parallelism with data parallelism for +different parts of the neural network. +This is explained in detail in the [next section](#hybrid-parallel-training-with-merlin-distributed-embeddings). + +Using DLRM or DCNv2, you can train a high-quality general model for recommendations. + +Both models in this directory are trained with mixed precision using Tensor Cores on NVIDIA Volta, NVIDIA Turing, and NVIDIA Ampere GPU architectures. +Therefore, researchers can get results 2x faster than training without Tensor Cores while experiencing the +benefits of mixed precision training. This model is tested against each NGC monthly container +release to ensure consistent accuracy and performance over time. + + +### Default configuration + +The following features were implemented: +- general + - static loss scaling for Tensor Cores (mixed precision) training + - hybrid-parallel multi-GPU training using Merlin Distributed Embeddings +- inference + - inference using Merlin HPS, Triton ensembles and TensorRT +- preprocessing + - dataset preprocessing using Spark 3 on GPUs + +### Feature support matrix + +The following features are supported by this model: + +| Feature | DLRM and DCNv2 +|----------------------|-------------------------- +|Hybrid-parallel training with Merlin Distributed Embeddings | Yes +|Multi-node training | Yes +|Triton inference with TensorRT and Merlin Hierarchical Parameter Server | Yes +|Automatic mixed precision (AMP) | Yes +|XLA | Yes +|Preprocessing on GPU with Spark 3| Yes +|Inference using NVIDIA Triton | Yes + + +#### Features + +**Automatic Mixed Precision (AMP)** +Enables mixed precision training without any changes to the code-base by performing automatic graph rewrites and loss scaling controlled by an environmental variable. + +**XLA** + +The training script supports a `--xla` flag. It can be used to enable XLA JIT compilation. Currently, we use [XLA Lite](https://docs.nvidia.com/deeplearning/frameworks/tensorflow-user-guide/index.html#xla-lite). It delivers a steady 10-30% performance boost depending on your hardware platform, precision, and the number of GPUs. It is turned off by default. + +**Horovod** +Horovod is a distributed training framework for TensorFlow, Keras, PyTorch, and MXNet. The goal of Horovod is to make distributed deep learning fast and easy to use. For more information about how to get started with Horovod, refer tothe Horovod [official repository](https://github.com/horovod/horovod). + +**Hybrid-parallel training with Merlin Distributed Embeddings** +Our model uses Merlin Distributed Embeddings to implement efficient multi-GPU training. +For details, refer to the example sources in this repository or refer to the TensorFlow tutorial. +For a detailed description of our multi-GPU approach, visit this [section](#hybrid-parallel-training-with-merlin-distributed-embeddings). + +**Multi-node training** +This repository supports multi-node training. For more information, refer to the [multinode section](#multi-node-training) + +**Merlin Hierarchical Parameter server (HPS)** +This repository supports inference with Merlin HPS. For more information, refer to [doc/inference.md](doc/inference.md). + + +### Mixed precision training + +Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in NVIDIA Volta, and following with both the NVIDIA Turing and NVIDIA Ampere architectures, significant training speedups are experienced by switching to mixed precision – up to 3.4x overall speedup on the most arithmetically intense model architectures. Using mixed precision training requires two steps: +1. Porting the model to use the FP16 data type where appropriate. +2. Adding loss scaling to preserve small gradient values. + +The ability to train deep learning networks with lower precision was introduced in the Pascal architecture and first supported in [CUDA 8](https://devblogs.nvidia.com/parallelforall/tag/fp16/) in the NVIDIA Deep Learning SDK. + +For information about: +- How to train using mixed precision, refer to the [Mixed Precision Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed Precision](https://docs.nvidia.com/deeplearning/performance/mixed-precision-training/index.html) documentation. +- Techniques used for mixed precision training, refer to the [Mixed-Precision Training of Deep Neural Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) blog. + +#### Enabling mixed precision + +Mixed precision training is turned off by default. To turn it on, issue the `--amp` flag to the `dlrm.py` or `dcnv2.py` script. + + +#### Enabling TF32 + +TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on Volta GPUs. + +TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require high dynamic range for weights or activations. + +For more information, refer to the [TensorFloat-32 in the A100 GPU Accelerates AI Training, HPC up to 20x](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) blog post. + +TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by default. + + +### Hybrid-parallel training with Merlin Distributed Embeddings + +Many recommendation models contain very large embedding tables. As a result, the model is often too large to fit onto a single device. +This could be easily solved by training in a model-parallel way, using either the CPU or other GPUs as "memory donors." +However, this approach is suboptimal as the "memory donor" devices' compute is not utilized. +In this repository, we use the model-parallel approach for the Embedding Tables while employing a usual data-parallel approach +for the more compute-intensive MLPs and Dot Interaction layer. This way, we can train models much larger than what would normally fit into +a single GPU while at the same time making the training faster by using multiple GPUs. We call this approach hybrid-parallel training. + +To implement this approach, we use the [Merlin Distributed Embeddings](https://github.com/NVIDIA-Merlin/distributed-embeddings) library. +It provides a scalable model parallel wrapper called `distributed_embeddings.dist_model_parallel`. This wrapper automatically distributes embedding tables to multiple GPUs. +This way, embeddings can be scaled beyond a single GPU’s memory capacity without +complex code to handle cross-worker communication. + +Under the hood, Merlin Distributed Embeddings uses a +specific multi-GPU communication pattern called +[all-2-all](https://en.wikipedia.org/wiki/All-to-all_\(parallel_pattern\)) to transition from model-parallel to data-parallel +paradigm. In the [original DLRM whitepaper](https://arxiv.org/abs/1906.00091), this is referred to as "butterfly shuffle." + +An example model using Hybrid Parallelism is shown in Figure 2. The compute-intensive dense layers are run in data-parallel +mode. The smaller embedding tables are run model-parallel, so each smaller table is placed entirely on a single device. +This is not suitable for larger tables that need more memory than can be provided by a single device. Therefore, +those large tables are split into multiple parts and each part is run on a different GPU. + +

+ +
+Figure 2. Hybrid parallelism with Merlin Distributed Embeddings. +

+ +In this repository, for both DLRM and DCNv2, +we train models of three sizes: "small" (15.6 GiB), "large" (84.9 GiB), and "extra large" (421 GiB). +The "small" model can be trained on a single V100-32GB GPU. The "large" model needs at least 8xV100-32GB GPUs, +but each table can fit on a single GPU. + +The "extra large" model, on the other hand, contains tables that do not fit into a single device and will be automatically +split and stored across multiple GPUs by Merlin Distributed Embeddings. + +#### Training very large embedding tables + +We tested this approach by training a DLRM model on the Criteo Terabyte dataset with the frequency limiting option turned off (set to zero). +The weights of the resulting model take 421 GiB. The largest table weighs 140 GiB. +Here are the commands you can use to reproduce this: + +``` +# build and run the preprocessing container as in the Quick Start Guide +# then when preprocessing set the frequency limit to 0: +./prepare_dataset.sh DGX2 0 + +# build and run the training container same as in the Quick Start Guide +# then append options necessary for training very large embedding tables: +horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dlrm.py --dataset_path /data/dlrm/ --amp --xla +``` + +When using this method on a DGX A100 with 8 A100-80GB GPUs and a large-enough dataset, it is possible to train a single embedding table of up to 600 GB. You can also use multi-node training (described below) to train even larger recommender systems. + + +#### Multi-node training + +Multi-node training is supported. Depending on the exact interconnect hardware and model configuration, +you might experience only a modest speedup with multi-node. +Multi-node training can also be used to train larger models. +For example, to train a 1.68 TB variant of DLRM on multi-node, you can run: + +``` +cmd='numactl --interleave=all -- python -u dlrm.py --dataset_path /data/dlrm/full_criteo_data --amp --xla\ +--embedding_dim 512 --bottom_mlp_dims 512,256,512' \ +srun_flags='--mpi=pmix' \ +cont=nvidia_dlrm_tf \ +mounts=/data/dlrm:/data/dlrm \ +sbatch -n 32 -N 4 -t 00:20:00 slurm_multinode.sh +``` + +### Preprocessing on GPU with Spark 3 + +Refer to the [preprocessing documentation](doc/criteo_dataset.md#advanced) for a detailed description of the Spark 3 GPU functionality. + + +### BYO dataset functionality overview + +Refer to the [BYO Dataset summary](doc/multidataset.md) for details. + +### Inference using NVIDIA Triton + +The [deployment](deployment) directory contains two examples of deploying recommender models larger than single GPU memory. Both use the NVIDIA Triton Inference Server. +1. For the example with Merlin Hierarchical Parameter Server and TensorRT, +refer to [detailed documentation](doc/merlin_hps_inference.md) +2. For the example with TensorFlow SavedModel and TensorRT +3. Refer to [detailed documentation](doc/tensorflow_inference.md) + +## Setup + +The following section lists the requirements for training DLRM and DCNv2. + +### Requirements + +This repository contains Dockerfile that extends the TensorFlow 2 NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: +- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) +- [TensorFlow 2 23.02-py3](https://ngc.nvidia.com/catalog/containers/nvidia:tensorflow/tags) NGC container +- Supported GPUs: + - [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) + - [NVIDIA Turing architecture](https://www.nvidia.com/en-us/geforce/turing/) + - [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) + + +For more information about how to get started with NGC containers, refer to the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: +- [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) +- [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) +- [Running TensorFlow](https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/running.html#running) + +For those unable to use the TensorFlow NGC container, to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). + +## Advanced + +The following sections provide more details of the dataset, running training and inference, and the training results. + +### Scripts and sample code + +These are the important modules in this repository: +- `dlrm.py` - The script for training DLRM. Wrapper around `main.py`. +- `dcnv2.py` - The script for training DCNv2. Wrapper around `main.py`. +- `main.py` - Contains common code for training and evaluating DLRM and DCNv2 (e.g., the training loop) +- `Dockerfile` - defines the docker image used for training DLRM and DCNv2. +- `nn/model.py` - Contains the definition of the full neural network, which can be used to create DLRM and DCNv2. +- `nn/dense_model.py` - Defines the "dense" part of DLRM and DCNv2 (Bottom MLP, Interaction, Top MLP). +- `nn/sparse_model.py` - Defines the "sparse" part of DLRM and DCNv2 (Embedding layers). +- `nn/trainer.py` - Defines a single training step (forward, backward, weight update). +- `nn/embedding.py` - Implementations of the embedding layers. +- `nn/lr_scheduler.py` - Defines a TensorFlow learning rate scheduler that supports learning rate warmup and polynomial decay. +- `deployment/deploy.py` - The script used for creating the Triton model store for inference. +- `deployment/evaluate_latency.py` - The script used to evaluate the latency of deployed Triton DLRM and DCNv2 models. +- `deployment/evaluate_accuracy.py` - The script used to evaluate the accuracy of deployed Triton DLRM and DCNv2 models. +- `dataloading/dataloader.py` - Handles defining the dataset objects based on command-line flags. +- `dataloading/datasets.py` - Defines the `TfRawBinaryDataset` class responsible for storing and loading the training data. +- `preproc` - directory containing source code for preprocessing the Criteo 1TB Dataset. +- `slurm_multinode.sh` - Example batch script for multi-node training on SLURM clusters. +- `tensorflow-dot-based-interact` - A directory with a set of custom CUDA kernels. They provide fast implementations of the dot-interaction operation for various precisions and hardware platforms. +- `utils.py` - General utilities, such as a timer used for taking performance measurements. + + +### Parameters + +The table below lists the most important command-line parameters of the `main.py` script. + +| Scope| parameter| Comment| Default Value | +| ----- | --- | ---- | ---- | +|datasets|dataset_path|Path to the JSON file with the sizes of embedding tables| +|function|mode| Choose "train" to train the model, "inference" to benchmark inference and "eval" to run validation| train| +|optimizations|amp| Enable automatic mixed precision| False +|optimizations|xla| Enable XLA| False| +|hyperparameters|batch_size| Batch size used for training|65536| +|hyperparameters|epochs| Number of epochs to train for|1| +|hyperparameters|optimizer| Optimization algorithm for training |SGD| +|hyperparameters|evals_per_epoch| Number of evaluations per epoch|1| +|hyperparameters|valid_batch_size| Batch size used for validation|65536| +|hyperparameters|max_steps| Stop the training/inference after this many optimization steps|-1| +|checkpointing|restore_checkpoint_path| Path from which to restore a checkpoint before training|None| +|checkpointing|save_checkpoint_path| Path to which to save a checkpoint file at the end of the training|None| +|debugging|run_eagerly| Disable all tf.function decorators for debugging|False| +|debugging|print_freq| Number of steps between debug prints|1000| +|debugging|max_steps| Exit early after performing a prescribed number of steps|None| + + +### Command-line options + +The training script supports a number of command-line flags. +You can get the descriptions of those, for example, by running `python dlrm.py --help`. + +### Getting the Data +Refer to: + +* [doc/criteo_dataset.md](doc/criteo_dataset.md) for information on how to run on the Criteo 1TB dataset. +* [doc/multidataset.md](doc/multidataset.md) for information on training with your own dataset. + + +## Release notes +We’re constantly refining and improving our performance on AI and HPC workloads, even on the same hardware, with frequent updates to our software stack. For our latest performance data, refer to these pages for [AI](https://developer.nvidia.com/deep-learning-performance-training-inference) and [HPC](https://developer.nvidia.com/hpc-application-performance) benchmarks. + +### Changelog +June 2023 +- Support and performance numbers for DCNv2 +- Support inference deployment using NVIDIA Merlin HPS, NVIDIA Triton, and NVIDIA TensorRT for DLRM and DCNv2 +- Major refactoring and usability improvements + +July 2022 +- Start using Merlin Distributed Embeddings + +March 2022 +- Major performance improvements +- Support for BYO dataset + +March 2021 +- Initial release diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/exceptions.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/__init__.py similarity index 83% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/exceptions.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/__init__.py index b48d480a6..4fda2b94d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/exceptions.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,5 +11,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -class ContainerNotStarted(Exception): - pass +# +# author: Tomasz Grel (tgrel@nvidia.com) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/dataloader.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/dataloader.py new file mode 100644 index 000000000..22d754d93 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/dataloader.py @@ -0,0 +1,136 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com), Tomasz Cheda (tcheda@nvidia.com) + +import os + +from .defaults import TRAIN_MAPPING, TEST_MAPPING +from .feature_spec import FeatureSpec +from .raw_binary_dataset import TfRawBinaryDataset, DatasetMetadata +from .synthetic_dataset import SyntheticDataset + +from .split_tfrecords_multihot_dataset import SplitTFRecordsDataset + + +def get_dataset_metadata(dataset_path, feature_spec): + fspec_path = os.path.join(dataset_path, feature_spec) + feature_spec = FeatureSpec.from_yaml(fspec_path) + dataset_metadata = DatasetMetadata(num_numerical_features=feature_spec.get_number_of_numerical_features(), + categorical_cardinalities=feature_spec.get_categorical_sizes()) + return dataset_metadata + + +def _create_pipelines_synthetic_fspec(**kwargs): + fspec_path = os.path.join(kwargs['dataset_path'], kwargs['feature_spec']) + feature_spec = FeatureSpec.from_yaml(fspec_path) + dataset_metadata = DatasetMetadata(num_numerical_features=feature_spec.get_number_of_numerical_features(), + categorical_cardinalities=feature_spec.get_categorical_sizes()) + local_table_sizes = [dataset_metadata.categorical_cardinalities[i] for i in kwargs['table_ids']] + + names = feature_spec.get_categorical_feature_names() + + local_names = [names[i] for i in kwargs['table_ids']] + local_table_hotness = [feature_spec.feature_spec[name]["hotness"] for name in local_names] + local_table_alpha = [feature_spec.feature_spec[name]["alpha"] for name in local_names] + + print('local table sizes: ', local_table_sizes) + print('Local table hotness: ', local_table_hotness) + + train_dataset = SyntheticDataset(batch_size=kwargs['train_batch_size'], + num_numerical_features=dataset_metadata.num_numerical_features, + categorical_feature_cardinalities=local_table_sizes, + categorical_feature_hotness=local_table_hotness, + categorical_feature_alpha=local_table_alpha, + num_batches=kwargs.get('synthetic_dataset_train_batches', int(1e9)), + num_workers=kwargs['world_size'], + variable_hotness=False) + + test_dataset = SyntheticDataset(batch_size=kwargs['test_batch_size'], + num_numerical_features=dataset_metadata.num_numerical_features, + categorical_feature_cardinalities=local_table_sizes, + categorical_feature_hotness=local_table_hotness, + categorical_feature_alpha=local_table_alpha, + num_batches=kwargs.get('synthetic_dataset_valid_batches', int(1e9)), + num_workers=kwargs['world_size'], + variable_hotness=False) + return train_dataset, test_dataset + + +def _create_pipelines_tf_raw(**kwargs): + fspec_path = os.path.join(kwargs['dataset_path'], kwargs['feature_spec']) + feature_spec = FeatureSpec.from_yaml(fspec_path) + + local_categorical_names = feature_spec.cat_positions_to_names(kwargs['table_ids']) + train_dataset = TfRawBinaryDataset(feature_spec=feature_spec, + instance=TRAIN_MAPPING, + batch_size=kwargs['train_batch_size'], + numerical_features_enabled=True, + local_categorical_feature_names=local_categorical_names, + rank=kwargs['rank'], + world_size=kwargs['world_size'], + concat_features=kwargs['concat_features'], + data_parallel_categoricals=kwargs['data_parallel_input']) + + test_dataset = TfRawBinaryDataset(feature_spec=feature_spec, + instance=TEST_MAPPING, + batch_size=kwargs['test_batch_size'], + numerical_features_enabled=True, + local_categorical_feature_names=local_categorical_names, + rank=kwargs['rank'], + world_size=kwargs['world_size'], + concat_features=kwargs['concat_features'], + data_parallel_categoricals=kwargs['data_parallel_input']) + return train_dataset, test_dataset + + +def _create_pipelines_split_tfrecords(**kwargs): + fspec_path = os.path.join(kwargs['dataset_path'], kwargs['feature_spec']) + feature_spec = FeatureSpec.from_yaml(fspec_path) + + train_dataset = SplitTFRecordsDataset(dataset_dir=feature_spec.base_directory + '/train/', + feature_ids=kwargs['table_ids'], + num_numerical=feature_spec.get_number_of_numerical_features(), + rank=kwargs['rank'], world_size=kwargs['world_size'], + batch_size=kwargs['train_batch_size']) + + test_dataset = SplitTFRecordsDataset(dataset_dir=feature_spec.base_directory + '/test/', + feature_ids=kwargs['table_ids'], + num_numerical=feature_spec.get_number_of_numerical_features(), + rank=kwargs['rank'], world_size=kwargs['world_size'], + batch_size=kwargs['test_batch_size']) + + return train_dataset, test_dataset + + +def create_input_pipelines(dataset_type, dataset_path, train_batch_size, test_batch_size, + table_ids, feature_spec, rank=0, world_size=1, concat_features=False, + data_parallel_input=False): + + # pass along all arguments except dataset type + kwargs = locals() + del kwargs['dataset_type'] + + #hardcoded for now + kwargs['synthetic_dataset_use_feature_spec'] = True + if dataset_type == 'synthetic' and not kwargs['synthetic_dataset_use_feature_spec']: + return _create_pipelines_synthetic(**kwargs) + elif dataset_type == 'synthetic' and kwargs['synthetic_dataset_use_feature_spec']: # synthetic based on feature spec + return _create_pipelines_synthetic_fspec(**kwargs) + elif dataset_type == 'tf_raw': + return _create_pipelines_tf_raw(**kwargs) + elif dataset_type == 'split_tfrecords': + return _create_pipelines_split_tfrecords(**kwargs) + else: + raise ValueError(f'Unsupported dataset type: {dataset_type}') diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/dataloader_benchmark.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/dataloader_benchmark.py new file mode 100644 index 000000000..1d7bf8028 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/dataloader_benchmark.py @@ -0,0 +1,163 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +from . import dataloader +import argparse +import os +import time + +import tensorflow as tf +import horovod.tensorflow as hvd +from .feature_spec import FeatureSpec + +def compute_bytes_per_batch(batch): + bytes_per_dtype = dict( + float16=2, + int32=4, + int8=1 + ) + + (numerical, categorical), label = batch + numerical_bytes = numerical.shape[0] * numerical.shape[1] * bytes_per_dtype[numerical.dtype.name] + + categorical_bytes = [] + for c in categorical: + if hasattr(c, 'flat_values'): + # ragged tensor + values = c.flat_values + values_bytes = values.shape[0] * bytes_per_dtype[values.dtype.name] + categorical_bytes.append(values_bytes) + else: + # dense tensor + num_bytes = c.shape[0] * c.shape[1] * bytes_per_dtype[c.dtype.name] + categorical_bytes.append(num_bytes) + categorical_bytes = sum(categorical_bytes) + + label_bytes = label.shape[0] * bytes_per_dtype[label.dtype.name] + return numerical_bytes + categorical_bytes + label_bytes + + +def main(): + parser = argparse.ArgumentParser(description="Benchmark a dataloader") + parser.add_argument('--dataset_path', default='synthetic_dataset', type=str, + help='Path to the destination directory') + parser.add_argument('--dataset_type', type=str, choices=['tf_raw', 'split_tfrecords']) + parser.add_argument('--batch_size', default=65536, type=int, help='Batch size') + parser.add_argument('--xla', default=False, action='http://github.com/store_true', help='Batch size') + parser.add_argument('--amp', default=False, action='http://github.com/store_true', help='Batch size') + parser.add_argument('--run_eagerly', default=False, action='http://github.com/store_true', help='Batch size') + parser.add_argument('--tfdata_debug', default=False, action='http://github.com/store_true', help='Batch size') + parser.add_argument('--feature_spec', type=str, default='feature_spec.yaml', + help='Filename of the feature spec describing the dataset') + parser.add_argument('--max_batches', type=int, default=100, + help='Stop after this many batches, even if there is still some data to be read') + parser.add_argument('--warmup_steps', type=int, default=5, + help='Number of warmup steps that are not benchmarked') + parser.add_argument('--sleep', type=int, default=0, + help='Sleep for this many seconds after creating the dataloader. For debug only.') + + args = parser.parse_args() + + args.synthetic_dataset_use_feature_spec = False + args.valid_batch_size = args.batch_size + + if args.dataset_type == 'nvt' and not args.run_eagerly: + raise ValueError('NVT dataloader does not support graph mode. Please specify --run_eagerly to use it.') + + if args.xla: + os.environ['TF_XLA_FLAGS'] = '--tf_xla_auto_jit=fusible' + + hvd.init() + + gpus = tf.config.experimental.list_physical_devices('GPU') + + if args.dataset_type != 'nvt': + for gpu in gpus: + tf.config.experimental.set_memory_growth(gpu, True) + + visible_gpus = [] + if gpus: + visible_gpus = gpus[hvd.local_rank()] + tf.config.experimental.set_visible_devices(visible_gpus, 'GPU') + + if args.amp: + policy = tf.keras.mixed_precision.Policy("mixed_float16") + tf.keras.mixed_precision.set_global_policy(policy) + + tf.config.run_functions_eagerly(args.run_eagerly) + if args.tfdata_debug: + tf.data.experimental.enable_debug_mode() + + fspec_path = os.path.join(args.dataset_path, args.feature_spec) + feature_spec = FeatureSpec.from_yaml(fspec_path) + + table_ids = list(range(len(feature_spec.get_categorical_sizes()))) + + table_ids = table_ids[hvd.rank()::hvd.size()] + + print('Creating the pipelines') + train_pipeline, validation_pipeline = dataloader.create_input_pipelines(args, table_ids=table_ids, + rank=hvd.rank(), + world_size=hvd.size()) + + print('Benchmarking...') + + it = iter(train_pipeline.op()) + + reduce_input = tf.convert_to_tensor([0], dtype=tf.float32, name='reduce_input') + + @tf.function + def step(): + device = '/GPU:0' + with tf.device(device): + b = next(it) + _ = hvd.allreduce(reduce_input, name='barrier') + return + + for i in range(args.warmup_steps): + print('warmup step:', i) + l = step() + + rank = hvd.rank() + if args.sleep != 0: + print('sleeping...') + time.sleep(args.sleep) + + begin = time.time() + current = begin + for idx in range(args.max_batches): + l = step() + new = time.time() + if rank == 0: + print(f'batch: {idx}, step time: {current - new:.3f}') + current = new + + end = time.time() + + print('Benchmark done') + num_batches = (idx + 1) + elapsed = (end - begin) + batches_per_second = num_batches / elapsed + samples_per_second = batches_per_second * args.batch_size + + if rank == 0: + print(f'Batches per second: {batches_per_second:.2e}') + print(f'Samples per second: {samples_per_second:.2e}') + + +if __name__ == '__main__': + main() diff --git a/TensorFlow2/Recommendation/DLRM/defaults.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/defaults.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/defaults.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/defaults.py diff --git a/TensorFlow2/Recommendation/DLRM/feature_spec.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/feature_spec.py similarity index 98% rename from TensorFlow2/Recommendation/DLRM/feature_spec.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/feature_spec.py index 758cb60fe..c2d41d79b 100644 --- a/TensorFlow2/Recommendation/DLRM/feature_spec.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/feature_spec.py @@ -17,7 +17,7 @@ from typing import Dict from typing import List import numpy as np -from defaults import CATEGORICAL_CHANNEL, NUMERICAL_CHANNEL, LABEL_CHANNEL, \ +from .defaults import CATEGORICAL_CHANNEL, NUMERICAL_CHANNEL, LABEL_CHANNEL, \ TRAIN_MAPPING, TEST_MAPPING, \ CARDINALITY_SELECTOR, DTYPE_SELECTOR, \ SPLIT_BINARY @@ -163,7 +163,7 @@ def _check_source_spec_section_model_specific(self): assert len(contained_features) == 1 # check label dtype - assert np.dtype(self.feature_spec[first_feature][DTYPE_SELECTOR]) == np.bool + assert np.dtype(self.feature_spec[first_feature][DTYPE_SELECTOR]) == bool else: assert False, "Feature of unknown type" @@ -237,7 +237,7 @@ def get_default_feature_spec(number_of_numerical_features, categorical_feature_c zip(categorical_feature_names, cat_feature_types, categorical_feature_cardinalities)} for f_name in numerical_feature_names: feature_dict[f_name] = {DTYPE_SELECTOR: str(np.dtype(np.float16))} - feature_dict[label_feature_name] = {DTYPE_SELECTOR: str(np.dtype(np.bool))} + feature_dict[label_feature_name] = {DTYPE_SELECTOR: str(np.dtype(bool))} channel_spec = {CATEGORICAL_CHANNEL: categorical_feature_names, NUMERICAL_CHANNEL: numerical_feature_names, @@ -297,4 +297,4 @@ def get_categorical_feature_type(size: int): if size < np.iinfo(numpy_type).max: return numpy_type - raise RuntimeError(f"Categorical feature of size {size} is too big for defined types") \ No newline at end of file + raise RuntimeError(f"Categorical feature of size {size} is too big for defined types") diff --git a/TensorFlow2/Recommendation/DLRM/gen_csv.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/gen_csv.py similarity index 96% rename from TensorFlow2/Recommendation/DLRM/gen_csv.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/gen_csv.py index ba644ca37..2ce2e0a3d 100644 --- a/TensorFlow2/Recommendation/DLRM/gen_csv.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/gen_csv.py @@ -11,13 +11,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from defaults import NUMERICAL_CHANNEL, LABEL_CHANNEL -from feature_spec import FeatureSpec from argparse import ArgumentParser import pandas as pd import os import numpy as np +from .defaults import NUMERICAL_CHANNEL, LABEL_CHANNEL +from .feature_spec import FeatureSpec + def parse_args(): parser = ArgumentParser() diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/generate_feature_spec.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/generate_feature_spec.py new file mode 100644 index 000000000..09d29fe0c --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/generate_feature_spec.py @@ -0,0 +1,83 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import yaml +import argparse + + +variants = dict( + # Generates 16 GiB embedding tables + criteo_t15_synthetic=dict( + num_numerical=13, + cardinalities=[7912889, 33823, 17139, 7339, 20046, 4, 7105, 1382, 63, 5554114, 582469, 245828, 11, 2209, + 10667, 104, 4, 968, 15, 8165896, 2675940, 7156453, 302516, 12022, 97, 35], + hotness=26 * [1], + alpha=26 * [1.45] + ), + # Generates 85 GiB embedding tables + criteo_t3_synthetic=dict( + num_numerical=13, + cardinalities=[45833188,36747,1572176,345139,11,2209,11268,128,4,975,15,48937457,17246,11316796,40094537, + 452104,12607,105,36,7414,20244,4,7115,1442,63,29275261], + hotness=26 * [1], + alpha=26 * [1.45] + ), + # Generates 421 GiB + criteo_t0_synthetic=dict( + num_numerical=13, + cardinalities=[227605432, 39061, 3067956, 405283, 11, 2209, 11939, 155, 4, 977, 15, 292775614, 17296, + 40790948, 187188510, 590152, 12974, 109, 37, 7425, 20266, 4, 7123, 1544, 64, 130229467], + hotness=26 * [1], + alpha=26 * [1.45] + ), +) + + +def main(): + parser = argparse.ArgumentParser(description="Generate a synthetic feature spec") + parser.add_argument('--dst', default='feature_spec.yaml', type=str, help='Output path') + parser.add_argument('--variant', choices=list(variants.keys()), required=True, type=str, + help='Variant of the synthetic dataset to be used') + args = parser.parse_args() + num_numerical, cardinalities, hotness, alphas = tuple(variants[args.variant].values()) + + feature_spec = {} + for i, (c, h, a) in enumerate(zip(cardinalities, hotness, alphas)): + name = f'cat_{i}' + f = dict(cardinality=c, hotness=h, alpha=a, dtype='int32') + feature_spec[name] = f + + for i in range(num_numerical): + name = f'num_{i}' + feature_spec[name] = dict(dtype='float16') + + feature_spec['label'] = dict(dtype='int8') + + channel_spec = {} + channel_spec['categorical'] = [k for k in feature_spec.keys() if 'cat' in k] + channel_spec['numerical'] = [k for k in feature_spec.keys() if 'num' in k] + channel_spec['label'] = ['label'] + + source_spec = None + full_spec = dict(feature_spec=feature_spec, channel_spec=channel_spec, source_spec=source_spec) + + with open(args.dst, 'w') as f: + yaml.dump(data=full_spec, stream=f) + + +if __name__ == '__main__': + main() diff --git a/TensorFlow2/Recommendation/DLRM/prepare_synthetic_dataset.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/prepare_synthetic_dataset.py similarity index 88% rename from TensorFlow2/Recommendation/DLRM/prepare_synthetic_dataset.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/prepare_synthetic_dataset.py index 8c8264ab6..1255c10f9 100644 --- a/TensorFlow2/Recommendation/DLRM/prepare_synthetic_dataset.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/prepare_synthetic_dataset.py @@ -15,11 +15,12 @@ import os import tqdm -from defaults import DTYPE_SELECTOR, TRAIN_MAPPING, TEST_MAPPING -from datasets import DummyDataset -from feature_spec import FeatureSpec from absl import app, flags +from .defaults import DTYPE_SELECTOR, TRAIN_MAPPING, TEST_MAPPING +from .synthetic_dataset import SyntheticDataset +from .feature_spec import FeatureSpec + FLAGS = flags.FLAGS flags.DEFINE_integer("synthetic_dataset_num_entries", @@ -116,13 +117,13 @@ def main(argv): number_of_numerical_features = fspec.get_number_of_numerical_features() categorical_feature_sizes = fspec.get_categorical_sizes() - train_dataset = DummyDataset(batch_size=batch_size, num_numerical_features=number_of_numerical_features, - categorical_feature_cardinalities=categorical_feature_sizes, - num_batches=number_of_batches) + train_dataset = SyntheticDataset(batch_size=batch_size, num_numerical_features=number_of_numerical_features, + categorical_feature_cardinalities=categorical_feature_sizes, + num_batches=number_of_batches) - test_dataset = DummyDataset(batch_size=batch_size, num_numerical_features=number_of_numerical_features, - categorical_feature_cardinalities=categorical_feature_sizes, - num_batches=number_of_batches) + test_dataset = SyntheticDataset(batch_size=batch_size, num_numerical_features=number_of_numerical_features, + categorical_feature_cardinalities=categorical_feature_sizes, + num_batches=number_of_batches) write_dataset_to_disk( dataset_train=train_dataset, diff --git a/TensorFlow2/Recommendation/DLRM/datasets.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/raw_binary_dataset.py similarity index 69% rename from TensorFlow2/Recommendation/DLRM/datasets.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/raw_binary_dataset.py index 010d2859b..d1cb76a09 100644 --- a/TensorFlow2/Recommendation/DLRM/datasets.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/raw_binary_dataset.py @@ -18,45 +18,17 @@ import tensorflow as tf import os import numpy as np +from itertools import chain from collections import namedtuple from typing import Optional, Tuple, List -from defaults import CATEGORICAL_CHANNEL, NUMERICAL_CHANNEL, LABEL_CHANNEL, DTYPE_SELECTOR -from feature_spec import FeatureSpec, FEATURES_SELECTOR, FILES_SELECTOR -DatasetMetadata = namedtuple('DatasetMetadata', ['num_numerical_features', - 'categorical_cardinalities']) - - -class DummyDataset: - def __init__(self, batch_size, num_numerical_features, categorical_feature_cardinalities, num_batches, num_workers): - cat_features_count = len( - categorical_feature_cardinalities) if categorical_feature_cardinalities is not None else 0 - num_features_count = num_numerical_features if num_numerical_features is not None else 0 - - self.numerical_features = tf.random.uniform(shape=[batch_size // num_workers, num_numerical_features], dtype=tf.float32) \ - if num_features_count else -1 - self.labels = tf.cast(tf.random.uniform(shape=[batch_size // num_workers, 1], maxval=2, dtype=tf.int32), tf.float32) - self.categorical_features = tf.concat( - [tf.random.uniform(shape=[batch_size, 1], maxval=cardinality, dtype=tf.int32) - for cardinality in categorical_feature_cardinalities], axis=1) if cat_features_count > 0 else -1 - self.num_batches = num_batches - self._iter = iter(self) - - def __next__(self): - return (self.numerical_features, self.categorical_features), self.labels - - def __len__(self): - return self.num_batches - - def op(self): - return self +import tqdm - def __iter__(self): - return self - - def get_next(self): - return self.__next__() +from .defaults import CATEGORICAL_CHANNEL, NUMERICAL_CHANNEL, LABEL_CHANNEL, DTYPE_SELECTOR +from .feature_spec import FeatureSpec, FEATURES_SELECTOR, FILES_SELECTOR, get_categorical_feature_type +DatasetMetadata = namedtuple('DatasetMetadata', ['num_numerical_features', + 'categorical_cardinalities']) fspec_type_to_tf_type = { 'int8': tf.int8, @@ -94,11 +66,15 @@ def __init__( batch_size: int = 1, numerical_features_enabled: bool = False, rank: int = 0, - world_size: int = 1 + world_size: int = 1, + concat_features: bool = False, + data_parallel_categoricals = False, ): + self._concat_features = concat_features self._feature_spec = feature_spec self._batch_size = batch_size + self._data_parallel_categoricals = data_parallel_categoricals local_batch_size = int(batch_size / world_size) batch_sizes_per_gpu = [local_batch_size] * world_size @@ -161,7 +137,7 @@ def _create_readers(self, feature_spec, local_categorical_feature_names, numeric elif first_feature in set_of_label_features: # Load label # We verified earlier that there is only one label feature - label_bytes_per_batch = np.dtype(np.bool).itemsize * self._batch_size + label_bytes_per_batch = np.dtype(bool).itemsize * self._batch_size self._label, batches = create_reader(path_to_open, label_bytes_per_batch) else: raise ValueError("Unknown chunk type") @@ -182,14 +158,14 @@ def op(self): pipeline = tf.data.Dataset.zip((self._label, self._numerical, self._categorical)) pipeline = pipeline.map(self.decode_batch, num_parallel_calls=tf.data.AUTOTUNE) pipeline = pipeline.batch(batch_size=1) - # Only one gpu is set to be visible + # Only one gpu is set to visible pipeline = pipeline.apply(tf.data.experimental.prefetch_to_device(f'/gpu:0')) pipeline = pipeline.unbatch() pipeline = pipeline.repeat() return pipeline @tf.function - def decode_batch(self, labels, numerical_features, categorical_features): + def decode_batch(self, labels, numerical_features, categorical_features, concat_features=False): labels = tf.io.decode_raw(labels, out_type=tf.int8) labels = labels[self.dp_begin_idx:self.dp_end_idx] @@ -200,12 +176,63 @@ def decode_batch(self, labels, numerical_features, categorical_features): numerical_features = numerical_features[self.dp_begin_idx:self.dp_end_idx, :] if self._categorical: - temp = [] + cat_data = [] for dtype, feature in zip(self._categorical_types_tf, categorical_features): feature = tf.io.decode_raw(feature, out_type=dtype) feature = tf.cast(feature, dtype=tf.int32) feature = tf.expand_dims(feature, axis=1) - temp.append(feature) - categorical_features = tf.concat(temp, axis=1) + feature = tf.reshape(feature, [self._batch_size, 1]) + if self._data_parallel_categoricals: + feature = feature[self.dp_begin_idx:self.dp_end_idx] + cat_data.append(feature) + if self._concat_features: + cat_data = tf.concat(cat_data, axis=1) + else: + cat_data = tuple(cat_data) + + return (numerical_features, cat_data), labels + + @staticmethod + def generate(src_train, src_test, feature_spec, dst_dir, dst_feature_spec, + max_batches_train, max_batches_test): + + categorical_sizes = feature_spec.get_categorical_sizes() + num_numerical = feature_spec.get_number_of_numerical_features() + feature_spec = FeatureSpec.get_default_feature_spec(number_of_numerical_features=num_numerical, + categorical_feature_cardinalities=categorical_sizes) + + feature_spec.to_yaml(output_path=os.path.join(dst_dir, dst_feature_spec)) + sources = [(src_train, 'train', max_batches_train), (src_test, 'test', max_batches_test)] + + cat_feature_types = [get_categorical_feature_type(cat_size) for cat_size in categorical_sizes] + + for src_dataset, split, max_batches in sources: + os.makedirs(os.path.join(dst_dir, split), exist_ok=True) + + categorical_fs = [] + for i in range(len(categorical_sizes)): + fs = open(os.path.join(dst_dir, split, f'cat_{i}.bin'), 'wb+') + categorical_fs.append(fs) + + label_f = open(os.path.join(dst_dir, split, 'label.bin'), 'wb+') + numerical_f = open(os.path.join(dst_dir, split, "numerical.bin"), "wb+") + + for batch_idx, src_batch in tqdm.tqdm(enumerate(src_dataset), + total=max_batches, + desc=f'Generating the {split} data'): + if batch_idx == max_batches: + break + + (numerical_features, categorical_features), label = src_batch + + for ftype, stream, feature in zip(cat_feature_types, categorical_fs, categorical_features): + if isinstance(feature, tf.RaggedTensor): + feature = feature.values + raw_data = feature.numpy().astype(ftype).tobytes() + stream.write(raw_data) + + label_f.write(label.numpy().astype(bool).tobytes()) + numerical_f.write(numerical_features.numpy().astype(np.float16).tobytes()) - return (numerical_features, categorical_features), labels + for stream in chain(*categorical_fs, [label_f, numerical_f]): + stream.close() diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/split_tfrecords_multihot_dataset.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/split_tfrecords_multihot_dataset.py new file mode 100644 index 000000000..081e4a03b --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/split_tfrecords_multihot_dataset.py @@ -0,0 +1,267 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import tensorflow as tf +import os +import glob +import json +import numpy as np + +import tqdm + +def serialize_composite(rt): + components = tf.nest.flatten(rt, expand_composites=True) + tensor = tf.stack([tf.io.serialize_tensor(t) for t in components]) + return tf.io.serialize_tensor(tensor) + + +def deserialize_composite(serialized, type_spec): + data = tf.io.parse_tensor(serialized, tf.string) + component_specs = tf.nest.flatten(type_spec, expand_composites=True) + components = [tf.io.parse_tensor(data[i], out_type=spec.dtype) + for i, spec in enumerate(component_specs)] + return tf.nest.pack_sequence_as(type_spec, components, expand_composites=True) + + +def length_filename(dataset_dir): + return f'{dataset_dir}/length.json' + + +class PrebatchStreamWriter: + def __init__(self, dst_dir, dtype, feature_name='data', multihot=False, batches_per_file=1): + self.dst_dir = dst_dir + os.makedirs(dst_dir, exist_ok=True) + self.dtype = dtype + self.feature_name = feature_name + self.multihot = multihot + self.batches_per_file = batches_per_file + self.writer = None + self._file_idx = -1 + self._batches_saved = 0 + + def _new_file(self): + if self.writer: + self.writer.close() + + self._file_idx += 1 + self.writer = tf.io.TFRecordWriter(os.path.join(self.dst_dir, f'data_{self._file_idx}.tfrecords')) + + def save(self, prebatch): + if self._batches_saved % self.batches_per_file == 0: + self._new_file() + + if self.multihot: + serialized = serialize_composite(tf.cast(prebatch, self.dtype)).numpy() + else: + if isinstance(prebatch, tf.RaggedTensor): + prebatch = prebatch.to_tensor() + + serialized = tf.io.serialize_tensor(tf.cast(prebatch, dtype=self.dtype)).numpy() + + features = tf.train.Features(feature={ + self.feature_name: tf.train.Feature(bytes_list=tf.train.BytesList(value=[serialized])) + }) + + example = tf.train.Example(features=features) + self.writer.write(example.SerializeToString()) + self._batches_saved += 1 + + def close(self): + self.writer.close() + + +def create_writer(dst_dir, dtype, feature_name='data', multihot=False, + format='tfrecords', num_features=1, batches_per_file=1): + if format == 'tfrecords': + writer = PrebatchStreamWriter(dst_dir=dst_dir, dtype=dtype, multihot=multihot, batches_per_file=batches_per_file) + metadata = dict(format=format, dtype=dtype.name, multihot=multihot, + feature_name=feature_name,num_features=num_features, batches_per_file=batches_per_file) + + with open(os.path.join(dst_dir, 'format.json'), 'w') as f: + json.dump(metadata, f) + return writer + else: + raise ValueError(f'Unknown feature format: {format}') + + +def create_reader(src_dir, batch_size, world_size=1, rank=0, data_parallel=True): + with open(os.path.join(src_dir, 'format.json')) as f: + metadata = json.load(f) + + if metadata['format'] == 'tfrecords': + reader = SingleFeatureTFRecordsFileReader(dst_dir=src_dir, batch_size=batch_size, + dtype=tf.dtypes.as_dtype(metadata['dtype']), + multihot=metadata['multihot'], + feature_name=metadata['feature_name'], + num_features=metadata['num_features'], + world_size=world_size, rank=rank, data_parallel=data_parallel) + + return reader + else: + raise ValueError(f'Unknown feature format: {metadata["format"]}') + + +class SingleFeatureTFRecordsFileReader: + def __init__(self, dst_dir, batch_size, dtype, rank=0, world_size=1, + num_features=1, feature_name='data', multihot=False, + data_parallel=True, parallel_calls=4): + self.filenames = glob.glob(os.path.join(dst_dir, 'data_*.tfrecords')) + self.feature_name = feature_name + self.multihot = multihot + self.batch_size = batch_size + self.num_features = num_features + self.dtype = dtype + self.feature_description = {self.feature_name: tf.io.FixedLenFeature([], tf.string, default_value='')} + self.data_parallel = data_parallel + self.parallel_calls = parallel_calls + + self.rank = rank + self.world_size = world_size + + if self.data_parallel: + local_batch_size = int(self.batch_size / world_size) + batch_sizes_per_gpu = [local_batch_size] * world_size + indices = tuple(np.cumsum([0] + list(batch_sizes_per_gpu))) + self.dp_begin_idx = indices[rank] + self.dp_end_idx = indices[rank + 1] + + def __len__(self): + pass + + def _data_parallel_split(self, x): + return x[self.dp_begin_idx:self.dp_end_idx, ...] + + def _parse_function(self, proto): + parsed = tf.io.parse_single_example(proto, self.feature_description) + + if self.multihot: + rt_spec = tf.RaggedTensorSpec(dtype=tf.int32, shape=[self.batch_size, None], + row_splits_dtype=tf.int32, ragged_rank=1) + tensor = parsed[self.feature_name] + tensor = deserialize_composite(serialized=tensor, type_spec=rt_spec) + else: + tensor = tf.io.parse_tensor(parsed[self.feature_name], out_type=self.dtype) + tensor = tf.reshape(tensor, shape=[self.batch_size, self.num_features]) + + if self.data_parallel: + tensor = self._data_parallel_split(tensor) + + return tensor + + def op(self): + num_parallel_reads = 8 + dataset = tf.data.TFRecordDataset(self.filenames, num_parallel_reads=num_parallel_reads) + dataset = dataset.map(self._parse_function, num_parallel_calls=self.parallel_calls, deterministic=True) + dataset = dataset.prefetch(buffer_size=1) + dataset = dataset.repeat() + return dataset + + +class SplitTFRecordsDataset: + def __init__(self, dataset_dir, feature_ids, num_numerical, batch_size, world_size, rank): + self.dataset_dir = dataset_dir + self.feature_ids = feature_ids + self.num_numerical = num_numerical + self.batch_size = batch_size + self.world_size = world_size + self.rank = rank + + self.numerical_reader = create_reader(src_dir=os.path.join(dataset_dir, 'numerical'), + world_size=world_size, rank=rank, batch_size=batch_size, + data_parallel=True) + + self.label_reader = create_reader(src_dir=os.path.join(dataset_dir, 'label'), + world_size=world_size, rank=rank, data_parallel=True, + batch_size=batch_size) + + self.categorical_readers = [] + for feature_id in feature_ids: + reader = create_reader(src_dir=os.path.join(dataset_dir, f'categorical_{feature_id}'), + batch_size=batch_size, data_parallel=False) + self.categorical_readers.append(reader) + + filename = length_filename(self.dataset_dir) + with open(filename) as f: + self.length = json.load(f) + + def __len__(self): + return self.length + + def op(self): + categorical_tf_datasets = tuple(d.op() for d in self.categorical_readers) + features_datasets = (self.numerical_reader.op(), categorical_tf_datasets) + structure_to_zip = (features_datasets, self.label_reader.op()) + dataset = tf.data.Dataset.zip(structure_to_zip) + return dataset + + @staticmethod + def generate(src_train, src_test, feature_spec, dst_dir, dst_feature_spec, prebatch_size, max_batches_train, max_batches_test): + local_table_sizes = feature_spec.get_categorical_sizes() + names = feature_spec.get_categorical_feature_names() + local_table_hotness = [feature_spec.feature_spec[name].get('hotness', 1) for name in names] + + os.makedirs(dst_dir, exist_ok=True) + num_files = 1 + + feature_spec.to_yaml(output_path=os.path.join(dst_dir, dst_feature_spec)) + sources = [(src_train, 'train', max_batches_train), (src_test, 'test', max_batches_test)] + + for src, dst_suffix, max_batches in sources: + num_batches = min(len(src), max_batches) + if num_batches % num_files != 0: + raise ValueError('The length of the dataset must be evenly divided by the number of TFRecords files') + + dst_subdir = os.path.join(dst_dir, dst_suffix) + numerical_writer = create_writer(dst_dir=os.path.join(dst_subdir, 'numerical'), dtype=tf.float16, + num_features=feature_spec.get_number_of_numerical_features(), + batches_per_file=num_batches // num_files) + + label_writer = create_writer(dst_dir=os.path.join(dst_subdir, 'label'), dtype=tf.int8, + batches_per_file=num_batches // num_files) + + categorical_writers = [] + for i, (hotness, cardinality) in enumerate(zip(local_table_hotness, local_table_sizes)): + # TODO: possibly optimize the dtype by using cardinality here + writer = create_writer(dst_dir=os.path.join(dst_subdir, f'categorical_{i}'), dtype=tf.int32, + multihot=hotness > 1, + batches_per_file=num_batches // num_files) + categorical_writers.append(writer) + + with open(length_filename(dst_subdir), 'w') as f: + json.dump(num_batches, f) + + for batch_idx, batch in tqdm.tqdm(enumerate(src.op()), + total=max_batches, + desc=f'Generating the {dst_suffix} data'): + + print('writing batch: ', batch_idx) + if batch_idx == max_batches: + break + print(batch_idx) + (numerical, categorical), label = batch + if label.shape[0] != prebatch_size: + raise ValueError(f'Source dataset batch size ({label.shape[0]}) ' + f'different from the prebatch size ({prebatch_size}). Unsupported.') + numerical_writer.save(numerical) + label_writer.save(label) + for writer, feature in zip(categorical_writers, categorical): + writer.save(feature) + + numerical_writer.close() + label_writer.close() + for writer in categorical_writers: + writer.close() diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/synthetic_dataset.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/synthetic_dataset.py new file mode 100644 index 000000000..3a6e34be2 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/synthetic_dataset.py @@ -0,0 +1,108 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import tensorflow as tf +import numpy as np + + +def power_law(k_min, k_max, alpha, x): + """convert uniform distribution to power law distribution""" + gamma = 1 - alpha + y = pow(x * (pow(k_max, gamma) - pow(k_min, gamma)) + pow(k_min, gamma), 1.0 / gamma) + return y.astype(np.int32) + + +def gen_power_law_data(batch_size, hotness, num_rows, alpha, variable_hotness): + """naive power law distribution generator + NOTE: Repetition is allowed in multi hot data. + NOTE: The resulting values are sorted by frequency, that is, the index=0 is the most frequently occurring etc. + """ + if variable_hotness: + # at least one element fetched for each feature + row_lengths = power_law(1, hotness, alpha, np.random.rand(batch_size)) + total_elements = np.sum(row_lengths) + y = power_law(1, num_rows + 1, alpha, np.random.rand(total_elements)) - 1 + result = tf.RaggedTensor.from_row_lengths(values=y, row_lengths=row_lengths) + else: + y = power_law(1, num_rows + 1, alpha, np.random.rand(batch_size * hotness)) - 1 + row_lengths = tf.ones(shape=[batch_size], dtype=tf.int32) * hotness + result = tf.RaggedTensor.from_row_lengths(values=y, row_lengths=row_lengths) + return result + + +class SyntheticDataset: + def __init__(self, batch_size, num_numerical_features, categorical_feature_cardinalities, + categorical_feature_hotness, categorical_feature_alpha, num_workers, variable_hotness=True, + constant=False, num_batches=int(1e9)): + self.batch_size = batch_size + self.num_numerical_features = num_numerical_features + self.categorical_feature_cardinalities = categorical_feature_cardinalities + self.categorical_feature_hotness = categorical_feature_hotness + self.categorical_feature_alpha = categorical_feature_alpha + self.variable_hotness = variable_hotness + self.num_workers = num_workers + self.num_batches = num_batches + + if len(categorical_feature_hotness) != len(categorical_feature_cardinalities): + raise ValueError("DummyDataset mismatch between cardinalities and hotness lengths." + f"Got {len(categorical_feature_cardinalities)} cardinalities and " + f"{len(categorical_feature_hotness)} hotnesses") + + self.cat_features_count = len( + categorical_feature_cardinalities) if categorical_feature_cardinalities is not None else 0 + self.num_features_count = num_numerical_features if num_numerical_features is not None else 0 + + self.constant = constant + if self.constant: + (self.numerical_features, self.categorical_features), self.labels = self._generate() + + def _generate(self): + + numerical_features = tf.random.uniform(shape=[self.batch_size // self.num_workers, self.num_numerical_features], + dtype=tf.float32) if self.num_features_count else -1 + labels = tf.cast(tf.random.uniform(shape=[self.batch_size // self.num_workers, 1], + maxval=2, dtype=tf.int32), tf.float32) + + categorical_features = [] + for cardinality, hotness, alpha in zip(self.categorical_feature_cardinalities, + self.categorical_feature_hotness, + self.categorical_feature_alpha): + + feature = gen_power_law_data(batch_size=self.batch_size, hotness=hotness, + num_rows=cardinality, alpha=alpha, + variable_hotness=self.variable_hotness) + + categorical_features.append(feature) + return (numerical_features, categorical_features), labels + + def __next__(self): + if self.constant: + return (self.numerical_features, self.categorical_features), self.labels + else: + return self._generate() + + def __len__(self): + return self.num_batches + + def op(self): + return self + + def __iter__(self): + return self + + def get_next(self): + return self.__next__() + + diff --git a/TensorFlow2/Recommendation/DLRM/transcode.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/transcode.py similarity index 96% rename from TensorFlow2/Recommendation/DLRM/transcode.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/transcode.py index d3ce4f026..8a31961f9 100644 --- a/TensorFlow2/Recommendation/DLRM/transcode.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/transcode.py @@ -19,8 +19,8 @@ import numpy as np import pandas as pd -from feature_spec import FeatureSpec, get_categorical_feature_type -from defaults import CATEGORICAL_CHANNEL, NUMERICAL_CHANNEL, LABEL_CHANNEL, CARDINALITY_SELECTOR +from .feature_spec import FeatureSpec, get_categorical_feature_type +from .defaults import CATEGORICAL_CHANNEL, NUMERICAL_CHANNEL, LABEL_CHANNEL, CARDINALITY_SELECTOR def parse_args(): @@ -116,7 +116,7 @@ def main(): # Append them to the binary files numerical_f.write(numerical_df.values.astype(np.float16).tobytes()) - label_f.write(label_df.values.astype(np.bool).tobytes()) + label_f.write(label_df.values.astype(bool).tobytes()) categorical_arr = categorical_df.values for cat_idx, cat_feature_type in enumerate(categorical_feature_types): diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/transcribe.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/transcribe.py new file mode 100644 index 000000000..e16279fa4 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dataloading/transcribe.py @@ -0,0 +1,86 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import os +import argparse +from .feature_spec import FeatureSpec +from .dataloader import create_input_pipelines +from .split_tfrecords_multihot_dataset import SplitTFRecordsDataset +from .raw_binary_dataset import TfRawBinaryDataset + + +def parse_args(): + p = argparse.ArgumentParser(description="Transcribe from one dataset format to another") + p.add_argument('--src_dataset_path', default='synthetic_dataset', type=str, help='Path to the source directory') + p.add_argument('--src_dataset_type', default='tf_raw', + choices=['tf_raw', 'synthetic', 'binary_multihot', 'tfrecords_multihot', 'nvt', 'split_tfrecords'], + help='The type of the source dataset') + p.add_argument('--src_feature_spec', default='feature_spec.yaml', type=str, help='Feature spec filename') + p.add_argument('--src_batch_size', default=65536, type=int, help='Batch size of the source dataset') + p.add_argument('--src_synthetic_dataset_use_feature_spec', action='http://github.com/store_true', + help='Use feature spec for the synthetic dataset') + + p.add_argument('--dst_dataset_path', default='synthetic_dataset', type=str, help='Path to the destination directory') + p.add_argument('--dst_prebatch_size', default=65536, type=int, help='Prebatch size for the dst dataset') + p.add_argument('--dst_feature_spec', type=str, default='feature_spec.yaml', + help='Dst feature spec filename') + p.add_argument('--dst_dataset_type', default='split_tfrecords', + choices=['tf_raw', 'synthetic', 'binary_multihot', 'tfrecords_multihot', 'nvt', 'split_tfrecords'], + help='The type of the source dataset') + + p.add_argument('--max_batches_train', default=-1, type=int, + help='Max number of train batches to transcribe. Passing -1 will transcribe all the data.') + p.add_argument('--max_batches_test', default=-1, type=int, + help='Max number of test batches to transcribe. Passing -1 will transcribe all the data.') + p.add_argument('--train_only', action='http://github.com/store_true', default=False, help='Only transcribe the train dataset.') + return p.parse_args() + + +def main(): + args = parse_args() + + fspec_path = os.path.join(args.src_dataset_path, args.src_feature_spec) + feature_spec = FeatureSpec.from_yaml(fspec_path) + table_ids = list(range(len(feature_spec.get_categorical_sizes()))) + + src_train, src_test = create_input_pipelines(dataset_type=args.src_dataset_type, dataset_path=args.src_dataset_path, + train_batch_size=args.src_batch_size, + test_batch_size=args.src_batch_size, + table_ids=table_ids, feature_spec=args.src_feature_spec, + rank=0, world_size=1) + + os.makedirs(args.dst_dataset_path, exist_ok=True) + + if args.dst_dataset_type == 'split_tfrecords': + SplitTFRecordsDataset.generate(src_train=src_train, src_test=src_test, feature_spec=feature_spec, + dst_dir=args.dst_dataset_path, dst_feature_spec=args.dst_feature_spec, + prebatch_size=args.dst_prebatch_size, max_batches_train=args.max_batches_train, + max_batches_test=args.max_batches_test) + elif args.dst_dataset_type == 'tf_raw': + TfRawBinaryDataset.generate(src_train=src_train, src_test=src_test, feature_spec=feature_spec, + dst_dir=args.dst_dataset_path, dst_feature_spec=args.dst_feature_spec, + max_batches_train=args.max_batches_train, max_batches_test=args.max_batches_test) + + else: + raise ValueError(f'Unimplemented dst_dataset_type: {args.dst_dataset_type}') + + + print('Done.') + + +if __name__ == '__main__': + main() diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dcnv2.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dcnv2.py new file mode 100644 index 000000000..848e2a0f8 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dcnv2.py @@ -0,0 +1,50 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +from absl import app, flags + + +def define_dcnv2_specific_flags(): + flags.DEFINE_integer("batch_size", default=64 * 1024, help="Batch size used for training") + flags.DEFINE_integer("valid_batch_size", default=64 * 1024, help="Batch size used for validation") + flags.DEFINE_list("top_mlp_dims", [1024, 1024, 512, 256, 1], "Linear layer sizes for the top MLP") + flags.DEFINE_list("bottom_mlp_dims", [512, 256, 128], "Linear layer sizes for the bottom MLP") + flags.DEFINE_string("embedding_dim", default='128', help='Number of columns in the embedding tables') + flags.DEFINE_enum("optimizer", default="adam", enum_values=['sgd', 'adam'], + help='The optimization algorithm to be used.') + flags.DEFINE_enum("interaction", default="cross", enum_values=["dot_custom_cuda", "dot_tensorflow", "cross"], + help="Feature interaction implementation to use") + flags.DEFINE_float("learning_rate", default=0.0001, help="Learning rate") + flags.DEFINE_float("beta1", default=0.9, help="Beta1 for the Adam optimizer") + flags.DEFINE_float("beta2", default=0.999, help="Bea2 for the Adam optimizer") + flags.DEFINE_integer("warmup_steps", default=100, + help='Number of steps over which to linearly increase the LR at the beginning') + flags.DEFINE_integer("decay_start_step", default=48000, help='Optimization step at which to start the poly LR decay') + flags.DEFINE_integer("decay_steps", default=24000, help='Number of steps over which to decay from base LR to 0') + + flags.DEFINE_integer("num_cross_layers", default=3, help='Number of cross layers for DCNv2') + flags.DEFINE_integer("cross_layer_projection_dim", default=512, help='Projection dimension used in the cross layers') + + +define_dcnv2_specific_flags() +import main + +def _main(argv): + main.main() + +if __name__ == '__main__': + app.run(_main) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/__init__.py new file mode 100644 index 000000000..4fda2b94d --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deploy.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deploy.py new file mode 100644 index 000000000..38214b7d3 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deploy.py @@ -0,0 +1,249 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import argparse +import os + +import tensorflow as tf +import horovod.tensorflow as hvd + +import deployment.tf +import deployment.hps + + +def clear_and_create_directory(repo_path): + print("creating directory:", repo_path) + os.makedirs(repo_path, exist_ok=True) + + +def create_model_repo(dst, sparse_model_name, dense_model_name, ensemble_name): + clear_and_create_directory(dst) + created = [] + for name in sparse_model_name, dense_model_name, ensemble_name: + d = os.path.join(dst, name) + clear_and_create_directory(d) + created.append(d) + return created + + +def set_tf_memory_growth(): + physical_devices = tf.config.list_physical_devices("GPU") + for d in physical_devices: + tf.config.experimental.set_memory_growth(d, True) + + +def main(): + parser = argparse.ArgumentParser(description="") + parser.add_argument( + "--checkpoint-dir", type=str, help="Source directory with a checkpoint" + ) + parser.add_argument( + "--model-repository-path", + type=str, + help="Destination directory with Triton model repository", + ) + parser.add_argument( + "--model-name", + type=str, + help="The name of the model used for inference.", + required=True, + ) + parser.add_argument( + "--sparse-model-name", + type=str, + default='sparse' + ) + parser.add_argument( + "--dense-model-name", + type=str, + default='dense' + ) + parser.add_argument( + "--model-version", + type=int, + help="The version of the model used for inference.", + required=False, + default=1, + ) + parser.add_argument( + "--dense-format", + type=str, + help="Target format of dense model part in ensemble.", + choices=["tf-savedmodel", "onnx", "trt"], + required=True, + default="tf-savedmodel", + ) + parser.add_argument( + "--sparse-format", + type=str, + help="Target format of dense model part in ensemble.", + choices=["tf-savedmodel", "hps"], + required=True, + default="tf-savedmodel", + ) + parser.add_argument( + "--model-precision", + type=str, + help="Target precision of dense model part in ensemble.", + choices=["fp16", "fp32"], + required=True, + default="fp32", + ) + parser.add_argument( + "--max-batch-size", + type=int, + help="The maximal batch size for deployed model.", + required=False, + default=32768, + ) + parser.add_argument( + "--trt-optimal-batch-size", + type=int, + help="Batch size to optimize TensorRT performance for.", + required=False, + default=1024, + ) + parser.add_argument( + "--memory-threshold-gb", + type=int, + help="Amount of memory in GB after reaching which CPU offloading will be used", + required=False, + default=70, + ) + parser.add_argument( + "--engine-count-per-device", + type=int, + default=1, + help="Number of model instances per GPU", + ) + parser.add_argument( + "--num_gpus", + type=int, + default=1, + help="Number of GPUs to deploy HPS onto", + ) + parser.add_argument( + "--fused_embedding", + action="http://github.com/store_true", + default=False, + help="Fuse the embedding table together for better GPU utilization.", + ) + parser.add_argument( + "--hps_gpucacheper", + type=float, + default=0.25, + help="Fraction of the embeddings to store in GPU cache.", + ) + parser.add_argument( + "--server-url", + type=str, + default="grpc://127.0.0.1:8001", + help="Url of Triton Inference Server", + required=False, + ) + parser.add_argument( + "--load-model", + action="http://github.com/store_true", + default=False, + help="Call load model Triton endpoint after creating model store.", + ) + parser.add_argument( + "--load-model-timeout-s", + type=int, + default=120, + help="Timeout of load model operation.", + required=False, + ) + parser.add_argument( + "--verbose", + action="http://github.com/store_true", + default=False, + help="Enable verbose logging", + ) + parser.add_argument( + "--cpu", + action="http://github.com/store_true", + default=False, + help="Run the entire model on CPU", + ) + parser.add_argument( + "--monolithic", + action="http://github.com/store_true", + default=False, + help="Don't use the ensemble paradigm. Instead, save everything into a single large SavedModel file", + ) + args = parser.parse_args() + + hvd.init() + + set_tf_memory_growth() + + deployment_package = deployment.hps if args.sparse_format == 'hps' else deployment.tf + + if args.monolithic: + deployment_package.deploy_monolithic(sparse_src=os.path.join(args.checkpoint_dir, "sparse"), + dense_src=os.path.join(args.checkpoint_dir, "dense"), + dst=args.model_repository_path, + model_name='dlrm', + max_batch_size=65536, + engine_count_per_device=1, + num_gpus=1, + version="1", + cpu=args.cpu, + model_precision='fp32') + return + + sparse_dst, dense_dst, ensemble_dst = create_model_repo( + dst=args.model_repository_path, ensemble_name=args.model_name, + sparse_model_name=args.sparse_model_name, dense_model_name=args.dense_model_name + ) + + num_numerical_features = deployment_package.deploy_dense( + src=os.path.join(args.checkpoint_dir, "dense"), + dst=dense_dst, + model_name=args.dense_model_name, + model_format=args.dense_format, + model_precision=args.model_precision, + max_batch_size=args.max_batch_size, + trt_optimal_batch_size=args.trt_optimal_batch_size, + engine_count_per_device=args.engine_count_per_device, + ) + num_cat_features = deployment_package.deploy_sparse( + src=os.path.join(args.checkpoint_dir, "sparse"), + dst=sparse_dst, + model_name=args.sparse_model_name, + num_gpus=args.num_gpus, + fused=args.fused_embedding, + max_batch_size=args.max_batch_size, + gpucacheper=args.hps_gpucacheper, + engine_count_per_device=args.engine_count_per_device, + memory_threshold_gb=args.memory_threshold_gb + ) + deployment_package.deploy_ensemble( + dst=ensemble_dst, + model_name=args.model_name, + sparse_model_name=args.sparse_model_name, + dense_model_name=args.dense_model_name, + num_cat_features=num_cat_features, + num_numerical_features=num_numerical_features, + version=args.model_version, + max_batch_size=args.max_batch_size, + ) + + +if __name__ == "__main__": + main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/__init__.py similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/__init__.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/__init__.py diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/args.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/args.py similarity index 76% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/args.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/args.py index f6876b80f..2e214cb5d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/args.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/args.py @@ -15,9 +15,7 @@ import argparse import inspect import logging -from typing import Callable, Dict, Optional, Union - -from model_navigator.utils.cli import is_dict_generic, is_list_generic, is_optional_generic +from typing import Callable, Dict, List, Optional, Union from .core import GET_ARGPARSER_FN_NAME, load_from_file @@ -55,7 +53,9 @@ def add_args_for_fn_signature(parser, fn) -> argparse.ArgumentParser: is_optional = is_optional_generic(parameter.annotation) if is_optional: - annotation = parameter.annotation.__args__[0] # Optional[cls] will be changed into Union[cls, None] + annotation = parameter.annotation.__args__[ + 0 + ] # Optional[cls] will be changed into Union[cls, None] else: annotation = parameter.annotation @@ -92,7 +92,11 @@ def __init__(self, cls_or_fn, module_path: Optional[str] = None): self._cls_or_fn = cls_or_fn init_method_name = "__init__" - self._handle = cls_or_fn if inspect.isfunction(cls_or_fn) else getattr(cls_or_fn, init_method_name, None) + self._handle = ( + cls_or_fn + if inspect.isfunction(cls_or_fn) + else getattr(cls_or_fn, init_method_name, None) + ) input_is_python_file = module_path and module_path.endswith(".py") self._input_path = module_path if input_is_python_file else None self._required_fn_name_for_signature_parsing = getattr( @@ -111,7 +115,9 @@ def get_args(self, args: argparse.Namespace): tmp_parser = argparse.ArgumentParser(allow_abbrev=False) self._update_argparser(tmp_parser) custom_names = [ - p.dest.replace("-", "_") for p in tmp_parser._actions if not isinstance(p, argparse._HelpAction) + p.dest.replace("-", "_") + for p in tmp_parser._actions + if not isinstance(p, argparse._HelpAction) ] custom_params = {n: getattr(args, n) for n in custom_names} filtered_args = {**filtered_args, **custom_params} @@ -125,12 +131,40 @@ def from_args(self, args: Union[argparse.Namespace, Dict]): def _update_argparser(self, parser): label = "argparser_update" if self._input_path: - update_argparser_handle = load_from_file(self._input_path, label=label, target=GET_ARGPARSER_FN_NAME) + update_argparser_handle = load_from_file( + self._input_path, label=label, target=GET_ARGPARSER_FN_NAME + ) if update_argparser_handle: update_argparser_handle(parser) elif self._required_fn_name_for_signature_parsing: fn_handle = load_from_file( - self._input_path, label=label, target=self._required_fn_name_for_signature_parsing + self._input_path, + label=label, + target=self._required_fn_name_for_signature_parsing, ) if fn_handle: add_args_for_fn_signature(parser, fn_handle) + + +def is_optional_generic(type_): + from typing_inspect import is_optional_type + + return is_optional_type(type_) + + +def is_list_generic(type_): + from typing_inspect import get_args, get_origin, is_generic_type + + is_optional = is_optional_generic(type_) + if is_optional: + type_, _ = get_args(type_, evaluate=True) + return is_generic_type(type_) and get_origin(type_) in [list, List] + + +def is_dict_generic(type_): + from typing_inspect import get_args, get_origin, is_generic_type + + is_optional = is_optional_generic(type_) + if is_optional: + type_, _ = get_args(type_, evaluate=True) + return is_generic_type(type_) and get_origin(type_) in [dict, Dict] diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/core.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/core.py new file mode 100644 index 000000000..fd1596445 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/core.py @@ -0,0 +1,109 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import abc +import importlib +import logging +import os +import time +from enum import Enum +from pathlib import Path +from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union + +import numpy as np + +LOGGER = logging.getLogger(__name__) +DATALOADER_FN_NAME = "get_dataloader_fn" +GET_MODEL_FN_NAME = "get_model" +GET_SERVING_INPUT_RECEIVER_FN = "get_serving_input_receiver_fn" +GET_ARGPARSER_FN_NAME = "update_argparser" + + +def load_from_file(file_path, label, target): + spec = importlib.util.spec_from_file_location(name=label, location=file_path) + my_module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(my_module) # pytype: disable=attribute-error + return getattr(my_module, target, None) + + +class BaseMetricsCalculator(abc.ABC): + required_fn_name_for_signature_parsing: Optional[str] = None + + def calc( + self, + *, + ids: List[Any], + y_pred: Dict[str, np.ndarray], + x: Optional[Dict[str, np.ndarray]], + y_real: Optional[Dict[str, np.ndarray]], + ) -> Dict[str, float]: + """ + Calculates error/accuracy metrics + Args: + ids: List of ids identifying each sample in the batch + y_pred: model output as dict where key is output name and value is output value + x: model input as dict where key is input name and value is input value + y_real: input ground truth as dict where key is output name and value is output value + Returns: + dictionary where key is metric name and value is its value + """ + pass + + @abc.abstractmethod + def update( + self, + ids: List[Any], + y_pred: Dict[str, np.ndarray], + x: Optional[Dict[str, np.ndarray]], + y_real: Optional[Dict[str, np.ndarray]], + ): + pass + + @property + @abc.abstractmethod + def metrics(self) -> Dict[str, Any]: + pass + + +class ShapeSpec(NamedTuple): + min: Tuple + opt: Tuple + max: Tuple + + +class MeasurementMode(Enum): + """ + Available measurement stabilization modes + """ + + COUNT_WINDOWS = "count_windows" + TIME_WINDOWS = "time_windows" + + +class EvaluationMode(Enum): + """ + Available evaluation modes + """ + + OFFLINE = "offline" + ONLINE = "online" + + +class OfflineMode(Enum): + """ + Available offline mode for memory + """ + + SYSTEM = "system" + CUDA = "cuda" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/dump.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/dump.py similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/dump.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/dump.py diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/report.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/report.py similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/report.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/report.py diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_client.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_client.py new file mode 100644 index 000000000..609130937 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_client.py @@ -0,0 +1,310 @@ +# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging +import time +from enum import Enum +from typing import Any, Dict, Optional + +# pytype: disable=import-error +from .utils import parse_server_url + +try: + import tritonclient.grpc as grpc_client + from tritonclient import utils as client_utils # noqa: F401 +except ImportError: + try: + import tritonclientutils as client_utils # noqa: F401 + import tritongrpcclient as grpc_client + except ImportError: + client_utils = None + grpc_client = None + +try: + import tritonclient.http as http_client +except (ImportError, RuntimeError): + try: + import tritonhttpclient as http_client + except (ImportError, RuntimeError): + http_client = None + +# pytype: enable=import-error + +LOGGER = logging.getLogger(__name__) + + +class TritonServerNotReadyException(Exception): + pass + + +# TODO: in which state "native" warm-up takes place? +class ModelState(Enum): + """Describe model state in Triton. + + Attributes: + LOADING: Loading of model + UNLOADING: Unloading of model + UNAVAILABLE: Model is missing or could not be loaded + READY: Model is ready for inference + """ + + LOADING = "LOADING" + UNLOADING = "UNLOADING" + UNAVAILABLE = "UNAVAILABLE" + READY = "READY" + + +class TritonClientProtocol(Enum): + """Describe protocol with which client communicates with Triton""" + + GRPC = "grpc" + HTTP = "http" + + +# TODO: How to obtain models that are available but not loaded yet? +# TODO: encode model_name and model_version as for ex. model_name/model_version (here and in many other places) +# TODO: How to obtain server model loading mode +class TritonClient: + """Provide high-level API for communicating with Triton. + + Usage: + + >>> client = TritonClient("grpc://127.0.0.1:8001") + >>> client.load_model("ResNet50") + + Above sample loads model on Triton and run inference iterating over provided dataloader. + + Args: + server_url: url where Triton is binded in format `://
:` + verbose: provide verbose logs from tritonclient library + + Attributes: + client: handle to low-level API client obtained from tritonclient python package + + Raises: + RuntimeError: in case of missing tritonclient library for selected protocol + or problems with connecting to Triton or its not in ready state yet. + ValueError: in case of errors in parsing provided server_url. Example source of errors are: missing protocol unknown protocol was requested. + InferenceServerClient: in case of error in processing initial requests on server side + """ + + def __init__(self, server_url: str, *, verbose: bool = False): + self.server_url = server_url + self._verbose = verbose + + self.client = self._create_client(server_url=server_url, verbose=verbose) + + def wait_for_server_ready(self, timeout: int): + """ + Parameters + ---------- + timeout : int + timeout in seconds to send a ready status + request to the server before raising + an exception + Raises + ------ + TritonModelAnalyzerException + If server readiness could not be + determined in given num_retries + """ + + retries = timeout + while retries > 0: + try: + if self.client.is_server_ready() and self.client.is_server_live(): + return + else: + time.sleep(1) + retries -= 1 + except Exception as e: + time.sleep(1) + retries -= 1 + if retries == 0: + return TritonServerNotReadyException(e) + raise TritonServerNotReadyException( + "Could not determine server readiness. " "Number of retries exceeded." + ) + + def get_server_metadata(self): + """Returns `server metadata `_. + + >>> client.get_server_metadata() + {name: "triton", version: "2.5.0", extensions: ["classification", "sequence", "model_repository", "schedule_policy", "model_configuration", "system_shared_memory", "cuda_shared_memory", "binary_tensor_data", "statistics"} + + Returns: + Dictionary with server metadata. + + Raises: + InferenceServerClient: in case of error in processing request on server side + """ + server_metadata = self.client.get_server_metadata() + server_metadata = self._format_response(server_metadata) + return server_metadata + + def get_model_metadata(self, model_name: str, model_version: Optional[str] = None): + """Returns `model metadata `_. + + Args: + model_name: name of the model which metadata is requested to obtain. + model_version: version of the model which metadata is requested to obtain. + + Returns: + Dictionary with model metadata. + + Raises: + InferenceServerClient: in case of error in processing request on server side. + """ + model_metadata = self.client.get_model_metadata(model_name, model_version) + model_metadata = self._format_response(model_metadata) + return model_metadata + + def load_model(self, model_name: str) -> None: + """Requests that a model be loaded into Triton, or reloaded if the model is already loaded. + + Args: + model_name: name of the model to load + + Raises: + InferenceServerException: in case of error in processing request on server side. + """ + self.client.load_model(model_name) + + def wait_for_model( + self, + *, + model_name: str, + model_version: str, + timeout_s: int = 120, + check_interval_s: int = 5, + ) -> Dict[str, Any]: + """Iteratively check for model state until model is ready or unavailable. + + Args: + model_name: name of the model to wait for + model_version: version of the model to wait for + timeout_s: how long in seconds to wait till model is in ready or in unavailable state + check_interval_s: time intervals in seconds at which state of model is should be checked + + Returns: + Dictionary with model metadata. + + Raises: + RuntimeError: in case model is not ready yet (is marked unavailable or timeout has been reached) + InferenceServerException: in case of error in processing request on server side. + """ + + def _shall_wait(model_state: ModelState) -> bool: + return model_state not in [ModelState.UNAVAILABLE, ModelState.READY] + + elapsed_time_s = 0 + start_time_s = time.time() + state = self.get_model_state(model_name, model_version) + while elapsed_time_s < timeout_s and _shall_wait(state): + LOGGER.info( + f"waiting for model... {elapsed_time_s:.0f}/{timeout_s} state={state}" + ) + time.sleep(check_interval_s) + state = self.get_model_state(model_name, model_version) + elapsed_time_s = time.time() - start_time_s + + if not self.client.is_model_ready(model_name): + raise RuntimeError( + f"Model {model_name} requested to be loaded, but is not ready" + ) + + model_metadata = self.client.get_model_metadata(model_name) + model_metadata = self._format_response(model_metadata) + return model_metadata + + def get_model_state(self, model_name: str, model_version: str) -> ModelState: + """Obtains the state of a model on Triton. + + Args: + model_name: name of the model which state is requested to obtain. + model_version: version of the model which state is requested to obtain. + + Returns: + Requested model state. + + Raises: + InferenceServerException: in case of error in processing request on server side. + """ + + def handle_http_response(models): + models_states = {} + for model in models: + if not model.get("version"): + continue + + model_state = ( + ModelState(model["state"]) + if model.get("state") + else ModelState.LOADING + ) + models_states[(model["name"], model["version"])] = model_state + + return models_states + + def handle_grpc_response(models): + models_states = {} + for model in models: + if not model.version: + continue + + model_state = ( + ModelState(model.state) if model.state else ModelState.LOADING + ) + models_states[(model.name, model.version)] = model_state + + return models_states + + repository_index = self.client.get_model_repository_index() + if isinstance(repository_index, list): + models_states = handle_http_response(models=repository_index) + else: + models_states = handle_grpc_response(models=repository_index.models) + + return models_states.get((model_name, model_version), ModelState.UNAVAILABLE) + + def _format_response(self, response): + if not isinstance(response, dict): + response = json.loads( + grpc_client.MessageToJson(response, preserving_proto_field_name=True) + ) + return response + + def _create_client(self, server_url: str, verbose: bool): + protocol, host, port = parse_server_url(http://github.com/server_url) + if protocol == TritonClientProtocol.HTTP and http_client is None: + raise RuntimeError( + "Could not obtain Triton HTTP client. Install extras while installing tritonclient wheel. " + "Example installation call: " + "find /workspace/install/python/ -iname triton*manylinux*.whl -exec pip install {}[all] \\;" + ) + + LOGGER.debug(f"Connecting to {server_url}") + + client_lib = { + TritonClientProtocol.HTTP.value: http_client, + TritonClientProtocol.GRPC.value: grpc_client, + }[protocol.value] + server_url = f"{host}:{port}" + + # pytype: disable=attribute-error + client = client_lib.InferenceServerClient(url=server_url, verbose=verbose) + # pytype: enable=attribute-error + + return client diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/__init__.py similarity index 91% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/__init__.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/__init__.py index 54b89998e..800d22f6d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/__init__.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/__init__.py @@ -11,3 +11,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from .runner import TritonPerformanceRunner # noqa: F401 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/containers/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/__init__.py similarity index 84% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/containers/__init__.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/__init__.py index 6aead0bc6..2f5af5170 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/containers/__init__.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/__init__.py @@ -11,4 +11,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from .triton_server_container import TritonServerContainer +from .runner import PerfAnalyzerRunner # noqa: F401 +from .warmup import PerfAnalyzerWarmupRunner # noqa: F401 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/exceptions.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/exceptions.py similarity index 91% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/exceptions.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/exceptions.py index 8947a98e3..9fd46bda1 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/exceptions.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/exceptions.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,7 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -class ModelAnalyzerException(Exception): + + + +class PerfAnalyzerException(Exception): def __init__(self, message: str): self._message = message diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/perf_analyzer.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/perf_analyzer.py similarity index 62% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/perf_analyzer.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/perf_analyzer.py index 193619be4..a82958d97 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/perf_analyzer.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/perf_analyzer.py @@ -16,6 +16,8 @@ from subprocess import PIPE, CalledProcessError, Popen # method from PEP-366 to support relative import in executed modules +from typing import List, Optional + if __package__ is None: __package__ = pathlib.Path(__file__).parent.name @@ -34,7 +36,7 @@ class PerfAnalyzer: with perf_analyzer. """ - def __init__(self, config): + def __init__(self, config, timeout: Optional[int]): """ Parameters ---------- @@ -44,7 +46,8 @@ def __init__(self, config): """ self.bin_path = "perf_analyzer" self._config = config - self._output = str() + self._output = "" + self._timeout = timeout def run(self): """ @@ -62,31 +65,23 @@ def run(self): PerfAnalyzerException If subprocess throws CalledProcessError """ + self._output = "" + for _ in range(MAX_INTERVAL_CHANGES): command = [self.bin_path] command += self._config.to_cli_string().replace("=", " ").split() LOGGER.debug(f"Perf Analyze command: {command}") - try: - process = Popen(command, start_new_session=True, stdout=PIPE, encoding="utf-8") - streamed_output = "" - while True: - output = process.stdout.readline() - if output == "" and process.poll() is not None: - break - if output: - streamed_output += output - print(output.rstrip()) - - self._output += streamed_output - result = process.poll() - if result != 0: - raise CalledProcessError(returncode=result, cmd=command, output=streamed_output) + if not self._timeout: + LOGGER.debug("Perf Analyze command timeout not set") + else: + LOGGER.debug(f"Perf Analyze command timeout: {self._timeout} [s]") + try: + self._run_with_stream(command=command) return - except CalledProcessError as e: - if self._faild_with_measruement_inverval(e.output): + if self._failed_with_measurement_inverval(e.output): if self._config["measurement-mode"] is None or self._config["measurement-mode"] == "count_windows": self._increase_request_count() else: @@ -109,10 +104,45 @@ def output(self): return self._output raise PerfAnalyzerException("Attempted to get perf_analyzer output" "without calling run first.") - def _faild_with_measruement_inverval(self, output: str): - return ( - output.find("Failed to obtain stable measurement") or output.find("Please use a larger time window") - ) != -1 + def _run_with_stream(self, command: List[str]): + commands_lst = [] + + if self._timeout: + commands_lst = ["timeout", str(self._timeout)] + + commands_lst.extend(command) + LOGGER.debug(f"Run with stream: {commands_lst}") + process = Popen(commands_lst, start_new_session=True, stdout=PIPE, encoding="utf-8") + streamed_output = "" + while True: + output = process.stdout.readline() + if output == "" and process.poll() is not None: + break + if output: + streamed_output += output + print(output.rstrip()) + + self._output += streamed_output + result = process.poll() + LOGGER.debug(f"Perf Analyzer process exited with result: {result}") + + # WAR for Perf Analyzer exit code 0 when stabilization failed + if result == 0 and self._failed_with_measurement_inverval(streamed_output): + LOGGER.debug("Perf Analyzer finished with exit status 0, however measurement stabilization failed.") + result = 1 + + if result != 0: + raise CalledProcessError(returncode=result, cmd=commands_lst, output=streamed_output) + + def _failed_with_measurement_inverval(self, output: str): + checks = [ + output.find("Failed to obtain stable measurement"), + output.find("Please use a larger time window"), + ] + result = any([status != -1 for status in checks]) + + LOGGER.debug(f"Measurement stability message validation: {checks}. Result: {result}.") + return result def _increase_request_count(self): self._config["measurement-request-count"] += COUNT_INTERVAL_DELTA diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/perf_config.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/perf_config.py similarity index 99% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/perf_config.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/perf_config.py index 39d363a58..e4c63f6a8 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/perf_config.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/perf_config.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Dict +from typing import Any from .exceptions import PerfAnalyzerException diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/runner.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/runner.py new file mode 100644 index 000000000..3b6a690a5 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/runner.py @@ -0,0 +1,195 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import csv +import logging +import os +import pathlib +import sys +from distutils.version import LooseVersion +from typing import Dict, List, Optional, Tuple + +# method from PEP-366 to support relative import in executed modules +if __package__ is None: + __package__ = pathlib.Path(__file__).parent.name + +from ...core import EvaluationMode, MeasurementMode, OfflineMode +from ...report import save_results, show_results, sort_results +from ...utils import log_dict, parse_server_url +from .perf_analyzer import PerfAnalyzer +from .perf_config import PerfAnalyzerConfig + +if LooseVersion(sys.version) >= LooseVersion("3.8.0"): + from importlib.metadata import version + + TRITON_CLIENT_VERSION = LooseVersion(version("tritonclient")) +else: + import pkg_resources + + TRITON_CLIENT_VERSION = LooseVersion( + pkg_resources.get_distribution("tritonclient").version + ) + +LOGGER = logging.getLogger("triton_performance_runner.perf_analyzer") + + +class PerfAnalyzerRunner: + def __init__( + self, + server_url: str, + model_name: str, + input_data: Dict[int, Tuple], + batch_sizes: List[int], + concurrency: List[int], + measurement_mode: MeasurementMode, + measurement_interval: int, + measurement_request_count: int, + evaluation_mode: EvaluationMode, + offline_mode: OfflineMode, + result_path: pathlib.Path, + output_shared_memory_size: int = 102400, + timeout: Optional[int] = None, + verbose: bool = False, + flattened_input: bool = False, + ): + log_dict( + "Selected configuration", + { + "server_url": server_url, + "model_name": model_name, + "input_data": input_data, + "batch_sizes": batch_sizes, + "concurrency": concurrency, + "measurement_mode": measurement_mode, + "measurement_interval": measurement_interval, + "measurement_request_count": measurement_request_count, + "evaluation_mode": evaluation_mode, + "offline_mode": offline_mode, + "output_shared_memory_size": output_shared_memory_size, + "result_path": result_path, + "timeout": timeout, + "verbose": verbose, + }, + ) + + if result_path.suffix != ".csv": + raise ValueError( + "Results path for Perf Analyzer is invalid. Please, provide the CSV file name. Example: results.csv" + ) + + self._server_url = server_url + self._model_name = model_name + self._input_data = input_data + self._batch_sizes = batch_sizes + self._concurrency = concurrency + self._measurement_mode = measurement_mode + self._measurement_interval = measurement_interval + self._measurement_request_count = measurement_request_count + self._evaluation_mode = evaluation_mode + self._offline_mode = offline_mode + self._result_path = result_path + self._output_shared_memory_size = output_shared_memory_size + self._timeout = timeout + self._verbose = verbose + + self._protocol, self._host, self._port = parse_server_url(http://github.com/server_url) + self._flattened_input = flattened_input + + def run(self): + results: List[Dict] = [] + for batch_size in self._batch_sizes: + print("Measuring inference performance ") + input_data_filename, shapes = self._input_data[batch_size] + + concurrency = 1 + performance_partial_file = f"{self._evaluation_mode.value.lower()}_partial_{batch_size}_{concurrency}.csv" + + perf_analyzer_batch_size = 1 if self._flattened_input else batch_size + + params = { + "model-name": self._model_name, + "model-version": 1, + "batch-size": perf_analyzer_batch_size, + "url": f"{self._host}:{self._port}", + "protocol": self._protocol.value, + "input-data": input_data_filename, + "measurement-interval": self._measurement_interval, + "concurrency-range": f"{concurrency}:{concurrency}:1", + "latency-report-file": performance_partial_file, + } + + if self._verbose: + params["extra-verbose"] = True + + if TRITON_CLIENT_VERSION >= LooseVersion("2.11.0"): + params["measurement-mode"] = self._measurement_mode.value + params["measurement-request-count"] = self._measurement_request_count + + if self._evaluation_mode == EvaluationMode.OFFLINE: + params["shared-memory"] = self._offline_mode.value + params["output-shared-memory-size"] = self._output_shared_memory_size + + if self._verbose: + log_dict( + f"Perf Analyzer config for batch_size: {batch_size} and concurrency: {concurrency}", + params, + ) + + config = PerfAnalyzerConfig() + for param, value in params.items(): + config[param] = value + + for shape in shapes: + config["shape"] = shape + + perf_analyzer = PerfAnalyzer(config=config, timeout=self._timeout) + perf_analyzer.run() + self._update_performance_data(results, batch_size, performance_partial_file) + os.remove(performance_partial_file) + + results = sort_results(results=results) + + save_results(filename=self._result_path.as_posix(), data=results) + show_results(results=results) + + def _calculate_average_latency(self, r): + avg_sum_fields = [ + "Client Send", + "Network+Server Send/Recv", + "Server Queue", + "Server Compute", + "Server Compute Input", + "Server Compute Infer", + "Server Compute Output", + "Client Recv", + ] + avg_latency = sum(int(r.get(f, 0)) for f in avg_sum_fields) + + return avg_latency + + def _update_performance_data( + self, results: List, batch_size: int, performance_partial_file: str + ): + row: Dict = {"Batch": batch_size} + with open(performance_partial_file) as csvfile: + reader = csv.DictReader(csvfile) + for r in reader: + avg_latency = self._calculate_average_latency(r) + row = {**row, **r, "avg latency": avg_latency} + + if self._flattened_input: + # correction necessary because "formally" this is run with batch_size=1 + row["Inferences/Second"] = str( + float(row["Inferences/Second"]) * batch_size + ) + results.append(row) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/warmup.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/warmup.py new file mode 100644 index 000000000..57394c0d8 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/perf_analyzer/warmup.py @@ -0,0 +1,102 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import logging +import pathlib +from distutils.version import LooseVersion +from importlib.metadata import version +from typing import Dict, List, Optional, Tuple + +# method from PEP-366 to support relative import in executed modules +if __package__ is None: + __package__ = pathlib.Path(__file__).parent.name + +from ...core import EvaluationMode, MeasurementMode, OfflineMode +from ...utils import parse_server_url +from .perf_analyzer import PerfAnalyzer +from .perf_config import PerfAnalyzerConfig + +LOGGER = logging.getLogger("warmup") + +TRITON_CLIENT_VERSION = LooseVersion(version("tritonclient")) + + +class PerfAnalyzerWarmupRunner: + def __init__( + self, + server_url: str, + model_name: str, + batch_sizes: List[int], + concurrency: List[int], + input_data: Dict[int, Tuple], + measurement_mode: MeasurementMode, + measurement_interval: int, + measurement_request_count: int, + offline_mode: OfflineMode, + evaluation_mode: EvaluationMode, + output_shared_memory_size: int, + timeout: Optional[int], + flattened_input: bool = False, + ): + self._model_name = model_name + self._input_data = input_data + self._measurement_mode = measurement_mode + self._offline_mode = offline_mode + self._evaluation_mode = evaluation_mode + self._output_shared_memory_size = output_shared_memory_size + + self._protocol, self._host, self._port = parse_server_url(http://github.com/server_url) + + self._measurement_interval = 2 * measurement_interval + self._measurement_request_count = 2 * measurement_request_count + + self._batch_sizes = [min(batch_sizes)] + self._concurrency = [max(concurrency)] + self._timeout = timeout + self._flattened_input = flattened_input + + def run(self): + for batch_size in self._batch_sizes: + input_data_filename, shapes = self._input_data[batch_size] + perf_analyzer_batch_size = 1 if self._flattened_input else batch_size + + concurrency = 1 + params = { + "model-name": self._model_name, + "model-version": 1, + "batch-size": perf_analyzer_batch_size, + "url": f"{self._host}:{self._port}", + "protocol": self._protocol.value, + "input-data": input_data_filename, + "measurement-interval": self._measurement_interval, + "concurrency-range": f"{concurrency}:{concurrency}:1", + "verbose": True, + } + + if TRITON_CLIENT_VERSION >= LooseVersion("2.11.0"): + params["measurement-mode"] = self._measurement_mode.value + params["measurement-request-count"] = self._measurement_request_count + + if self._evaluation_mode == EvaluationMode.OFFLINE: + params["shared-memory"] = self._offline_mode.value + params["output-shared-memory-size"] = self._output_shared_memory_size + + config = PerfAnalyzerConfig() + for param, value in params.items(): + config[param] = value + + for shape in shapes: + config["shape"] = shape + + perf_analyzer = PerfAnalyzer(config=config, timeout=self._timeout) + perf_analyzer.run() diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/runner.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/runner.py new file mode 100644 index 000000000..d0892763f --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/triton_performance_runner/runner.py @@ -0,0 +1,91 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# method from PEP-366 to support relative import in executed modules +import logging +import pathlib +from typing import List, Optional, Dict, Tuple + +if __package__ is None: + __package__ = pathlib.Path(__file__).parent.name + +from ..core import EvaluationMode, MeasurementMode, OfflineMode +from .perf_analyzer import PerfAnalyzerRunner, PerfAnalyzerWarmupRunner + +LOGGER = logging.getLogger("triton_performance_runner") + + +class TritonPerformanceRunner: + def __init__( + self, + server_url: str, + model_name: str, + input_data: Dict[int, Tuple], + batch_sizes: List[int], + concurrency: List[int], + measurement_mode: MeasurementMode, + measurement_interval: int, + measurement_request_count: int, + evaluation_mode: EvaluationMode, + offline_mode: OfflineMode, + output_shared_memory_size: int, + result_path: pathlib.Path, + warmup: bool, + timeout: Optional[int], + verbose: bool, + flattened_input: bool, + ): + + self._warmup_runner = None + if warmup: + LOGGER.info("Running warmup before the main test") + self._warmup_runner = PerfAnalyzerWarmupRunner( + server_url=server_url, + model_name=model_name, + input_data=input_data, + batch_sizes=batch_sizes, + concurrency=concurrency, + measurement_mode=measurement_mode, + measurement_interval=measurement_interval, + measurement_request_count=measurement_request_count, + evaluation_mode=evaluation_mode, + offline_mode=offline_mode, + output_shared_memory_size=output_shared_memory_size, + timeout=timeout, + flattened_input=flattened_input + ) + + LOGGER.info("Using Perf Analyzer for performance evaluation") + self._runner = PerfAnalyzerRunner( + server_url=server_url, + model_name=model_name, + input_data=input_data, + batch_sizes=batch_sizes, + measurement_mode=measurement_mode, + measurement_interval=measurement_interval, + measurement_request_count=measurement_request_count, + concurrency=concurrency, + evaluation_mode=evaluation_mode, + offline_mode=offline_mode, + output_shared_memory_size=output_shared_memory_size, + result_path=result_path, + timeout=timeout, + verbose=verbose, + flattened_input=flattened_input + ) + + def run(self): + if self._warmup_runner: + self._warmup_runner.run() + + self._runner.run() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/utils.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/utils.py similarity index 73% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/utils.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/utils.py index c1a1a6f36..018be31cf 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/utils.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/deployment_toolkit/utils.py @@ -12,20 +12,31 @@ # See the License for the specific language governing permissions and # limitations under the License. import logging -from typing import Tuple +from enum import Enum +from typing import Any, Dict, Tuple LOGGER = logging.getLogger(__name__) -def parse_server_url(http://github.com/server_url:%20str) -> Tuple[str, str, int]: - DEFAULT_PORTS = {"http": 8000, "grpc": 8001} +class TritonClientProtocol(Enum): + """Describe protocol with which client communicates with Triton""" + + GRPC = "grpc" + HTTP = "http" + + +def parse_server_url(http://github.com/server_url:%20str) -> Tuple[TritonClientProtocol, str, int]: + DEFAULT_PORTS = { + TritonClientProtocol.HTTP: 8000, + TritonClientProtocol.GRPC: 8001, + } # extract protocol server_url_items = server_url.split("://") if len(server_url_items) != 2: raise ValueError("Prefix server_url with protocol ex.: grpc://127.0.0.1:8001") requested_protocol, server_url = server_url_items - requested_protocol = requested_protocol.lower() + requested_protocol = TritonClientProtocol(requested_protocol.lower()) if requested_protocol not in DEFAULT_PORTS: raise ValueError(f"Unsupported protocol: {requested_protocol}") @@ -45,3 +56,9 @@ def parse_server_url(http://github.com/server_url:%20str) -> Tuple[str, str, int]: else: raise ValueError(f"Could not parse {server_url}. Example of correct server URL: grpc://127.0.0.1:8001") return requested_protocol, host, port + + +def log_dict(title: str, dict_: Dict[str, Any]): + LOGGER.info(title) + for key, value in dict_.items(): + LOGGER.info(f"\t{key} = {value}") diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/evaluate_accuracy.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/evaluate_accuracy.py new file mode 100644 index 000000000..d03d4a542 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/evaluate_accuracy.py @@ -0,0 +1,112 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import dataloading.feature_spec +import os +import numpy as np +import argparse + +import dllogger + +from dataloading.dataloader import create_input_pipelines +from nn.evaluator import Evaluator +from utils.logging import IterTimer, init_logging +import deployment.tf.triton_ensemble_wrapper +import deployment.hps.triton_ensemble_wrapper + + +def log_results(auc, test_loss, latencies, batch_size, compute_latencies=False, warmup_steps=10): + # don't benchmark the first few warmup steps + latencies = latencies[warmup_steps:] + result_data = { + 'mean_inference_throughput': batch_size / np.mean(latencies), + 'mean_inference_latency': np.mean(latencies) + } + if compute_latencies: + for percentile in [90, 95, 99]: + result_data[f'p{percentile}_inference_latency'] = np.percentile(latencies, percentile) + result_data['auc'] = auc + result_data['test_loss'] = test_loss + + dllogger.log(data=result_data, step=tuple()) + + +def parse_args(): + parser = argparse.ArgumentParser(description='') + parser.add_argument('--dataset_path', type=str, required=True, help='') + parser.add_argument('--dataset_type', default='tf_raw', type=str, help='') + parser.add_argument('--feature_spec', default='feature_spec.yaml', type=str, help='') + parser.add_argument('--batch_size', type=int, default=32768, help='Batch size') + parser.add_argument('--auc_thresholds', type=int, default=8000, help='') + + parser.add_argument('--max_steps', type=int, default=None, help='') + parser.add_argument('--print_freq', type=int, default=10, help='') + + parser.add_argument('--log_path', type=str, default='dlrm_tf_log.json', help='triton_inference_log.json') + parser.add_argument('--verbose', action='http://github.com/store_true', default=False, help='') + parser.add_argument('--test_on_train', action='http://github.com/store_true', default=False, + help='Run validation on the training set.') + parser.add_argument('--fused_embedding', action='http://github.com/store_true', default=False, + help='Fuse the embedding table together for better GPU utilization.') + parser.add_argument("--model_name", type=str, help="The name of the model used for inference.", required=True) + + parser.add_argument("--sparse_input_format", type=str, choices=["tf-savedmodel", "hps"], + required=True, default="tf-savedmodel") + + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + init_logging(log_path=args.log_path, params_dict=args.__dict__) + fspec = dataloading.feature_spec.FeatureSpec.from_yaml(os.path.join(args.dataset_path, args.feature_spec)) + num_tables = len(fspec.get_categorical_sizes()) + table_ids = list(range(num_tables)) # possibly wrong ordering, to be tested + + train_pipeline, validation_pipeline = create_input_pipelines(dataset_type=args.dataset_type, + dataset_path=args.dataset_path, + train_batch_size=args.batch_size, + test_batch_size=args.batch_size, + table_ids=table_ids, + feature_spec=args.feature_spec, + rank=0, world_size=1) + + if args.test_on_train: + validation_pipeline = train_pipeline + + if args.sparse_input_format == 'hps': + wrapper_cls = deployment.hps.triton_ensemble_wrapper.RecsysTritonEnsemble + else: + wrapper_cls = deployment.tf.triton_ensemble_wrapper.RecsysTritonEnsemble + + model = wrapper_cls(model_name=args.model_name, num_tables=num_tables, verbose=args.verbose, + categorical_sizes=fspec.get_categorical_sizes(), fused_embedding=args.fused_embedding) + + timer = IterTimer(train_batch_size=args.batch_size, test_batch_size=args.batch_size, + optimizer=None, print_freq=args.print_freq, enabled=True) + + evaluator = Evaluator(model=model, timer=timer, auc_thresholds=args.auc_thresholds, + max_steps=args.max_steps, cast_dtype=None) + + auc, test_loss, latencies = evaluator(validation_pipeline=validation_pipeline) + log_results(auc, test_loss, latencies, batch_size=args.batch_size) + print('DONE') + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/evaluate_latency.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/evaluate_latency.py new file mode 100755 index 000000000..b98d0a7b2 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/evaluate_latency.py @@ -0,0 +1,347 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import json +import logging +import os +import pathlib +import base64 + +import tensorflow as tf +import numpy as np + +# method from PEP-366 to support relative import in executed modules +if __package__ is None: + __package__ = pathlib.Path(__file__).parent.name + +import dataloading.feature_spec +from dataloading.dataloader import create_input_pipelines, get_dataset_metadata + +from deployment.hps import constants +from deployment.hps.triton_ensemble_wrapper import NumpyToHpsInputConverter + +from deployment.deployment_toolkit.core import EvaluationMode, MeasurementMode, OfflineMode +from deployment.deployment_toolkit.triton_performance_runner import TritonPerformanceRunner + +LOGGER = logging.getLogger("run_performance_on_triton") + + +def b64_tensor(x): + return {'b64': base64.b64encode(x.flatten()).decode("utf-8")} + + +def create_input_data(sparse_backend, *args, **kwargs): + + if sparse_backend == 'hps': + return create_input_data_hps(*args, **kwargs) + elif sparse_backend == 'tf-savedmodel': + return create_input_data_tf(*args, **kwargs) + else: + raise ValueError(f'Unknown sparse backend: {sparse_backend}') + + +def create_input_data_tf(batch_sizes, dataset_path, dataset_type, feature_spec, + total_benchmark_samples, fused_embedding): + fspec = dataloading.feature_spec.FeatureSpec.from_yaml( + os.path.join(dataset_path, feature_spec) + ) + num_tables = len(fspec.get_categorical_sizes()) + table_ids = list(range(num_tables)) + + filename = f"/tmp/triton_input_data_batch.json" + print("generating input data: ", filename) + + _, dataloader = create_input_pipelines(dataset_type=dataset_type, dataset_path=dataset_path, train_batch_size=1, + test_batch_size=1, table_ids=table_ids, feature_spec=feature_spec, + rank=0, world_size=1) + generated = 0 + samples = [] + for sample in dataloader.op(): + features, labels = sample + numerical_features, cat_features = features + + cat_features = tf.concat(cat_features, axis=1).numpy().astype(np.int32) + numerical_features = numerical_features.numpy().astype(np.float32) + + sample = { + "categorical_features": b64_tensor(cat_features), + "numerical_features": b64_tensor(numerical_features), + } + samples.append(sample) + generated += 1 + if generated >= total_benchmark_samples: + break + + with open(filename, "w") as f: + json.dump(obj={"data": samples}, fp=f, indent=4) + + shapes = [ + f"categorical_features:{cat_features.shape[1]}", + f"numerical_features:{numerical_features.shape[1]}", + ] + + input_data = {} + for batch_size in batch_sizes: + input_data[batch_size] = (filename, shapes) + return input_data + + +def create_input_data_hps(batch_sizes, dataset_path, dataset_type, feature_spec, + total_benchmark_samples, fused_embedding): + + input_data = {} + for batch_size in batch_sizes: + filename = f"/tmp/triton_input_data_batch{batch_size}.json" + print("generating input data: ", filename) + shapes = create_input_data_hps_batch(batch_size=batch_size, dst_path=filename, dataset_path=dataset_path, + dataset_type=dataset_type, feature_spec=feature_spec, + total_benchmark_samples=total_benchmark_samples, + fused_embedding=fused_embedding) + input_data[batch_size] = (filename, shapes) + return input_data + + +def create_input_data_hps_batch(batch_size, dst_path, dataset_path, dataset_type, feature_spec, + total_benchmark_samples, fused_embedding): + + fspec = dataloading.feature_spec.FeatureSpec.from_yaml( + os.path.join(dataset_path, feature_spec) + ) + num_tables = len(fspec.get_categorical_sizes()) + table_ids = list(range(num_tables)) + + converter = NumpyToHpsInputConverter(categorical_sizes=fspec.get_categorical_sizes(), + fused_embedding=fused_embedding) + + _, dataloader = create_input_pipelines(dataset_type=dataset_type, dataset_path=dataset_path, + train_batch_size=batch_size, test_batch_size=batch_size, + table_ids=table_ids, feature_spec=feature_spec, rank=0, world_size=1) + + generated = 0 + batches = [] + for batch in dataloader.op(): + features, labels = batch + numerical_features, cat_features = features + key_tensor, nkey_tensor, numerical_features = converter( + numerical_features, cat_features + ) + + batch = { + constants.key_global_prefix: b64_tensor(key_tensor), + constants.numkey_global_prefix: b64_tensor(nkey_tensor), + constants.ens_numerical_features_name: b64_tensor(numerical_features) + } + batches.append(batch) + generated += batch_size + if generated >= total_benchmark_samples: + break + + with open(dst_path, "w") as f: + json.dump(obj={"data": batches}, fp=f, indent=4) + + shapes = [ + f"{constants.key_global_prefix}:{key_tensor.shape[1]}", + f"{constants.numkey_global_prefix}:{nkey_tensor.shape[1]}", + f"{constants.ens_numerical_features_name}:{numerical_features.shape[1]}", + ] + return shapes + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--model-name", + type=str, + required=True, + help="Name of the model to test", + ) + parser.add_argument( + "--result-path", + type=pathlib.Path, + required=True, + help="Path where results files is stored.", + ) + parser.add_argument( + "--server-url", + type=str, + default="http://127.0.0.1:8000/", + help="Url to Triton server", + ) + + parser.add_argument( + "--model-version", + type=str, + default=1, + help="Version of model", + ) + parser.add_argument( + "--sparse-format", + type=str, + help="Target format of dense model part in ensemble.", + choices=["tf-savedmodel", "hps"], + required=True, + default="tf-savedmodel", + ) + parser.add_argument( + "--fused-embedding", + action="http://github.com/store_true", + help="Use the fused embedding API for HPS", + ) + parser.add_argument( + "--batch-sizes", + type=int, + default=[256, 512, 1024, 2048, 4096, 8192, 16384, 32768], + help="List of batch sizes to test.", + nargs="*", + ) + parser.add_argument( + "--concurrency", + type=int, + default=[1], + help="List of concurrency modes.", + nargs="*", + ) + parser.add_argument( + "--measurement-mode", + choices=[item.value for item in MeasurementMode], + default=MeasurementMode.COUNT_WINDOWS.value, + type=str, + help="Select measurement mode " + "'time_windows' stabilize performance on measurement window. " + "'count_windows' stabilize performance on number of samples.", + ) + parser.add_argument( + "--measurement-interval", + help="Time window perf_analyzer will wait to stabilize the measurement", + default=1000, + type=int, + ) + parser.add_argument( + "--measurement-request-count", + help="Number of samples on which perf_analyzer will stabilize the measurement", + default=20, + type=int, + ) + parser.add_argument( + "--evaluation-mode", + choices=[item.value for item in EvaluationMode], + default=EvaluationMode.OFFLINE.value, + type=str, + help="Select evaluation mode " + "'offline' run offline analysis and use GPU memory to pass tensors. " + "'online' run online analysis and use HTTP protocol.", + ) + parser.add_argument( + "--offline-mode", + choices=[item.value for item in OfflineMode], + default=OfflineMode.SYSTEM.value, + type=str, + help="Select offline mode " + "'system' pass tensors through CPU RAM memory. " + "'cuda' pass tensors through GPU RAM memory.", + ) + parser.add_argument( + "--output-shared-memory-size", + default=524288, + type=int, + help="Size of memory buffer allocated for output with dynamic shapes in bytes. " + "Has to be equal to maximal size of output tensor.", + ) + parser.add_argument( + "--warmup", + help="Enable model warmup before performance test", + action="http://github.com/store_true", + default=False, + ) + parser.add_argument( + "--timeout", + help="Timeout for performance analysis", + type=int, + default=None, + required=False, + ) + parser.add_argument( + "-v", + "--verbose", + help="Verbose logs", + action="http://github.com/store_true", + default=False, + ) + + # dataset and dataloading settings + parser.add_argument( + "--dataset_path", default=None, required=True, help="Path to dataset directory" + ) + parser.add_argument( + "--feature_spec", + default="feature_spec.yaml", + help="Name of the feature spec file in the dataset directory", + ) + parser.add_argument( + "--dataset_type", + default="tf_raw", + choices=["tf_raw", "synthetic", "split_tfrecords"], + help="The type of the dataset to use", + ) + + parser.add_argument( + "--num-benchmark-samples", + default=2**18, + type=int, + help="The type of the dataset to use", + ) + + args = parser.parse_args() + + log_level = logging.INFO if not args.verbose else logging.DEBUG + log_format = "%(asctime)s %(levelname)s %(name)s %(message)s" + logging.basicConfig(level=log_level, format=log_format) + + input_data = create_input_data(sparse_backend=args.sparse_format, + batch_sizes=args.batch_sizes, dataset_path=args.dataset_path, + dataset_type=args.dataset_type, feature_spec=args.feature_spec, + total_benchmark_samples=args.num_benchmark_samples, + fused_embedding=args.fused_embedding) + + runner = TritonPerformanceRunner( + server_url=args.server_url, + model_name=args.model_name, + input_data=input_data, + batch_sizes=args.batch_sizes, + measurement_mode=MeasurementMode(args.measurement_mode), + measurement_interval=args.measurement_interval, + measurement_request_count=args.measurement_request_count, + concurrency=args.concurrency, + evaluation_mode=EvaluationMode(args.evaluation_mode), + offline_mode=OfflineMode(args.offline_mode), + output_shared_memory_size=args.output_shared_memory_size, + result_path=args.result_path, + warmup=args.warmup, + timeout=args.timeout, + verbose=args.verbose, + flattened_input=args.sparse_format == 'hps' + ) + + runner.run() + + for _, (filename, _) in input_data.items(): + if os.path.exists(filename): + os.remove(filename) + + +if __name__ == "__main__": + main() diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/Dockerfile b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/Dockerfile new file mode 100644 index 000000000..d3219f4c8 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/Dockerfile @@ -0,0 +1,129 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +ARG DLFW_VERSION=23.02 + +FROM nvcr.io/nvidia/tensorflow:${DLFW_VERSION}-tf2-py3 as tf +FROM nvcr.io/nvidia/tritonserver:${DLFW_VERSION}-py3 as tritonserver + +WORKDIR /hugectr_backend + +# rapids components from the DLFW image +COPY --chown=1000:1000 --from=tf /usr/lib/libcudf* /usr/lib/ +COPY --chown=1000:1000 --from=tf /usr/lib/libarrow* /usr/lib/ +COPY --chown=1000:1000 --from=tf /usr/lib/libparquet* /usr/lib/ +COPY --chown=1000:1000 --from=tf /usr/lib/cmake/arrow /usr/lib/cmake/arrow/ +COPY --chown=1000:1000 --from=tf /usr/lib/libnvcomp* /usr/lib/ +COPY --chown=1000:1000 --from=tf /usr/include/parquet /usr/include/parquet/ +COPY --chown=1000:1000 --from=tf /usr/include/arrow /usr/include/arrow/ +COPY --chown=1000:1000 --from=tf /usr/include/cudf /usr/include/cudf/ +COPY --chown=1000:1000 --from=tf /usr/include/rmm /usr/include/rmm/ +ARG PYTHON_VERSION=3.8 +COPY --chown=1000:1000 --from=tf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/rmm /usr/local/lib/python${PYTHON_VERSION}/dist-packages/rmm +COPY --chown=1000:1000 --from=tf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/cuda /usr/local/lib/python${PYTHON_VERSION}/dist-packages/cuda +COPY --chown=1000:1000 --from=tf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/pyarrow /usr/local/lib/python${PYTHON_VERSION}/dist-packages/pyarrow +COPY --chown=1000:1000 --from=tf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/cudf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/cudf +COPY --chown=1000:1000 --from=tf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/dask_cudf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/dask_cudf +COPY --chown=1000:1000 --from=tf /usr/local/lib/python${PYTHON_VERSION}/dist-packages/dask_cuda /usr/local/lib/python${PYTHON_VERSION}/dist-packages/dask_cuda + +COPY --chown=1000:1000 --from=tf /usr/local/lib/python3.8/dist-packages/cudf-*.dist-info /usr/local/lib/python3.8/dist-packages/cudf.dist-info/ +COPY --chown=1000:1000 --from=tf /usr/local/lib/python3.8/dist-packages/dask_cudf-*.dist-info /usr/local/lib/python3.8/dist-packages/dask_cudf.dist-info/ +COPY --chown=1000:1000 --from=tf /usr/local/lib/python3.8/dist-packages/dask_cuda-*.dist-info /usr/local/lib/python3.8/dist-packages/dask_cuda.dist-info/ +COPY --chown=1000:1000 --from=tf /usr/local/lib/python3.8/dist-packages/pyarrow-*.dist-info /usr/local/lib/python3.8/dist-packages/pyarrow.dist-info/ +COPY --chown=1000:1000 --from=tf /usr/local/lib/python3.8/dist-packages/rmm-*.dist-info /usr/local/lib/python3.8/dist-packages/rmm.dist-info/ + + +RUN apt update -y --fix-missing && \ + apt install -y --no-install-recommends software-properties-common && \ + apt install -y --no-install-recommends \ + ca-certificates \ + clang-format \ + curl \ + libcurl4-openssl-dev \ + git \ + graphviz \ + libarchive-dev \ + libb64-dev \ + libboost-serialization-dev \ + libexpat1-dev \ + libopenblas-dev \ + libre2-dev \ + libsasl2-2 \ + libssl-dev \ + libtbb-dev \ + openssl \ + policykit-1 \ + protobuf-compiler \ + python3 \ + python3-pip \ + python3-dev \ + rapidjson-dev \ + tree \ + wget \ + zlib1g-dev \ + # Required to build RocksDB and RdKafka.. + libgflags-dev \ + libbz2-dev \ + libsnappy-dev \ + liblz4-dev \ + libzstd-dev \ + libsasl2-dev \ + # Required to build Protocol Buffers. + autoconf automake libtool \ + # Required to build Hadoop. + default-jdk maven pkg-config \ + libpmem-dev \ + libsnappy-dev \ + # Required to run Hadoop. + openssh-server \ + # [ HugeCTR ] + libaio-dev && \ + apt autoremove -y && \ + apt clean && \ + rm -rf /var/lib/apt/lists/* + +RUN pip install --no-cache-dir "cmake<3.25.0" + +# Install spdlog +RUN git clone --branch v1.9.2 https://github.com/gabime/spdlog.git build-env && \ + pushd build-env && \ + mkdir build && cd build && cmake .. && make -j && make install && \ + popd && \ + rm -rf build-env + +RUN git clone https://github.com/NVIDIA/HugeCTR.git &&\ + cd HugeCTR &&\ + git checkout 7134016 &&\ + git submodule update --init --recursive + +RUN cd HugeCTR &&\ + mkdir -p build && cd build &&\ + cmake -DCMAKE_BUILD_TYPE=Release -DSM="70;80;90" -DENABLE_INFERENCE=ON .. &&\ + make -j && make install + +RUN git clone https://github.com/triton-inference-server/hugectr_backend.git &&\ + cd hugectr_backend/hps_backend && git checkout release-23.02 && mkdir build && cd build &&\ + cmake -DCMAKE_INSTALL_PREFIX:PATH=`pwd`/install -DTRITON_COMMON_REPO_TAG=r23.02\ + -DTRITON_CORE_REPO_TAG=r23.02\ + -DTRITON_BACKEND_REPO_TAG=r23.02 .. + +RUN cd hugectr_backend/hps_backend/build &&\ + export CPATH=/usr/local/hugectr/include:$CPATH && \ + export LIBRARY_PATH=/usr/local/hugectr/lib:$LIBRARY_PATH && \ + make install && mkdir -p /opt/tritonserver/backends/hps &&\ + cp libtriton_hps.* /opt/tritonserver/backends/hps/ + +WORKDIR /opt/tritonserver diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/__init__.py similarity index 61% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/__init__.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/__init__.py index e1dfc06ed..39da88ade 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/__init__.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,11 +11,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import pathlib +# +# author: Tomasz Grel (tgrel@nvidia.com) -# method from PEP-366 to support relative import in executed modules -if __package__ is None: - __package__ = pathlib.Path(__file__).parent.name -from .perf_analyzer import PerfAnalyzer # noqa: F401 -from .perf_config import PerfAnalyzerConfig # noqa: F401 +from deployment.hps.constants import dense_model_name, hps_model_name +from deployment.hps.deploy_dense import deploy_dense +from deployment.hps.deploy_ensemble import deploy_ensemble +from deployment.hps.deploy_sparse import deploy_sparse diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/constants.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/constants.py new file mode 100644 index 000000000..a600df41c --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/constants.py @@ -0,0 +1,35 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +key_local_prefix = "KEYS" +numkey_local_prefix = "NUMKEYS" + +key_global_prefix = "EMB_KEY" +numkey_global_prefix = "EMB_N_KEY" + +emb_output_name = "OUTPUT0" +ens_lookup_tensors_name = "LOOKUP_VECTORS" +dense_input1_name = "args_1" + +ens_numerical_features_name = "numerical_features" +dense_numerical_features_name = "args_0" + +dense_output_name = "output_1" +ens_output_name = "DENSE_OUTPUT" + +hps_model_name = "hps_embedding" +dense_model_name = "tf_reshape_dense_model" diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_dense.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_dense.py new file mode 100644 index 000000000..4165d6079 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_dense.py @@ -0,0 +1,279 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import logging +import os +import pathlib +import shutil +import subprocess +import tempfile +import textwrap +from typing import List + +import numpy as np +import tensorflow as tf +from nn.dense_model import DenseModel + +from . import constants as c + +LOGGER = logging.getLogger(__name__) + +_dense_model_config_template = r"""name: "{model_name}" +{backend_type}: "{backend_runtime}" +max_batch_size: 0 +input [ + {{ + name: "{input1}" + data_type: TYPE_FP32 + dims: [-1] + }}, + {{ + name: "{input2}" + data_type: TYPE_FP32 + dims: [-1] + }} +] +output [ + {{ + name: "{output1}" + data_type: TYPE_FP32 + dims: [-1,1] + }} +] +version_policy: {{ + specific:{{versions: 1}} +}}, +instance_group [ + {{ + count: {engine_count_per_device} + kind : KIND_GPU + gpus: [0] + }} +] +""" + + +def _execute_cmd(cmd: List, verbose: bool = False): + """Execute command as subprocess. + + Args: + cmd: A command definition + verbose: Stream command output + + Raises: + OSError when command execution failed + """ + process = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8" + ) + + if verbose: + LOGGER.info("Command output:") + + stream_output = "" + while True: + output = process.stdout.readline() + if output == "" and process.poll() is not None: + break + if output: + stream_output += output + if verbose: + print(textwrap.indent(output.rstrip(), " ")) # noqa: T201 + + result = process.poll() + + if result != 0: + raise OSError( + f"Processes exited with error code:{result}. Command to reproduce error:\n{' '.join(cmd)}" + ) + + +def _savedmodel2onnx(source_model_path, dst_model_path, opset=11, verbose=False): + convert_cmd = [ + "python", + "-m", + "tf2onnx.convert", + "--saved-model", + source_model_path.as_posix(), + "--output", + dst_model_path.as_posix(), + "--opset", + str(opset), + "--verbose", + ] + + _execute_cmd(convert_cmd, verbose=verbose) + + +def _onnx2trt( + model, + source_model_path, + dst_model_path, + precision, + optimal_batch_size, + max_batch_size, + verbose=False, +): + + min_batch = np.array([model.num_numerical_features, sum(model.embedding_dim)]) + + optimal_batch = min_batch * optimal_batch_size + max_batch = min_batch * max_batch_size + + print( + f"min batch {min_batch}, optimal_batch: {optimal_batch}, max_batch: {max_batch}" + ) + + convert_cmd = [ + "trtexec", + f"--onnx={source_model_path.as_posix()}", + "--buildOnly", + f"--saveEngine={dst_model_path.as_posix()}", + f"--minShapes=args_0:{min_batch[0]},args_1:{min_batch[1]}", + f"--optShapes=args_0:{optimal_batch[0]},args_1:{optimal_batch[1]}", + f"--maxShapes=args_0:{max_batch[0]},args_1:{max_batch[1]}", + ] + + if precision == "fp16": + convert_cmd += ["--fp16"] + + _execute_cmd(convert_cmd, verbose=verbose) + + +def _convert2onnx(source_model_path, workdir, verbose=False): + model_path = workdir / "model.onnx" + _savedmodel2onnx( + source_model_path=source_model_path, + dst_model_path=model_path, + verbose=verbose, + ) + return model_path + + +def _convert2trt( + model, + source_model_path, + precision, + workdir, + optimal_batch_size, + max_batch_size, + verbose=False, +): + + onnx_model_path = _convert2onnx( + source_model_path=source_model_path, + workdir=workdir, + verbose=verbose, + ) + trt_model_path = workdir / "model.plan" + _onnx2trt( + model=model, + source_model_path=onnx_model_path, + dst_model_path=trt_model_path, + precision=precision, + verbose=verbose, + optimal_batch_size=optimal_batch_size, + max_batch_size=max_batch_size, + ) + return trt_model_path + + +def _set_tf_memory_growth(): + physical_devices = tf.config.list_physical_devices("GPU") + for d in physical_devices: + tf.config.experimental.set_memory_growth(d, True) + + +def deploy_dense( + src, + dst, + model_name, + model_format, + model_precision, + max_batch_size, + engine_count_per_device, + trt_optimal_batch_size, + version="1", +): + print("deploy dense dst: ", dst) + + _set_tf_memory_growth() + + os.makedirs(dst, exist_ok=True) + + dense_model = DenseModel.from_config(os.path.join(src, "config.json")) + if model_precision == "fp16" and model_format == 'tf-savedmodel': + policy = tf.keras.mixed_precision.Policy("mixed_float16") + tf.keras.mixed_precision.set_global_policy(policy) + + # Currently, there's no support for custom kernels deployment. + # Use pure tensorflow implementation instead on the inference side. + if dense_model.interaction == 'dot_custom_cuda': + dense_model.interaction = 'dot_tensorflow' + dense_model._create_interaction_op() + + dense_model.load_weights(os.path.join(src, "dense")) + + # transpose needed here because HPS expects a table-major format vs TensorFlow uses batch-major + dense_model.transpose = True + dense_model.force_initialization(training=False, flattened_input=True) + with tempfile.TemporaryDirectory() as tempdir: + tempdir = pathlib.Path(tempdir) + model_path = tempdir / "model.savedmodel" + dense_model.save_model(model_path.as_posix(), save_input_signature=False) + model_store = pathlib.Path(dst) / str(version) + model_store.mkdir(parents=True, exist_ok=True) + + if model_format == "tf-savedmodel": + backend_type = "platform" + backend_runtime = "tensorflow_savedmodel" + shutil.copytree(model_path, model_store / "model.savedmodel") + elif model_format == "onnx": + backend_type = "backend" + backend_runtime = "onnxruntime" + model_path = _convert2onnx(model_path, workdir=tempdir) + shutil.copy(model_path, model_store / "model.onnx") + elif model_format == "trt": + backend_type = "backend" + backend_runtime = "tensorrt" + model_path = _convert2trt( + dense_model, + model_path, + precision=model_precision, + workdir=tempdir, + optimal_batch_size=trt_optimal_batch_size, + max_batch_size=max_batch_size, + ) + shutil.copy(model_path, model_store / "model.plan") + else: + raise ValueError(f"Unsupported format: {model_format}") + + with open(os.path.join(dst, "config.pbtxt"), "w") as f: + s = _dense_model_config_template.format( + backend_type=backend_type, + backend_runtime=backend_runtime, + model_name=model_name, + input1=c.dense_input1_name, + input2=c.dense_numerical_features_name, + output1=c.dense_output_name, + max_batch_size=max_batch_size, + engine_count_per_device=engine_count_per_device, + ) + f.write(s) + + print(f"{model_name} configuration:") + print(s) + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_ensemble.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_ensemble.py new file mode 100644 index 000000000..53aa8ca7d --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_ensemble.py @@ -0,0 +1,104 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import os +from collections import namedtuple + + +Tensor = namedtuple("Tensor", ["name", "dtype", "dims"]) + +_config_template = r''' +name: "{model_name}" +platform: "ensemble" +max_batch_size: {max_batch_size} +input [ + {{ + name: "EMB_KEY" + data_type: TYPE_INT64 + dims: [-1] + }}, + {{ + name: "EMB_N_KEY" + data_type: TYPE_INT32 + dims: [-1] + }}, + {{ + name: "numerical_features" + data_type: TYPE_FP32 + dims: [-1] + }} +] +output [ + {{ + name: "DENSE_OUTPUT" + data_type: TYPE_FP32 + dims: [-1] + }} +] +ensemble_scheduling {{ + step [ + {{ + model_name: "{sparse_model_name}" + model_version: -1 + input_map {{ + key: "KEYS" + value: "EMB_KEY" + }}, + input_map {{ + key: "NUMKEYS" + value: "EMB_N_KEY" + }}, + output_map {{ + key: "OUTPUT0" + value: "LOOKUP_VECTORS" + }} + }}, + {{ + model_name: "{dense_model_name}" + model_version: -1 + input_map {{ + key: "args_1" + value: "LOOKUP_VECTORS" + }}, + input_map {{ + key: "args_0" + value: "numerical_features" + }}, + output_map {{ + key: "output_1" + value: "DENSE_OUTPUT" + }} + }} + ] +}} +''' + + +def deploy_ensemble(dst, model_name, sparse_model_name, dense_model_name, + num_cat_features, num_numerical_features, max_batch_size, version): + + config_str = _config_template.format(model_name=model_name, + sparse_model_name=sparse_model_name, + dense_model_name=dense_model_name, + max_batch_size=max_batch_size) + + with open(os.path.join(dst, "config.pbtxt"), "w") as f: + f.write(config_str) + os.mkdir(os.path.join(dst, str(version))) + + print("Ensemble configuration:") + print(config_str) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_sparse.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_sparse.py new file mode 100644 index 000000000..427b21a5a --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/deploy_sparse.py @@ -0,0 +1,261 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import json +import math +import os +import numpy as np + + +def save_embedding_table(numpy_table, dst_dir, offset=0, min_keys=100): + if numpy_table.shape[0] < min_keys: + print( + f"Artificially lengthening embedding table from size: {numpy_table.shape} to size {min_keys}" + ) + num_missing_rows = min_keys - numpy_table.shape[0] + padding = np.zeros( + shape=[num_missing_rows, numpy_table.shape[1]], dtype=numpy_table.dtype + ) + numpy_table = np.vstack([numpy_table, padding]) + + keys_table = np.arange( + start=offset, stop=offset + numpy_table.shape[0], dtype=np.int64 + ) + keys_bytes = keys_table.tobytes() + key_file = os.path.join(dst_dir, "key") + with open(key_file, "wb") as f: + f.write(keys_bytes) + + table_bytes = numpy_table.tobytes() + table_file = os.path.join(dst_dir, "emb_vector") + with open(table_file, "wb") as f: + f.write(table_bytes) + + +_hps_triton_config_template = r"""name: "{model_name}" +backend: "hps" +max_batch_size:{max_batch_size} +input [ {{ + name: "KEYS" + data_type: TYPE_INT64 + dims: [-1] + }}, + {{ + name: "NUMKEYS" + data_type: TYPE_INT32 + dims: [-1] + }}] +output [ {{ + name: "OUTPUT0" + data_type: TYPE_FP32 + dims: [-1] + }}] +version_policy: {{ + specific:{{versions: {version}}} +}}, +instance_group [ + {{ + count: {engine_count_per_device} + kind : KIND_GPU + gpus : [0] + }} +] +""" + + +def save_triton_config( + dst_path, model_name, version, max_batch_size, engine_count_per_device +): + config = _hps_triton_config_template.format( + model_name=model_name, + max_batch_size=max_batch_size, + version=version, + engine_count_per_device=engine_count_per_device, + ) + + print("saving pbtxt HPS config to: ", dst_path) + with open(dst_path, "w") as f: + f.write(config) + print("Wrote HPS Triton config to:", dst_path) + + print(f"{model_name} configuration:") + print(config) + + +def save_json_config( + dst_path, + hps_embedding_dirs, + src_config, + num_gpus, + gpucacheper, + max_batch_size, + model_name, + fused=True, +): + num_cat_features = 1 if fused else len(src_config["categorical_cardinalities"]) + + if len(hps_embedding_dirs) != num_cat_features: + raise ValueError( + f"Length mismatch between hps_embedding_dirs ({len(hps_embedding_dirs)}) " + f"and num_cat_features ({num_cat_features}), fused={fused}. This should not happen." + ) + + vecsize_per_table = src_config["embedding_dim"] + max_batch_size_factor = 1 + if fused: + vecsize_per_table = [vecsize_per_table[0]] + max_batch_size_factor = len(src_config["categorical_cardinalities"]) + + hps_embedding_config = { + "supportlonglong": True, + "models": [ + { + "model": model_name, + # these directories should contain the "emb_vector" and "keys" files, need to copy them over from the previous location + "sparse_files": hps_embedding_dirs, + "num_of_worker_buffer_in_pool": 3, + "embedding_table_names": [ + f"sparse_embedding{i}" for i in range(num_cat_features) + ], + "embedding_vecsize_per_table": vecsize_per_table, + # for now, every table uses the same embedding dim + "maxnum_catfeature_query_per_table_per_sample": [ + 1 for _ in range(num_cat_features) + ], + "default_value_for_each_table": [1.0 for _ in range(num_cat_features)], + "deployed_device_list": list(range(num_gpus)), + "max_batch_size": max_batch_size * max_batch_size_factor, + "cache_refresh_percentage_per_iteration": 0.0, + "hit_rate_threshold": 1.0, + "gpucacheper": gpucacheper, + "gpucache": True, + } + ], + } + print("saving json config to: ", dst_path) + with open(dst_path, "w") as f: + json.dump(obj=hps_embedding_config, fp=f, indent=4) + + +def convert_embedding_tables(src_paths, dst, fused): + if fused: + return convert_embedding_tables_fused(src_paths, dst) + else: + return convert_embedding_tables_unfused(src_paths, dst) + + +def convert_embedding_tables_unfused(src_paths, dst): + hps_embedding_dirs = [] + for src_path in src_paths: + table_index = int(src_path.split("_")[-1].split(".")[0]) + dst_dir = os.path.join(dst, str(table_index)) + print(f"Converting embedding table: {src_path} to {dst_dir}") + + print(f"Loading source from {src_path}") + data = np.load(src_path, mmap_mode="r") + os.makedirs(dst_dir, exist_ok=True) + print(f"Saving embedding table to {dst_dir}") + save_embedding_table(numpy_table=data, dst_dir=dst_dir) + hps_embedding_dirs.append(dst_dir) + return hps_embedding_dirs + + +def convert_embedding_tables_fused(src_paths, dst): + dst_dir = os.path.join(dst, "0") + os.makedirs(dst_dir, exist_ok=True) + + current_offset = 0 + first_width = None + + key_file = os.path.join(dst_dir, "key") + table_file = os.path.join(dst_dir, "emb_vector") + with open(key_file, "wb") as keys_f, open(table_file, "wb") as table_f: + for src_path in src_paths: + print(f"Converting table {src_path}") + data = np.load(src_path, mmap_mode="r") + + if first_width is not None and data.shape[1] != first_width: + raise ValueError( + "Attempting to deploy with a fused embedding but not all embeddings have the same dimension." + f"Got embedding dimension: {data.shape[1]}, expected: {first_width}" + ) + if first_width is None: + first_width = data.shape[1] + + length = data.shape[0] + + keys_table = np.arange( + start=current_offset, stop=current_offset + length, dtype=np.int64 + ) + keys_bytes = keys_table.tobytes() + keys_f.write(keys_bytes) + + # write the table in chunks to minimize memory usage + chunk_size = 2**20 + num_chunks = math.ceil(length / chunk_size) + for i in range(num_chunks): + begin = i * chunk_size + end = (i + 1) * chunk_size + end = min(end, length) + table_bytes = data[begin:end].tobytes() + table_f.write(table_bytes) + + current_offset += length + return [dst_dir] + + +def deploy_sparse( + src, + dst, + model_name, + max_batch_size, + engine_count_per_device, + gpucacheper, + num_gpus=1, + version="1", + fused=True, + **kwargs +): + print("deploy sparse dst: ", dst) + with open(os.path.join(src, "config.json")) as f: + src_config = json.load(f) + + num_cat_features = len(src_config["categorical_cardinalities"]) + src_paths = [os.path.join(src, f"feature_{i}.npy") for i in range(num_cat_features)] + hps_embedding_dirs = convert_embedding_tables( + src_paths=src_paths, dst=os.path.join(dst, version), fused=fused + ) + + save_triton_config( + dst_path=os.path.join(dst, "config.pbtxt"), + model_name=model_name, + version=version, + max_batch_size=max_batch_size, + engine_count_per_device=engine_count_per_device, + ) + + save_json_config( + dst_path=os.path.join(dst, f"{model_name}.json"), + hps_embedding_dirs=hps_embedding_dirs, + src_config=src_config, + num_gpus=num_gpus, + fused=fused, + gpucacheper=gpucacheper, + max_batch_size=max_batch_size, + model_name=model_name, + ) + + return len(src_config["categorical_cardinalities"]) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/triton_ensemble_wrapper.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/triton_ensemble_wrapper.py new file mode 100644 index 000000000..242b414af --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/hps/triton_ensemble_wrapper.py @@ -0,0 +1,86 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import tritonclient.utils +import tritonclient.http +import numpy as np + +import deployment.hps.constants as c + + +class NumpyToHpsInputConverter: + def __init__(self, categorical_sizes, fused_embedding=True): + self.offsets = np.cumsum([0] + categorical_sizes)[:-1] + self.fused_embedding = fused_embedding + + def __call__(self, numerical_features, cat_features): + batch_size = cat_features[0].shape[0] + + cat_features = [f.numpy().flatten() for f in cat_features] + + # add the offsets + if self.fused_embedding: + cat_features = [f + o for f, o in zip(cat_features, self.offsets)] + key_tensor = np.concatenate(cat_features, axis=0).astype(np.int64).reshape([1, -1]) + + if self.fused_embedding: + nkey_tensor = np.full(shape=(1, 1), fill_value=batch_size * len(cat_features), dtype=np.int32) + else: + nkey_tensor = np.full(shape=(1, len(cat_features)), fill_value=batch_size, dtype=np.int32) + + numerical_features = numerical_features.numpy().astype(np.float32).reshape([1, -1]) + return key_tensor, nkey_tensor, numerical_features + + +class RecsysTritonEnsemble: + def __init__(self, model_name, num_tables, verbose, categorical_sizes, fused_embedding=True): + self.input_converter = NumpyToHpsInputConverter(categorical_sizes, fused_embedding) + self.model_name = model_name + self.triton_client = tritonclient.http.InferenceServerClient(url="localhost:8000", verbose=verbose) + if not self.triton_client.is_server_live(): + raise ValueError('Triton server is not live!') + + print('triton model repo: ', self.triton_client.get_model_repository_index()) + + def __call__(self, inputs, sigmoid=False, training=False): + numerical_features, cat_features = list(inputs.values()) + batch_size = cat_features[0].shape[0] + + key_tensor, nkey_tensor, numerical_features = self.input_converter(numerical_features, cat_features) + + inputs = [ + tritonclient.http.InferInput(c.key_global_prefix, + key_tensor.shape, + tritonclient.utils.np_to_triton_dtype(np.int64)), + tritonclient.http.InferInput(c.numkey_global_prefix, + nkey_tensor.shape, + tritonclient.utils.np_to_triton_dtype(np.int32)), + tritonclient.http.InferInput(c.ens_numerical_features_name, + numerical_features.shape, + tritonclient.utils.np_to_triton_dtype(np.float32)), + ] + inputs[0].set_data_from_numpy(key_tensor) + inputs[1].set_data_from_numpy(nkey_tensor) + inputs[2].set_data_from_numpy(numerical_features) + + + outputs = [tritonclient.http.InferRequestedOutput(c.ens_output_name)] + response = self.triton_client.infer(self.model_name, inputs, outputs=outputs) + result_np = response.as_numpy(c.ens_output_name) + + result_np = result_np.reshape([batch_size]) + return result_np diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/Dockerfile b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/Dockerfile new file mode 100644 index 000000000..bdd97c328 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/Dockerfile @@ -0,0 +1,20 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +FROM nvcr.io/nvidia/tritonserver:23.06-py3 as tritonserver + +WORKDIR /opt/tritonserver diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/__init__.py new file mode 100644 index 000000000..afaadab43 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/__init__.py @@ -0,0 +1,22 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +#from constants import dense_model_name, hps_model_name +from deployment.tf.deploy_dense import deploy_dense +from deployment.tf.deploy_ensemble import deploy_ensemble +from deployment.tf.deploy_sparse import deploy_sparse +from deployment.tf.deploy_monolithic import deploy_monolithic diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/constants.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/constants.py new file mode 100644 index 000000000..2879dff22 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/constants.py @@ -0,0 +1,26 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +emb_output_name = "OUTPUT0" +ens_lookup_tensors_name = "LOOKUP_VECTORS" +dense_input1_name = "args_1" + +ens_numerical_features_name = "numerical_features" +dense_numerical_features_name = "args_0" + +dense_output_name = "output_1" +ens_output_name = "DENSE_OUTPUT" diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_dense.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_dense.py new file mode 100644 index 000000000..3466060ea --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_dense.py @@ -0,0 +1,280 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import argparse +import logging +import os +import pathlib +import shutil +import subprocess +import tempfile +import textwrap +from typing import List + +import numpy as np +import tensorflow as tf +from nn.dense_model import DenseModel + +from . import constants as c + +LOGGER = logging.getLogger(__name__) + +_dense_model_config_template = r"""name: "{model_name}" +{backend_type}: "{backend_runtime}" +max_batch_size: 0 +input [ + {{ + name: "{input1}" + data_type: TYPE_FP32 + dims: [-1, {input1_dim}] + }}, + {{ + name: "{input2}" + data_type: TYPE_FP32 + dims: [-1, {input2_dim}] + }} +] +output [ + {{ + name: "{output1}" + data_type: TYPE_FP32 + dims: [-1,1] + }} +] +version_policy: {{ + specific:{{versions: 1}} +}}, +instance_group [ + {{ + count: {engine_count_per_device} + kind : KIND_GPU + gpus: [0] + }} +] +""" + + +def _execute_cmd(cmd: List, verbose: bool = False): + """Execute command as subprocess. + + Args: + cmd: A command definition + verbose: Stream command output + + Raises: + OSError when command execution failed + """ + process = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8" + ) + + if verbose: + LOGGER.info("Command output:") + + stream_output = "" + while True: + output = process.stdout.readline() + if output == "" and process.poll() is not None: + break + if output: + stream_output += output + if verbose: + print(textwrap.indent(output.rstrip(), " ")) # noqa: T201 + + result = process.poll() + + if result != 0: + raise OSError( + f"Processes exited with error code:{result}. Command to reproduce error:\n{' '.join(cmd)}" + ) + + +def _savedmodel2onnx(source_model_path, dst_model_path, opset=11, verbose=False): + convert_cmd = [ + "python", + "-m", + "tf2onnx.convert", + "--saved-model", + source_model_path.as_posix(), + "--output", + dst_model_path.as_posix(), + "--opset", + str(opset), + "--verbose", + ] + + _execute_cmd(convert_cmd, verbose=verbose) + + +def _onnx2trt( + model, + source_model_path, + dst_model_path, + precision, + optimal_batch_size, + max_batch_size, + verbose=False, +): + + min_batch = np.array([model.num_numerical_features, sum(model.embedding_dim)]) + + optimal_batch = min_batch * optimal_batch_size + max_batch = min_batch * max_batch_size + + print( + f"min batch {min_batch}, optimal_batch: {optimal_batch}, max_batch: {max_batch}" + ) + + convert_cmd = [ + "trtexec", + f"--onnx={source_model_path.as_posix()}", + "--buildOnly", + f"--saveEngine={dst_model_path.as_posix()}", + f"--minShapes=args_0:1x{min_batch[0]},args_1:1x{min_batch[1]}", + f"--optShapes=args_0:{optimal_batch_size}x{min_batch[0]},args_1:{optimal_batch_size}x{min_batch[1]}", + f"--maxShapes=args_0:{max_batch_size}x{min_batch[0]},args_1:{max_batch_size}x{min_batch[1]}" + ] + + if precision == "fp16": + convert_cmd += ["--fp16"] + + _execute_cmd(convert_cmd, verbose=True) + + +def _convert2onnx(source_model_path, workdir, verbose=False): + model_path = workdir / "model.onnx" + _savedmodel2onnx( + source_model_path=source_model_path, + dst_model_path=model_path, + verbose=verbose, + ) + return model_path + + +def _convert2trt( + model, + source_model_path, + precision, + workdir, + optimal_batch_size, + max_batch_size, + verbose=False, +): + + onnx_model_path = _convert2onnx( + source_model_path=source_model_path, + workdir=workdir, + verbose=verbose, + ) + trt_model_path = workdir / "model.plan" + _onnx2trt( + model=model, + source_model_path=onnx_model_path, + dst_model_path=trt_model_path, + precision=precision, + verbose=verbose, + optimal_batch_size=optimal_batch_size, + max_batch_size=max_batch_size, + ) + return trt_model_path + + +def deploy_dense( + src, + dst, + model_name, + model_format, + model_precision, + max_batch_size, + engine_count_per_device, + trt_optimal_batch_size, + version="1", +): + print("deploy dense dst: ", dst) + + os.makedirs(dst, exist_ok=True) + + dense_model = DenseModel.from_config(os.path.join(src, "config.json")) + if model_precision == "fp16" and model_format == 'tf-savedmodel': + policy = tf.keras.mixed_precision.Policy("mixed_float16") + tf.keras.mixed_precision.set_global_policy(policy) + + # Currently, there's no support for custom kernels deployment. + # Use pure tensorflow implementation instead on the inference side. + if dense_model.interaction == 'dot_custom_cuda': + dense_model.interaction = 'dot_tensorflow' + dense_model._create_interaction_op() + + dense_model.load_weights(os.path.join(src, "dense")) + + dense_model.transpose = False + dense_model.force_initialization(training=False, flattened_input=False) + + tempdir_path = '/tmp/deploy_recsys' + shutil.rmtree(tempdir_path, ignore_errors=True) + os.makedirs(tempdir_path, exist_ok=True) + + tempdir = pathlib.Path(tempdir_path) + model_path = tempdir / "model.savedmodel" + dense_model.save_model(model_path.as_posix(), save_input_signature=False) + model_store = pathlib.Path(dst) / str(version) + model_store.mkdir(parents=True, exist_ok=True) + + if model_format == "tf-savedmodel": + backend_type = "platform" + backend_runtime = "tensorflow_savedmodel" + shutil.copytree(model_path, model_store / "model.savedmodel") + elif model_format == "onnx": + backend_type = "backend" + backend_runtime = "onnxruntime" + model_path = _convert2onnx(model_path, workdir=tempdir) + shutil.copy(model_path, model_store / "model.onnx") + elif model_format == "trt": + backend_type = "backend" + backend_runtime = "tensorrt" + model_path = _convert2trt( + dense_model, + model_path, + precision=model_precision, + workdir=tempdir, + optimal_batch_size=trt_optimal_batch_size, + max_batch_size=max_batch_size, + ) + shutil.copy(model_path, model_store / "model.plan") + else: + raise ValueError(f"Unsupported format: {model_format}") + + shutil.rmtree(tempdir_path) + with open(os.path.join(dst, "config.pbtxt"), "w") as f: + s = _dense_model_config_template.format( + backend_type=backend_type, + backend_runtime=backend_runtime, + model_name=model_name, + input1=c.dense_input1_name, + input1_dim=sum(dense_model.embedding_dim), + input2=c.dense_numerical_features_name, + input2_dim=dense_model.num_numerical_features, + output1=c.dense_output_name, + max_batch_size=max_batch_size, + engine_count_per_device=engine_count_per_device, + ) + f.write(s) + + return dense_model.num_numerical_features + + +if __name__ == "__main__": + main() diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_ensemble.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_ensemble.py new file mode 100644 index 000000000..dd84dd9b9 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_ensemble.py @@ -0,0 +1,94 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import os + + +_config_template = ''' +name: "{ensemble_name}" +platform: "ensemble" +max_batch_size: {max_batch_size} +input [ + {{ + name: "categorical_features" + data_type: TYPE_INT32 + dims: [{num_cat_features}] + }}, + {{ + name: "numerical_features" + data_type: TYPE_FP32 + dims: [{num_numerical_features}] + }} +] +output [ + {{ + name: "DENSE_OUTPUT" + data_type: TYPE_FP32 + dims: [1] + }} +] +ensemble_scheduling {{ + step [ + {{ + model_name: "{sparse_model_name}" + model_version: -1 + input_map {{ + key: "input_1" + value: "categorical_features" + }}, + output_map {{ + key: "output_1" + value: "LOOKUP_VECTORS" + }} + }}, + {{ + model_name: "{dense_model_name}" + model_version: -1 + input_map {{ + key: "args_1" + value: "LOOKUP_VECTORS" + }}, + input_map {{ + key: "args_0" + value: "numerical_features" + }}, + output_map {{ + key: "output_1" + value: "DENSE_OUTPUT" + }} + }} + ] +}} +''' + + +def deploy_ensemble(dst, model_name, sparse_model_name, dense_model_name, + num_cat_features, num_numerical_features, max_batch_size, version): + config_str = _config_template.format( + ensemble_name=model_name, + dense_model_name=dense_model_name, + sparse_model_name=sparse_model_name, + num_cat_features=num_cat_features, + num_numerical_features=num_numerical_features, + max_batch_size=max_batch_size + ) + with open(os.path.join(dst, "config.pbtxt"), "w") as f: + f.write(config_str) + os.mkdir(os.path.join(dst, str(version))) + + print("Ensemble configuration:") + print(config_str) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_monolithic.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_monolithic.py new file mode 100644 index 000000000..cd7f69246 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_monolithic.py @@ -0,0 +1,113 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import json +import os + +import tensorflow as tf +from tensorflow.python.saved_model import save_options + +from nn.embedding import DualEmbeddingGroup +from nn.dense_model import DenseModel + + +class SparseModel(tf.keras.Model): + def __init__(self, cardinalities, output_dim, memory_threshold): + super().__init__() + self.cardinalities = cardinalities + self.output_dim = output_dim + self.embedding = DualEmbeddingGroup(cardinalities, output_dim, memory_threshold, use_mde_embeddings=False) + + @tf.function + def call(self, x): + x = self.embedding(x) + x = tf.reshape(x, [-1, len(self.cardinalities) * self.output_dim]) + return x + + +class Model(tf.keras.Model): + def __init__(self, sparse_submodel, dense_submodel, cpu): + super().__init__() + self.sparse_submodel = sparse_submodel + self.dense_submodel = dense_submodel + self.cpu = cpu + + def call(self, numerical_features, cat_features): + device = '/CPU:0' if self.cpu else '/GPU:0' + with tf.device(device): + embedding_outputs = self.sparse_submodel(cat_features) + y = self.dense_submodel(numerical_features, embedding_outputs) + return y + +def load_dense(src, model_precision, model_format): + dense_model = DenseModel.from_config(os.path.join(src, "config.json")) + if dense_model.amp and model_precision == "fp16" and model_format == 'tf-savedmodel': + policy = tf.keras.mixed_precision.Policy("mixed_float16") + tf.keras.mixed_precision.set_global_policy(policy) + + if dense_model.interaction == 'dot_custom_cuda': + dense_model.interaction = 'dot_tensorflow' + dense_model._create_interaction_op() + + dense_model.load_weights(os.path.join(src, "dense")) + + dense_model.transpose = False + dense_model.force_initialization(training=False) + return dense_model + + +def deploy_monolithic( + sparse_src, + dense_src, + dst, + model_name, + max_batch_size, + engine_count_per_device, + num_gpus=1, + version="1", + cpu=False, + model_precision='fp32' +): + + if model_precision == 'fp16': + policy = tf.keras.mixed_precision.Policy("mixed_float16") + tf.keras.mixed_precision.set_global_policy(policy) + + dense_model = load_dense(src=dense_src, model_precision=model_precision, model_format='tf-savedmodel') + + print("deploy monolithic dst: ", dst) + with open(os.path.join(sparse_src, "config.json")) as f: + src_config = json.load(f) + + num_cat_features = len(src_config["categorical_cardinalities"]) + src_paths = [os.path.join(sparse_src, f"feature_{i}.npy") for i in range(num_cat_features)] + + sparse_model = SparseModel(cardinalities=src_config["categorical_cardinalities"], + output_dim=src_config['embedding_dim'][0], + memory_threshold=75 if not cpu else 0) + + model = Model(sparse_submodel=sparse_model, dense_submodel=dense_model, cpu=cpu) + + dummy_batch_size = 65536 + dummy_categorical = tf.zeros(shape=(dummy_batch_size, len(src_config["categorical_cardinalities"])), dtype=tf.int32) + dummy_numerical = tf.zeros(shape=(dummy_batch_size, dense_model.num_numerical_features), dtype=tf.float32) + + _ = model(numerical_features=dummy_numerical, cat_features=dummy_categorical) + + options = save_options.SaveOptions(experimental_variable_policy=save_options.VariablePolicy.SAVE_VARIABLE_DEVICES) + savedmodel_dir = os.path.join(dst, model_name, version, 'model.savedmodel') + os.makedirs(savedmodel_dir) + tf.keras.models.save_model(model=model, filepath=savedmodel_dir, overwrite=True, options=options) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_sparse.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_sparse.py new file mode 100644 index 000000000..d63e71869 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/deploy_sparse.py @@ -0,0 +1,112 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import json +import os +import tensorflow as tf +from tensorflow.python.saved_model import save_options + + +from nn.embedding import DualEmbeddingGroup + +class Model(tf.keras.Model): + def __init__(self, cardinalities, output_dim, memory_threshold): + super().__init__() + self.cardinalities = cardinalities + self.output_dim = output_dim + self.embedding = DualEmbeddingGroup(cardinalities, output_dim, memory_threshold, use_mde_embeddings=False) + + @tf.function + def call(self, x): + x = self.embedding(x) + x = tf.reshape(x, [-1, len(self.cardinalities) * self.output_dim]) + return x + +_sparse_model_config_template = r"""name: "{model_name}" +platform: "tensorflow_savedmodel" +max_batch_size:{max_batch_size} +optimization {{ + execution_accelerators {{ + gpu_execution_accelerator {{ + name: "gpu_io" + }} + }} +}} +version_policy: {{ + specific:{{versions: {version}}} +}}, +instance_group [ + {{ + count: {engine_count_per_device} + kind : KIND_GPU + gpus : [0] + }} +]""" + + +def save_triton_config( + dst_path, model_name, version, max_batch_size, engine_count_per_device +): + config_str = _sparse_model_config_template.format( + model_name=model_name, + max_batch_size=max_batch_size, + version=version, + engine_count_per_device=engine_count_per_device, + ) + + with open(dst_path, "w") as f: + f.write(config_str) + print("Wrote sparse model Triton config to:", dst_path) + + +def deploy_sparse( + src, + dst, + model_name, + max_batch_size, + engine_count_per_device, + memory_threshold_gb, + num_gpus=1, + version="1", + **kwargs, +): + print("deploy sparse dst: ", dst) + with open(os.path.join(src, "config.json")) as f: + src_config = json.load(f) + + model = Model(cardinalities=src_config["categorical_cardinalities"], + output_dim=src_config['embedding_dim'][0], + memory_threshold=memory_threshold_gb) + + x = tf.zeros(shape=(65536, len(src_config["categorical_cardinalities"])), dtype=tf.int32) + _ = model(x) + + model.embedding.restore_checkpoint(src) + + options = save_options.SaveOptions(experimental_variable_policy=save_options.VariablePolicy.SAVE_VARIABLE_DEVICES) + savedmodel_dir = os.path.join(dst, '1', 'model.savedmodel') + os.makedirs(savedmodel_dir) + tf.keras.models.save_model(model=model, filepath=savedmodel_dir, overwrite=True, options=options) + + save_triton_config( + dst_path=os.path.join(dst, "config.pbtxt"), + model_name=model_name, + version=version, + max_batch_size=max_batch_size, + engine_count_per_device=engine_count_per_device, + ) + + return len(src_config["categorical_cardinalities"]) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/triton_ensemble_wrapper.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/triton_ensemble_wrapper.py new file mode 100644 index 000000000..f16bbdfd5 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/deployment/tf/triton_ensemble_wrapper.py @@ -0,0 +1,59 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import tritonclient.utils +import tritonclient.http +import numpy as np +import tensorflow as tf + +import deployment.tf.constants as c + + +class RecsysTritonEnsemble: + def __init__(self, model_name, num_tables, verbose, categorical_sizes, fused_embedding=True): + self.model_name = model_name + self.triton_client = tritonclient.http.InferenceServerClient(url="localhost:8000", verbose=verbose) + if not self.triton_client.is_server_live(): + raise ValueError('Triton server is not live!') + + print('triton model repo: ', self.triton_client.get_model_repository_index()) + + def __call__(self, inputs, sigmoid=False, training=False): + numerical_features, cat_features = list(inputs.values()) + + batch_size = cat_features[0].shape[0] + + cat_features = tf.concat(cat_features, axis=1).numpy().astype(np.int32) + numerical_features = numerical_features.numpy().astype(np.float32) + + inputs = [ + tritonclient.http.InferInput("categorical_features", + cat_features.shape, + tritonclient.utils.np_to_triton_dtype(np.int32)), + tritonclient.http.InferInput("numerical_features", + numerical_features.shape, + tritonclient.utils.np_to_triton_dtype(np.float32)), + ] + inputs[0].set_data_from_numpy(cat_features) + inputs[1].set_data_from_numpy(numerical_features) + + outputs = [tritonclient.http.InferRequestedOutput(c.ens_output_name)] + + response = self.triton_client.infer(self.model_name, inputs, outputs=outputs) + + result_np = response.as_numpy(c.ens_output_name) + result_np = result_np.reshape([batch_size]) + return result_np diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/dlrm.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dlrm.py new file mode 100644 index 000000000..24efcd111 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/dlrm.py @@ -0,0 +1,52 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +from absl import app, flags + + +def define_dlrm_specific_flags(): + flags.DEFINE_integer("batch_size", default=64 * 1024, help="Batch size used for training") + flags.DEFINE_integer("valid_batch_size", default=64 * 1024, help="Batch size used for validation") + flags.DEFINE_list("top_mlp_dims", [1024, 1024, 512, 256, 1], "Linear layer sizes for the top MLP") + flags.DEFINE_list("bottom_mlp_dims", [512, 256, 128], "Linear layer sizes for the bottom MLP") + flags.DEFINE_string("embedding_dim", default='128', help='Number of columns in the embedding tables') + flags.DEFINE_enum("optimizer", default="sgd", enum_values=['sgd', 'adam'], + help='The optimization algorithm to be used.') + flags.DEFINE_enum("interaction", default="dot_custom_cuda", enum_values=["dot_custom_cuda", "dot_tensorflow", "cross"], + help="Feature interaction implementation to use") + flags.DEFINE_float("learning_rate", default=24, help="Learning rate") + flags.DEFINE_float("beta1", default=0.9, help="Beta1 for the Adam optimizer") + flags.DEFINE_float("beta2", default=0.999, help="Bea2 for the Adam optimizer") + + flags.DEFINE_integer("warmup_steps", default=8000, + help='Number of steps over which to linearly increase the LR at the beginning') + flags.DEFINE_integer("decay_start_step", default=48000, help='Optimization step at which to start the poly LR decay') + flags.DEFINE_integer("decay_steps", default=24000, help='Number of steps over which to decay from base LR to 0') + + flags.DEFINE_integer("num_cross_layers", default=3, help='Number of cross layers for DCNv2') + flags.DEFINE_integer("cross_layer_projection_dim", default=512, help='Projection dimension used in the cross layers') + + +define_dlrm_specific_flags() +import main + + +def _main(argv): + main.main() + +if __name__ == '__main__': + app.run(_main) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/DCNv2.md b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/DCNv2.md new file mode 100644 index 000000000..9c92e2640 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/DCNv2.md @@ -0,0 +1,245 @@ +# DCNv2 for TensorFlow 2 + +## Table Of Contents + * [Model overview](#model-overview) + * [Model architecture](#model-architecture) + * [Quick Start Guide](#quick-start-guide) + * [Performance](#performance) + * [Benchmarking](#benchmarking) + * [Training performance benchmark](#training-performance-benchmark) + * [Inference performance benchmark](#inference-performance-benchmark) + * [Training process](#training-process) + * [Results](#results) + * [Training accuracy results](#training-accuracy-results) + * [Training accuracy: NVIDIA DGX A100 (8x A100 80GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-80gb) + * [Training stability test](#training-stability-test) + * [Training performance results](#training-performance-results) + * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-dgx-a100-8x-a100-80gb) + * [Inference performance results](#inference-performance-results) + * [Inference performance: NVIDIA DGX A100 (8x A100 80GB)](#inference-performance-nvidia-dgx-a100-8x-a100-80gb) + + +## Model overview + +The Deep Cross Network version 2 models (DCNv2) were first proposed in +[DCN V2: Improved Deep & Cross Network and Practical Lessons for Web-scale Learning to Rank Systems](https://arxiv.org/abs/2008.13535) +as an improvement upon [ Deep & Cross Network for Ad Click Predictions.](https://arxiv.org/abs/1708.05123). +It is a learning-to-rank algorithm designed to efficiently learn feature interactions. In this repository, we implement +an example of a DCNv2 model by replacing DLRM's dot interaction layer with a low-rank Deep Cross Network v2 interaction. + +For DCNv2, we also chose to use the Adam optimization algorithm to better reflect common industry practices. +This also significantly improves results on the Criteo 1TB dataset but also increases memory usage. + + +Similarly to our DLRM implementation, we use a technique +called frequency thresholding to demonstrate models of different sizes. +The table below summarizes the model sizes and frequency thresholds used in this repository. +"Total embedding size" means the amount of memory necessary for a single forward pass, while the "GPU Memory required for training" +also includes the memory needed to store the full optimizer state. + +The table below summarizes the model sizes and frequency thresholds used in this repository, for both the synthetic and real datasets supported. + +| Dataset | Frequency Threshold | Final dataset size | Intermediate preprocessing storage required | Suitable for accuracy tests | Total download & preprocess time | GPU Memory required for training | Total embedding size | Number of model parameters | +|:-------|:-------|:-------|:-------------|:-------------------|:-------------------|:-------------------|:-------------------|:-------------------| +| Synthetic T15 |15 | 6 GiB | None | No | ~Minutes | 48 GiB | 15.6 GiB | 4.2B | +| Synthetic T3 |3 | 6 GiB | None | No | ~Minutes | 250 GiB | 84.9 GiB | 22.8B | +| Synthetic T0 |0 | 6 GiB | None | No | ~Minutes | 1.27 TiB | 421 GiB | 113B | +| Real Criteo T15 |15 | 370 GiB | ~Terabytes | Yes | ~Hours | 48 GiB | 15.6 GiB | 4.2B | +| Real Criteo T3 |3 | 370 GiB | ~Terabytes | Yes | ~Hours | 250 GiB | 84.9 GiB | 22.8B | +| Real Criteo T0 |0 | 370 GiB | ~Terabytes | Yes | ~Hours | 1.27 TiB | 421 GiB | 113B | + +You can find a detailed description of the Criteo dataset preprocessing the [preprocessing documentation](./criteo_dataset.md#advanced). + +### Model architecture + +DCNv2 accepts two types of features: categorical and numerical. For each categorical feature, +an embedding table is used to provide a dense representation of each unique value. +The dense features enter the model and are transformed by a simple neural network referred to as "Bottom MLP". + +This part of the network consists of a series +of linear layers with ReLU activations. The output of the bottom MLP and the embedding vectors are then fed into the +Deep Cross Network v2 interaction layer. +The output of this layer is then concatenated +with the features resulting from the bottom MLP and fed +into the "top MLP," which is a series of dense layers with activations. +The model outputs a single number which can be interpreted as a likelihood of a certain user clicking an ad. + +

+ +
+Figure 1. The architecture of our DCNv2 model. +

+ +### Hardware requirements + +| Dataset | Disk space required | Total GPU memory required for training | Total embedding size | Suitable for accuracy tests | Total download & preprocess time | +|:-------|:-------------|:-------------------|:-------------------|:-------------------|:-------------------| +| Synthetic Criteo T15 | 370 GiB | 48 GiB | 16 GiB | No | ~Hours | +| Synthetic Criteo T3 | 370 GiB | 250 GiB | 82 GiB | No | ~Hours | +| Synthetic Criteo T0 | 370 GiB | 1.27 TiB | 421 GiB | No | ~Hours | +| Real Criteo T15 | 6 GiB | 48 GiB | 16 GiB | Yes | ~Minutes | +| Real Criteo T3 | 6 GiB | 250 GiB | 82 GiB | Yes | ~Minutes | +| Real Criteo T0 | 6 GiB | 1.27 TiB | 421 GiB | Yes | ~Minutes | + +## Quick Start Guide + +To train DCNv2 perform the following steps. +For the specifics concerning training and inference, +refer to the [Advanced](../README.md#advanced) section. + +1. Clone the repository. +``` +git clone https://github.com/NVIDIA/DeepLearningExamples +cd DeepLearningExamples/TensorFlow2/Recommendation/DLRM +``` + +2. Build and run a DCNv2 Docker container. +```bash +docker build -t train_docker_image . +docker run --cap-add SYS_NICE --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data train_docker_image bash +``` + +3. Generate a synthetic dataset. + +Downloading and preprocessing the Criteo 1TB dataset requires a lot of time and disk space. +Because of this we provide a synthetic dataset generator that roughly matches Criteo 1TB characteristics. +This will enable you to benchmark quickly. +If you prefer to benchmark on the real data, please follow [these instructions](./criteo_dataset.md#quick-start-guide) +to download and preprocess the dataset. + +```bash +python -m dataloading.generate_feature_spec --variant criteo_t15_synthetic --dst feature_spec.yaml +python -m dataloading.transcribe --src_dataset_type synthetic --src_dataset_path . \ + --dst_dataset_path /data/preprocessed --max_batches_train 1000 --max_batches_test 100 --dst_dataset_type tf_raw +``` +4. Verify the input data: + +After running `tree /data/preprocessed` you should see the following directory structure: +```bash +$ tree /data/preprocessed +/data/preprocessed +├── feature_spec.yaml +├── test +│   ├── cat_0.bin +│   ├── cat_1.bin +│   ├── ... +│   ├── label.bin +│   └── numerical.bin +└── train + ├── cat_0.bin + ├── cat_1.bin + ├── ... + ├── label.bin + └── numerical.bin + +2 directories, 57 files +``` + +5. Start training. + +- single-GPU: +```bash +horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dcnv2.py --dataset_path /data/preprocessed --amp --xla --save_checkpoint_path /data/checkpoint/ +``` + +- multi-GPU: +```bash +horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dcnv2.py --dataset_path /data/preprocessed --amp --xla --save_checkpoint_path /data/checkpoint/ +``` + +6. Start evaluation. + +To evaluate a previously trained checkpoint, append `--restore_checkpoint_path --mode eval` to the command used for training. For example, to test a checkpoint trained on 8xA100 80GB, run: + +```bash +horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dcnv2.py --dataset_path /data/preprocessed --amp --xla --restore_checkpoint_path /data/checkpoint/ --mode eval +``` + +## Performance + +The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to [NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). + +### Benchmarking + +The following section shows how to run benchmarks measuring the model performance in training and inference modes. + +#### Training performance benchmark + +To benchmark the training performance on a specific batch size, follow the instructions +in the [Quick Start Guide](#quick-start-guide). You can also add the `--max_steps 1000` +if you want to get a reliable throughput measurement without running the entire training. + +You can also use synthetic data by running with the `--dataset_type synthetic` option if you haven't downloaded the dataset yet. + +#### Inference performance benchmark + +To benchmark the inference performance on a specific batch size, run: + +``` +horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dcnv2.py --dataset_path /data/preprocessed --amp --restore_checkpoint_path --mode inference +``` + +### Training process + +The main training scripts resides in `dcnv2.py`. The training speed is measured by throughput, that is, +the number of samples processed per second. +We use mixed precision training with static loss scaling for the bottom and top MLPs +while embedding tables are stored in FP32 format. + +### Results + +The following sections provide details on how we achieved our performance and accuracy in training and inference. + +We used three model size variants to show memory scalability in a multi-GPU setup +(4.2B params, 22.8B params, and 113B params). Refer to the [Model overview](#model-overview) section for detailed +information about the model variants. + +#### Training accuracy results + +##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) + +Our results were obtained by running training scripts as described in the Quick Start Guide in the DCNv2 Docker container. + +| GPUs | Model size | Batch size / GPU | Accuracy (AUC) - TF32 | Accuracy (AUC) - mixed precision | Time to train - TF32 [minutes] | Time to train - mixed precision [minutes] | Time to train speedup (TF32 to mixed precision) | +|:-------|:-------------|:-------------------|:------------------------|:-----------------------------------|:---------------------------------|:--------------------------------------------|:--------------------------------------------------| +| 1 | small | 64k | 0.8078 | 0.8077 | 102.7 | 51.7 | 1.99 | +| 8 | large | 8k | 0.8075 | 0.8074 | 19.5 | 13.3 | 1.33 | + + +##### Training stability test + +The histograms below show the distribution of ROC AUC results achieved at the end of the training. + +

+ +
+Figure 4. Results of stability tests for DCNv2. +

+ + +#### Training performance results + + +We used throughput in items processed per second as the performance metric. + + +##### Training performance: NVIDIA DGX A100 (8x A100 80GB) + +Our results were obtained by following the commands from the Quick Start Guide +in the DCNv2 Docker container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in items per second) were averaged over 1000 training steps. + +| GPUs | Model size | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 to mixed precision) | +|:-------|:-------------|:-------------------|:--------------------|:-------------------------------|:-----------------------------------------------| +| 1 | small | 64k | 0.689M | 1.37M | 1.99 | +| 8 | large | 8k | 3.81M | 5.75M | 1.51 | + + +To achieve the same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +#### Inference performance results + +##### Inference performance: NVIDIA DGX A100 (8x A100 80GB) + +| GPUs | Model size | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Average latency - TF32 [ms] | Average latency - mixed precision [ms] | Throughput speedup (mixed precision to TF32) | +|-------:|:-------------|-------------------:|:--------------------|:-------------------------------|------------------------------:|-----------------------------------------:|-----------------------------------------------:| +| 1 | small | 2048 | 1.30M | 1.31 | 1.57 | 1.56 | 1.01 | diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/DLRM.md b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/DLRM.md new file mode 100644 index 000000000..4bc1807cf --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/DLRM.md @@ -0,0 +1,308 @@ +# DLRM for TensorFlow 2 + +This document provides detailed instructions on running DLRM training as well as benchmark results for this model. + +## Table Of Contents + + * [Model overview](#model-overview) + * [Model architecture](#model-architecture) + * [Quick Start Guide](#quick-start-guide) + * [Performance](#performance) + * [Benchmarking](#benchmarking) + * [Training performance benchmark](#training-performance-benchmark) + * [Inference performance benchmark](#inference-performance-benchmark) + * [Training process](#training-process) + * [Results](#results) + * [Training accuracy results](#training-accuracy-results) + * [Training accuracy: NVIDIA DGX A100 (8x A100 80GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-80gb) + * [Training accuracy: NVIDIA DGX-1 (8x V100 32GB)](#training-accuracy-nvidia-dgx-1-8x-v100-32gb) + * [Training accuracy: NVIDIA DGX-2 (16x V100 32GB)](#training-accuracy-nvidia-dgx-2-16x-v100-32gb) + * [Training stability test](#training-stability-test) + * [Training performance results](#training-performance-results) + * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-dgx-a100-8x-a100-80gb) + * [Training performance: comparison with CPU for the "extra large" model](#training-performance-comparison-with-cpu-for-the-extra-large-model) + * [Training performance: NVIDIA DGX-1 (8x V100 32GB)](#training-performance-nvidia-dgx-1-8x-v100-32gb) + * [Training performance: NVIDIA DGX-2 (16x V100 32GB)](#training-performance-nvidia-dgx-2-16x-v100-32gb) + * [Inference performance results](#inference-performance-results) + * [Inference performance: NVIDIA DGX A100 (8x A100 80GB)](#inference-performance-nvidia-dgx-a100-8x-a100-80gb) + * [Inference performance: NVIDIA DGX1V-32GB (8x V100 32GB)](#inference-performance-nvidia-dgx1v-32gb-8x-v100-32gb) + * [Inference performance: NVIDIA DGX2 (16x V100 16GB)](#inference-performance-nvidia-dgx2-16x-v100-16gb) + + +## Model overview + +The Deep Learning Recommendation Model (DLRM) is a recommendation model designed to make use of both categorical and numerical inputs. +It was first described in [Deep Learning Recommendation Model for Personalization and Recommendation Systems](https://arxiv.org/abs/1906.00091). +This repository provides a reimplementation of the code base provided originally [here](https://github.com/facebookresearch/dlrm). +The scripts enable you to train DLRM on a synthetic dataset or on the [Criteo Terabyte Dataset](https://labs.criteo.com/2013/12/download-terabyte-click-logs/). + +For the Criteo 1TB Dataset, we use a slightly different preprocessing procedure than the one found in the original implementation. +Most importantly, we use a technique called frequency thresholding to demonstrate models of different sizes. +The smallest model can be trained on a single V100-32GB GPU, while the largest one needs 8xA100-80GB GPUs. + +The table below summarizes the model sizes and frequency thresholds used in this repository, for both the synthetic and real datasets supported. + +| Dataset | Frequency Threshold | Final dataset size | Intermediate preprocessing storage required | Suitable for accuracy tests | Total download & preprocess time |GPU Memory required for training | Total embedding size | Number of model parameters | +|:-------|:-------|:-------|:-------------|:-------------------|:-------------------|:-------------------|:-------------------|:-------------------| +| Synthetic T15 |15 | 6 GiB | None | No | ~Minutes | 15.6 GiB | 15.6 GiB | 4.2B | +| Synthetic T3 |3 | 6 GiB | None | No | ~Minutes | 84.9 GiB | 84.9 GiB | 22.8B | +| Synthetic T0 |0 | 6 GiB | None | No | ~Minutes | 421 GiB | 421 GiB | 113B | +| Real Criteo T15 |15 | 370 GiB | ~Terabytes | Yes | ~Hours | 15.6 GiB | 15.6 GiB | 4.2B | +| Real Criteo T3 |3 | 370 GiB | ~Terabytes | Yes | ~Hours | 84.9 GiB | 84.9 GiB | 22.8B | +| Real Criteo T0 |0 | 370 GiB | ~Terabytes | Yes | ~Hours | 421 GiB | 421 GiB | 113B | + +You can find a detailed description of the Criteo dataset preprocessing the [preprocessing documentation](./criteo_dataset.md#advanced). + +### Model architecture + +DLRM accepts two types of features: categorical and numerical. For each categorical feature, +an embedding table is used to provide a dense representation of each unique value. +The dense features enter the model and are transformed by a simple neural network referred to as "Bottom MLP." + +This part of the network consists of a series +of linear layers with ReLU activations. The output of the bottom MLP and the embedding vectors are then fed into the +"dot interaction" operation. The output of "dot interaction" is then concatenated +with the features resulting from the bottom MLP and fed +into the "top MLP," which is a series of dense layers with activations. +The model outputs a single number which can be interpreted as a likelihood of a certain user clicking an ad. + +

+ +
+Figure 1. The architecture of DLRM. +

+ +## Quick Start Guide + +To train DLRM perform the following steps. +For the specifics concerning training and inference, +refer to the [Advanced](../README.md#advanced) section. + +1. Clone the repository. +``` +git clone https://github.com/NVIDIA/DeepLearningExamples +cd DeepLearningExamples/TensorFlow2/Recommendation/DLRM +``` + +2. Build and run a DLRM Docker container. +```bash +docker build -t train_docker_image . +docker run --cap-add SYS_NICE --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data train_docker_image bash +``` + +3. Generate a synthetic dataset. + +Downloading and preprocessing the Criteo 1TB dataset requires a lot of time and disk space. +Because of this we provide a synthetic dataset generator that roughly matches Criteo 1TB characteristics. +This will enable you to benchmark quickly. +If you prefer to benchmark on the real data, please follow [these instructions](./criteo_dataset.md#quick-start-guide) +to download and preprocess the dataset. + +```bash +python -m dataloading.generate_feature_spec --variant criteo_t15_synthetic --dst feature_spec.yaml +python -m dataloading.transcribe --src_dataset_type synthetic --src_dataset_path . \ + --dst_dataset_path /data/preprocessed --max_batches_train 1000 --max_batches_test 100 --dst_dataset_type tf_raw +``` + +4. Verify the input data: + +After running `tree /data/preprocessed` you should see the following directory structure: +```bash +$ tree /data/preprocessed +/data/preprocessed +├── feature_spec.yaml +├── test +│   ├── cat_0.bin +│   ├── cat_1.bin +│   ├── ... +│   ├── label.bin +│   └── numerical.bin +└── train + ├── cat_0.bin + ├── cat_1.bin + ├── ... + ├── label.bin + └── numerical.bin + +2 directories, 57 files +``` + +5. Start training. + +- single-GPU: +```bash +horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dlrm.py --dataset_path /data/preprocessed --amp --xla --save_checkpoint_path /data/checkpoint/ +``` + +- multi-GPU: +```bash +horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dlrm.py --dataset_path /data/preprocessed --amp --xla --save_checkpoint_path /data/checkpoint/ +``` + +6. Start evaluation. + +To evaluate a previously trained checkpoint, append `--restore_checkpoint_path --mode eval` to the command used for training. For example, to test a checkpoint trained on 8xA100 80GB, run: + +```bash +horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dlrm.py --dataset_path /data/preprocessed --amp --xla --restore_checkpoint_path /data/checkpoint --mode eval +``` + +## Performance + +The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to [NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). + +### Benchmarking + +The following section shows how to run benchmarks measuring the model performance in training and inference modes. + +#### Training performance benchmark + +To benchmark the training performance on a specific batch size, follow the instructions +in the [Quick Start Guide](#quick-start-guide). You can also add the `--max_steps 1000` +if you want to get a reliable throughput measurement without running the entire training. + +You can also use synthetic data by running with the `--dataset_type synthetic` option if you haven't downloaded the dataset yet. + +#### Inference performance benchmark + +To benchmark the inference performance on a specific batch size, run: + +``` +horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u dlrm.py --dataset_path /data/preprocessed/ --amp --restore_checkpoint_path --mode inference +``` + +### Training process + +The main training scripts resides in `dlrm.py`. The training speed is measured by throughput, i.e., +the number of samples processed per second. +We use mixed precision training with static loss scaling for the bottom and top MLPs +while embedding tables are stored in FP32 format. + +### Results + +The following sections provide details on how we achieved our performance and accuracy in training and inference. + +We used three model size variants to show memory scalability in a multi-GPU setup +(4.2B params, 22.8B params, and 113B params). Refer to the [Model overview](#model-overview) section for detailed +information about the model variants. + +#### Training accuracy results + +##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) + +Our results were obtained by running training scripts as described in the Quick Start Guide in the DLRM Docker container. + +| GPUs | Model size | Batch size / GPU | Accuracy (AUC) - TF32 | Accuracy (AUC) - mixed precision | Time to train - TF32 [minutes] | Time to train - mixed precision [minutes] | Time to train speedup (TF32 to mixed precision) | +|:-------|:-------------|:-------------------|:------------------------|:-----------------------------------|:---------------------------------|:--------------------------------------------|:--------------------------------------------------| +| 1 | small | 64k | 0.8025 | 0.8025 | 26.75 | 16.27 | 1.64 | +| 8 | large | 8k | 0.8027 | 0.8026 | 8.77 | 6.57 | 1.33 | +| 8 | extra large | 8k | 0.8026 | 0.8026 | 10.47 | 9.08 | 1.15 | + +##### Training accuracy: NVIDIA DGX-1 (8x V100 32GB) + +Our results were obtained by running training scripts as described in the Quick Start Guide in the DLRM Docker container. + +| GPUs | Model size | Batch size / GPU | Accuracy (AUC) - FP32 | Accuracy (AUC) - mixed precision | Time to train - FP32 [minutes] | Time to train - mixed precision [minutes] | Time to train speedup (FP32 to mixed precision) | +|:-------|:-------------|:-------------------|:------------------------|:-----------------------------------|:---------------------------------|:--------------------------------------------|:--------------------------------------------------| +| 1 | small | 64k | 0.8027 | 0.8025 | 109.63 | 34.83 | 3.15 | +| 8 | large | 8k | 0.8028 | 0.8026 | 26.01 | 13.73 | 1.89 | +##### Training accuracy: NVIDIA DGX-2 (16x V100 32GB) + +Our results were obtained by running training scripts as described in the Quick Start Guide in the DLRM Docker container. + +| GPUs | Model size | Batch size / GPU | Accuracy (AUC) - FP32 | Accuracy (AUC) - mixed precision | Time to train - FP32 [minutes] | Time to train - mixed precision [minutes] | Time to train speedup (FP32 to mixed precision) | +|:-------|:-------------|:-------------------|:------------------------|:-----------------------------------|:---------------------------------|:--------------------------------------------|:--------------------------------------------------| +| 1 | small | 64k | 0.8026 | 0.8026 | 105.13 | 33.37 | 3.15 | +| 8 | large | 8k | 0.8027 | 0.8027 | 21.21 | 11.43 | 1.86 | +| 16 | large | 4k | 0.8025 | 0.8026 | 15.52 | 10.88 | 1.43 | + +##### Training stability test + +The histograms below show the distribution of ROC AUC results achieved at the end of the training for each precision/hardware platform tested. No statistically significant differences exist between precision, number of GPUs, or hardware platform. Using the larger dataset has a modest, positive impact on the final AUC score. + + +

+ +
+Figure 4. Results of stability tests for DLRM. +

+ + +#### Training performance results + + +We used throughput in items processed per second as the performance metric. + + +##### Training performance: NVIDIA DGX A100 (8x A100 80GB) + +Our results were obtained by following the commands from the Quick Start Guide +in the DLRM Docker container on NVIDIA DGX A100 (8x A100 80GB) GPUs. Performance numbers (in items per second) were averaged over 1000 training steps. + +| GPUs | Model size | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 to mixed precision) | +|:-------|:-------------|:-------------------|:--------------------|:-------------------------------|:-----------------------------------------------| +| 1 | small | 64k | 2.84M | 4.55M | 1.60 | +| 8 | large | 8k | 10.9M | 13.8M | 1.27 | +| 8 | extra large | 8k | 9.76M | 11.5M | 1.17 + +To achieve these results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +##### Training performance: comparison with CPU for the "extra large" model + +For the "extra large" model (113B parameters), we also obtained CPU results for comparison using the same source code +(using the `--cpu` command line flag for the CPU-only experiments). + +We compare three hardware setups: +- CPU only, +- a single GPU that uses CPU memory for the largest embedding tables, +- Hybrid-Parallel using the full DGX A100-80GB + +| Hardware | Throughput [samples / second]| Speedup over CPU| +|:---|:---|:---| +2xAMD EPYC 7742 | 17.7k | 1x | +1xA100-80GB + 2xAMD EPYC 7742 (large embeddings on CPU) | 768k |43x | +DGX A100 (8xA100-80GB) (hybrid parallel) | 11.5M | 649x | + + +##### Training performance: NVIDIA DGX-1 (8x V100 32GB) + +| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 to mixed precision) | +|:-------|:-------------|:-------------------|:--------------------|:-------------------------------|:-----------------------------------------------| +| 1 | small | 64k | 0.663M | 2.23M | 3.37 | +| 8 | large | 8k | 3.13M | 6.31M | 2.02 | + +To achieve the same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + + +##### Training performance: NVIDIA DGX-2 (16x V100 32GB) + +| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 to mixed precision) | +|:-------|:-------------|:-------------------|:--------------------|:-------------------------------|:-----------------------------------------------| +| 1 | small | 64k | 0.698M | 2.44M | 3.49 | +| 8 | large | 8k | 3.79M | 7.82M | 2.06 | +| 16 | large | 4k | 6.43M | 10.5M | 1.64 | + + +To achieve the same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +#### Inference performance results + +##### Inference performance: NVIDIA DGX A100 (8x A100 80GB) + +| GPUs | Model size | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Average latency - TF32 [ms] | Average latency - mixed precision [ms] | Throughput speedup (mixed precision to TF32) | +|-------:|:-------------|-------------------:|:--------------------|:-------------------------------|------------------------------:|-----------------------------------------:|-----------------------------------------------:| +| 1 | small | 2048 | 1.38M | 1.48M | 1.49 | 1.38 | 1.07 | + + +##### Inference performance: NVIDIA DGX1V-32GB (8x V100 32GB) + +| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Average latency - FP32 [ms] | Average latency - mixed precision [ms] | Throughput speedup (mixed precision to FP32) | +|-------:|:-------------|-------------------:|:--------------------|:-------------------------------|------------------------------:|-----------------------------------------:|-----------------------------------------------:| +| 1 | small | 2048 | 0.871M | 0.951M | 2.35 | 2.15 | 1.09 | + +##### Inference performance: NVIDIA DGX2 (16x V100 16GB) + +| GPUs | Model size | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Average latency - FP32 [ms] | Average latency - mixed precision [ms] | Throughput speedup (mixed precision to FP32) | +|-------:|:-------------|-------------------:|:--------------------|:-------------------------------|------------------------------:|-----------------------------------------:|-----------------------------------------------:| +| 1 | small | 2048 | 1.15M | 1.37M | 1.78 | 1.50 | 1.19 | + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/criteo_dataset.md b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/criteo_dataset.md new file mode 100644 index 000000000..0731f91b8 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/criteo_dataset.md @@ -0,0 +1,170 @@ +## Quick Start Guide + +To prepare the Criteo 1TB dataset for training, follow these steps. + +1. Make sure you meet the prerequisites. + +You will need around 4TB of storage for storing the original Criteo 1TB dataset, the results of some +intermediate preprocessing steps and the final dataset. The final dataset itself will take about 400GB. + +We recommend using local storage, such as a fast SSD drive, to run the preprocessing. Using other types of storage +will negatively impact the preprocessing time. + + +2. Build the preprocessing docker image. +```bash +docker build -t preproc_docker_image -f Dockerfile_spark . +``` + +3. Download the data by following the instructions at: http://labs.criteo.com/2013/12/download-terabyte-click-logs/. + +When you have successfully downloaded the dataset, put it in the `/data/criteo_orig` directory in the container +(`$PWD/data/criteo_orig` in the host system). + +4. Start an interactive session in the NGC container to run preprocessing. +The DLRM TensorFlow container can be launched with: + +```bash +mkdir -p data +docker run --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data preproc_docker_image bash +``` + +5. Unzip the data with: + +```bash +gunzip /data/criteo_orig/*.gz +``` + +6. Preprocess the data. + +Here are a few examples of different preprocessing commands. +For the details on how those scripts work and a detailed description of all the parameters, +consult the [preprocess with spark section](criteo_dataset.md#preprocess-with-spark). + +```bash +export download_dir=/data/criteo_orig +export final_output_dir=/data/preprocessed + +cd preproc + +# to run on a DGX-2 with a frequency limit of 3 (will need 8xV100-32GB to fit the model in GPU memory) +./prepare_dataset.sh DGX2 3 + +# to run on a DGX-2 with a frequency limit of 15 (should fit on a single V100-32GB): +./prepare_dataset.sh DGX2 15 + +# to run on CPU with a frequency limit of 15: +./prepare_dataset.sh CPU 15 + +# to run on DGX-2 with no frequency limit: +./prepare_dataset.sh DGX2 0 +``` + +7. Verify the preprocessed data + +After running `tree /data/preprocessed` you should see the following directory structure: +```bash +$ tree /data/preprocessed +/data/preprocessed +├── feature_spec.yaml +├── test +│   ├── cat_0.bin +│   ├── cat_1.bin +│   ├── ... +│   ├── label.bin +│   └── numerical.bin +└── train + ├── cat_0.bin + ├── cat_1.bin + ├── ... + ├── label.bin + └── numerical.bin + +2 directories, 57 files +``` + + +## Advanced + +### Dataset guidelines + +The first 23 days are used as the training set. The last day is split in half. +The first part is used as a validation set and the second set is used as a hold-out test set. + +The preprocessing steps applied to the raw data include: +- Replacing the missing values with `0`. +- Replacing the categorical values that exist fewer than 15 times with a special value. +- Converting the hash values to consecutive integers. +- Adding 2 to all the numerical features so that all of them are greater or equal to 1. +- Taking a natural logarithm of all numerical features. + + +### Preprocess with Spark + +The preprocessing scripts provided in this repository support running both on CPU and on DGX-2 using [Apache Spark 3.0](https://www.nvidia.com/en-us/deep-learning-ai/solutions/data-science/apache-spark-3/). +It should be possible to change the values in `preproc/dgx2_config.sh` +so that they'll work on other hardware platforms such as DGX-1. + +Note that the preprocessing will require about 4TB of disk storage. + +The syntax for the preprocessing script is as follows: +```bash +cd preproc +./prepare_dataset.sh +``` + +The first argument is the hardware platform to use (either DGX-2 or pure-CPU). The second argument means the frequency +threshold to apply to the categorical variables. For a frequency threshold `T`, the categorical values that occur less +often than `T` will be replaced with a special embedding. Thus, a larger value of `T` will require smaller embedding tables +and will substantially reduce the overall size of the model. + +For the Criteo Terabyte dataset we recommend a frequency threshold of `T=3` if you intend to run the hybrid-parallel mode +on multiple GPUs. If you want to make the model fit into a single NVIDIA Tesla V100-32GB, you can set `T=15`. + +The preprocessing scripts makes use of the following environment variables to configure the data directory paths: +- `download_dir` – this directory should contain the original Criteo Terabyte CSV files +- `spark_output_path` – directory to which the parquet data will be written +- `conversion_intermediate_dir` – directory used for storing intermediate data used to convert from parquet to train-ready format +- `final_output_dir` – directory to store the final results of the preprocessing which can then be used to train DLRM + +The script `spark_data_utils.py` is a PySpark application, which is used to preprocess the Criteo Terabyte Dataset. In the Docker image, we have installed Spark 3.0.1, which will start a standalone cluster of Spark. The scripts `run_spark_cpu.sh` and `run_spark_gpu.sh` start Spark, then runs several PySpark jobs with `spark_data_utils.py`, for example: +generates the dictionary +- transforms the train dataset +- transforms the test dataset +- transforms the validation dataset + + Change the variables in the `run-spark.sh` script according to your environment. + Configure the paths. +``` +export SPARK_LOCAL_DIRS=/data/spark-tmp +export INPUT_PATH=/data/criteo +export OUTPUT_PATH=/data/output +``` +Note that the Spark job requires about 3TB disk space used for data shuffle. + +Where: +`SPARK_LOCAL_DIRS` is the path where Spark uses to write shuffle data. +`INPUT_PATH` is the path of the Criteo Terabyte Dataset, including uncompressed files like day_0, day_1… +`OUTPUT_PATH` is where the script writes the output data. It will generate the following subdirectories of `models`, `train`, `test`, and `validation`. +- The `model` is the dictionary folder. +- The `train` is the train dataset transformed from day_0 to day_22. +- The `test` is the test dataset transformed from the prior half of day_23. +- The `validation` is the dataset transformed from the latter half of day_23. + +Configure the resources which Spark will use. +``` +export TOTAL_CORES=80 +export TOTAL_MEMORY=800 +``` + +Where: +`TOTAL_CORES` is the total CPU cores you want Spark to use. + +`TOTAL_MEMORY` is the total memory Spark will use. + +Configure frequency limit. +``` +USE_FREQUENCY_LIMIT=15 +``` +The frequency limit is used to filter out the categorical values which appear less than n times in the whole dataset, and make them be 0. Change this variable to 1 to enable it. The default frequency limit is 15 in the script. You also can change the number as you want by changing the line of `OPTS="--frequency_limit 8"`. + diff --git a/TensorFlow2/Recommendation/DLRM/img/columnwise_split.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/columnwise_split.svg similarity index 100% rename from TensorFlow2/Recommendation/DLRM/img/columnwise_split.svg rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/columnwise_split.svg diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dcnv2_singlegpu_architecture.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dcnv2_singlegpu_architecture.svg new file mode 100644 index 000000000..11c59dbeb --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dcnv2_singlegpu_architecture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dcnv2_stability_test.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dcnv2_stability_test.svg new file mode 100644 index 000000000..eaa1397be --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dcnv2_stability_test.svg @@ -0,0 +1,1312 @@ + + + + + + + + 2023-04-20T15:50:20.202493 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM/img/df_diagram.png b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/df_diagram.png similarity index 100% rename from TensorFlow2/Recommendation/DLRM/img/df_diagram.png rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/df_diagram.png diff --git a/TensorFlow2/Recommendation/DLRM/img/dlrm_histograms.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dlrm_histograms.svg similarity index 100% rename from TensorFlow2/Recommendation/DLRM/img/dlrm_histograms.svg rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dlrm_histograms.svg diff --git a/TensorFlow2/Recommendation/DLRM/img/singlegpu_architecture.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dlrm_singlegpu_architecture.svg similarity index 100% rename from TensorFlow2/Recommendation/DLRM/img/singlegpu_architecture.svg rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/dlrm_singlegpu_architecture.svg diff --git a/TensorFlow2/Recommendation/DLRM/img/hybrid_parallel.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/hybrid_parallel.svg similarity index 100% rename from TensorFlow2/Recommendation/DLRM/img/hybrid_parallel.svg rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/hybrid_parallel.svg diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/cache_approach.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/cache_approach.svg new file mode 100644 index 000000000..4eeaa3a0e --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/cache_approach.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/hps_tensorrt_architecture.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/hps_tensorrt_architecture.svg new file mode 100644 index 000000000..dacf4a6c6 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/hps_tensorrt_architecture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_a30-24gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_a30-24gb_t3_fp16.svg new file mode 100644 index 000000000..88f2bfb22 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_a30-24gb_t3_fp16.svg @@ -0,0 +1,1462 @@ + + + + + + + + 2023-04-18T16:39:14.743323 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_a30-24gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_a30-24gb_t3_fp32.svg new file mode 100644 index 000000000..bda135861 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_a30-24gb_t3_fp32.svg @@ -0,0 +1,1364 @@ + + + + + + + + 2023-04-18T16:39:14.608101 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_dgx-a100-80gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_dgx-a100-80gb_t3_fp16.svg new file mode 100644 index 000000000..97a424eb8 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_dgx-a100-80gb_t3_fp16.svg @@ -0,0 +1,1440 @@ + + + + + + + + 2023-04-18T16:39:14.461702 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_dgx-a100-80gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_dgx-a100-80gb_t3_fp32.svg new file mode 100644 index 000000000..f68c5732e --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_dgx-a100-80gb_t3_fp32.svg @@ -0,0 +1,1462 @@ + + + + + + + + 2023-04-18T16:39:14.308971 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_t4-16gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_t4-16gb_t3_fp16.svg new file mode 100644 index 000000000..899b74764 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_t4-16gb_t3_fp16.svg @@ -0,0 +1,1444 @@ + + + + + + + + 2023-04-18T16:39:15.047543 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_t4-16gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_t4-16gb_t3_fp32.svg new file mode 100644 index 000000000..3b706fbfb --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dcnv2_t4-16gb_t3_fp32.svg @@ -0,0 +1,1455 @@ + + + + + + + + 2023-04-18T16:39:14.896113 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_a30-24gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_a30-24gb_t3_fp16.svg new file mode 100644 index 000000000..25de034c0 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_a30-24gb_t3_fp16.svg @@ -0,0 +1,1459 @@ + + + + + + + + 2023-04-18T16:39:13.807401 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_a30-24gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_a30-24gb_t3_fp32.svg new file mode 100644 index 000000000..b91a805d5 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_a30-24gb_t3_fp32.svg @@ -0,0 +1,1482 @@ + + + + + + + + 2023-04-18T16:39:13.648357 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_dgx-a100-80gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_dgx-a100-80gb_t3_fp16.svg new file mode 100644 index 000000000..59890b1c0 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_dgx-a100-80gb_t3_fp16.svg @@ -0,0 +1,1457 @@ + + + + + + + + 2023-04-18T16:39:13.426063 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_dgx-a100-80gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_dgx-a100-80gb_t3_fp32.svg new file mode 100644 index 000000000..7c24392ee --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_dgx-a100-80gb_t3_fp32.svg @@ -0,0 +1,1442 @@ + + + + + + + + 2023-04-18T16:39:13.260902 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_t4-16gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_t4-16gb_t3_fp16.svg new file mode 100644 index 000000000..41a94c389 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_t4-16gb_t3_fp16.svg @@ -0,0 +1,1384 @@ + + + + + + + + 2023-04-18T16:39:14.170802 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_t4-16gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_t4-16gb_t3_fp32.svg new file mode 100644 index 000000000..160db6ce1 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/merlin_hps_dlrm_t4-16gb_t3_fp32.svg @@ -0,0 +1,1444 @@ + + + + + + + + 2023-04-18T16:39:14.001360 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/sorted_tables_approach.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/sorted_tables_approach.svg new file mode 100644 index 000000000..16b64b81b --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/sorted_tables_approach.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t15_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t15_fp16.svg new file mode 100644 index 000000000..5d0f54dac --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t15_fp16.svg @@ -0,0 +1,1611 @@ + + + + + + + + 2023-04-18T16:43:49.489073 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t15_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t15_fp32.svg new file mode 100644 index 000000000..959facc82 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t15_fp32.svg @@ -0,0 +1,1614 @@ + + + + + + + + 2023-04-18T16:43:49.289367 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t3_fp16.svg new file mode 100644 index 000000000..96d3676be --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t3_fp16.svg @@ -0,0 +1,1633 @@ + + + + + + + + 2023-04-18T16:43:49.909982 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t3_fp32.svg new file mode 100644 index 000000000..cd7d34d25 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_a30-24gb_t3_fp32.svg @@ -0,0 +1,1632 @@ + + + + + + + + 2023-04-18T16:43:49.677898 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t15_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t15_fp16.svg new file mode 100644 index 000000000..9331ef0ef --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t15_fp16.svg @@ -0,0 +1,1589 @@ + + + + + + + + 2023-04-18T16:43:48.690119 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t15_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t15_fp32.svg new file mode 100644 index 000000000..5057cbbab --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t15_fp32.svg @@ -0,0 +1,1614 @@ + + + + + + + + 2023-04-18T16:43:48.482546 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t3_fp16.svg new file mode 100644 index 000000000..aa679e407 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t3_fp16.svg @@ -0,0 +1,1633 @@ + + + + + + + + 2023-04-18T16:43:49.092032 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t3_fp32.svg new file mode 100644 index 000000000..6a3373b28 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_dgx-a100-80gb_t3_fp32.svg @@ -0,0 +1,1592 @@ + + + + + + + + 2023-04-18T16:43:48.884323 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t15_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t15_fp16.svg new file mode 100644 index 000000000..15e0675c8 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t15_fp16.svg @@ -0,0 +1,1604 @@ + + + + + + + + 2023-04-18T16:43:50.514472 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t15_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t15_fp32.svg new file mode 100644 index 000000000..4981d1892 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t15_fp32.svg @@ -0,0 +1,1606 @@ + + + + + + + + 2023-04-18T16:43:50.146530 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t3_fp16.svg new file mode 100644 index 000000000..66317f264 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t3_fp16.svg @@ -0,0 +1,1604 @@ + + + + + + + + 2023-04-18T16:43:50.910818 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t3_fp32.svg new file mode 100644 index 000000000..4caa05666 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dcnv2_t4-16gb_t3_fp32.svg @@ -0,0 +1,1626 @@ + + + + + + + + 2023-04-18T16:43:50.726672 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t15_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t15_fp16.svg new file mode 100644 index 000000000..b3b8daba5 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t15_fp16.svg @@ -0,0 +1,1613 @@ + + + + + + + + 2023-04-18T16:43:47.101301 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t15_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t15_fp32.svg new file mode 100644 index 000000000..c0996305d --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t15_fp32.svg @@ -0,0 +1,1555 @@ + + + + + + + + 2023-04-18T16:43:46.941342 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t3_fp16.svg new file mode 100644 index 000000000..a206e0cd2 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t3_fp16.svg @@ -0,0 +1,1574 @@ + + + + + + + + 2023-04-18T16:43:47.445114 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t3_fp32.svg new file mode 100644 index 000000000..646ec5d07 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_a30-24gb_t3_fp32.svg @@ -0,0 +1,1653 @@ + + + + + + + + 2023-04-18T16:43:47.269987 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t15_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t15_fp16.svg new file mode 100644 index 000000000..1090d3036 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t15_fp16.svg @@ -0,0 +1,1565 @@ + + + + + + + + 2023-04-18T16:43:46.446541 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t15_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t15_fp32.svg new file mode 100644 index 000000000..915a5bfa0 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t15_fp32.svg @@ -0,0 +1,1592 @@ + + + + + + + + 2023-04-18T16:43:46.277277 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t3_fp16.svg new file mode 100644 index 000000000..b8bf874ce --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t3_fp16.svg @@ -0,0 +1,1607 @@ + + + + + + + + 2023-04-18T16:43:46.775796 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t3_fp32.svg new file mode 100644 index 000000000..e77e1102f --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_dgx-a100-80gb_t3_fp32.svg @@ -0,0 +1,1604 @@ + + + + + + + + 2023-04-18T16:43:46.610094 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t15_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t15_fp16.svg new file mode 100644 index 000000000..b4275f9a8 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t15_fp16.svg @@ -0,0 +1,1593 @@ + + + + + + + + 2023-04-18T16:43:47.800561 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t15_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t15_fp32.svg new file mode 100644 index 000000000..9c103a67c --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t15_fp32.svg @@ -0,0 +1,1604 @@ + + + + + + + + 2023-04-18T16:43:47.623575 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t3_fp16.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t3_fp16.svg new file mode 100644 index 000000000..40dd40ff9 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t3_fp16.svg @@ -0,0 +1,1593 @@ + + + + + + + + 2023-04-18T16:43:48.313655 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t3_fp32.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t3_fp32.svg new file mode 100644 index 000000000..be4bf13e5 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tensorflow_dlrm_t4-16gb_t3_fp32.svg @@ -0,0 +1,1604 @@ + + + + + + + + 2023-04-18T16:43:48.126646 + image/svg+xml + + + Matplotlib v3.5.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tf_tensorrt_architecture.svg b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tf_tensorrt_architecture.svg new file mode 100644 index 000000000..6e1a09db5 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/inference/tf_tensorrt_architecture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM/img/layout_example.png b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/layout_example.png similarity index 100% rename from TensorFlow2/Recommendation/DLRM/img/layout_example.png rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/img/layout_example.png diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/merlin_hps_inference.md b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/merlin_hps_inference.md new file mode 100644 index 000000000..375da1a46 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/merlin_hps_inference.md @@ -0,0 +1,627 @@ +# Deploying Large Recommender models with Merlin HPS and Triton Inference Server + +This file contains instructions to run inference +on Triton Inference Server as well as detailed performance analysis for DLRM and DCNv2 +with Merlin HPS and TensorRT. It is intended to provide the best possible performance for +inference with recommender models that don't fit into a single GPU memory. + +For models that can fit into a single GPU or, for some reason, cannot use Merlin HPS, we maintain +a separate solution, described [here](tensorflow_inference.md). + + +## Solution overview +### Introduction + +The [NVIDIA Triton Inference Server](https://github.com/NVIDIA/triton-inference-server) +provides a data center and cloud inferencing solution optimized for NVIDIA GPUs. +The server provides an inference service via an HTTP or gRPC endpoint, +allowing remote clients to request inferencing for any number of GPU +or CPU models being managed by the server. + +This README provides step-by-step deployment instructions for models generated +during training (as described in the [model README](../README.md)). +Additionally, this README provides the corresponding deployment scripts that +ensure optimal GPU utilization during inferencing on Triton Inference Server. + +### Deployment with Merlin Hierarchical Parameter Server (HPS) + +[Merlin Hierarchical Parameter Server (HPS)](https://nvidia-merlin.github.io/HugeCTR/main/hierarchical_parameter_server/index.html) +library is a native C++ library that provides caching and +hierarchical storage for embeddings. The library is built from the GPU embedding cache +and HPS database backend subcomponents. + +HPS offers flexible deployment and configuration to meet site-specific recommender system needs and is integrated +by other projects that need the ability to work with embeddings that exceed the capacity of the GPU and host memory. + +Here, HPS is used to offload the least frequently used embedding vectors into CPU memory. This way, we can efficiently +serve models that do not fit in the GPU. This approach is illustrated in Figure 1. + +

+ +
+Figure 1. GPU cache as a way to serve very large embedding tables. +

+ +In the example below, the model served as a Triton Ensemble, that is, it is +composed of two submodels. The first submodel is the HPS part that handles the embedding lookup (sparse submodel). + +The second part is the dense submodel. It consists of the interaction layer and the MLPs with linear layers. Those are +run with NVIDIA TensorRT Triton backend. + +The communication between the submodels is managed efficiently with CUDA memory copies by Triton. + +This solution allows us to get the benefits of Merlin HPS for the sparse part as well as the latest performance optimizations +for the linear and interaction layers offered by NVIDIA TensorRT. The overall architecture of this approach is depicted in Figure 2. + +

+ +
+Figure 2. Overall architecture of the Merlin HPS + TensorRT ensemble for running large recommender inference. +

+ + +### Deployment process + +The deployment process consists of two steps: + +1. Conversion. + + The purpose of conversion is to transform the checkpoint saved during training into a ready-to-serve model. + +2. Configuration. + + Model configuration on Triton Inference Server that generates + necessary [configuration files](https://github.com/triton-inference-server/server/blob/master/docs/model_configuration.md). + +After deployment, the Triton inference server is used for the evaluation of the converted model in two steps: + +1. Correctness tests. + + Produce results that are tested against given correctness thresholds. + +2. Performance tests. + + Produce latency and throughput results for offline (static batching) + and online (dynamic batching) scenarios. + + +Refer to [Quick Start Guide](#quick-start-guide) for further instructions on performing these tests. + + +## Setup +Ensure you have the following components: +* [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) +* [NVIDIA TensorFlow NGC container 22.02](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tensorflow) +* [NVIDIA Triton Inference Server NGC container 22.02](https://ngc.nvidia.com/catalog/containers/nvidia:tritonserver) +* [NVIDIA CUDA](https://docs.nvidia.com/cuda/archive//index.html) +* [NVIDIA Ampere](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/), [Volta](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) or [Turing](https://www.nvidia.com/en-us/geforce/turing/) based GPU + + +## Quick Start Guide +The instructions below assume you have already cloned the repository, +built the training docker container, preprocessed the Criteo +1TB dataset, run the training and saved a model checkpoint. +If you haven't completed those steps, refer +to the [Quick Start Guide for DLRM](DLRM.md#quick-start-guide) +or the [Quick Start Guide to DCNv2](DCNv2.md#quick-start-guide), +depending on which model you'd like to deploy. + + +1. Build the Merlin HPS docker container: + +``` +cd deployment/hps +docker build -t hps_triton . +``` + +2. Run the training docker container built during the training stage: + +``` +# set input variables +checkpoint_path= +deploy_path= +dataset_path= + +mkdir -p $deploy_path +docker run -v $checkpoint_path:$checkpoint_path -v $deploy_path:$deploy_path -v $dataset_path:$dataset_path -it --rm --network=host --ipc=host \ + --shm-size=2g --ulimit memlock=-1 --ulimit stack=67108864 --gpus=all --cap-add SYS_NICE train_docker_image \ + bash +``` + +3. Convert the model checkpoint into a Triton model repository: + +``` +# set input variables inside the container +checkpoint_path= +deploy_path= +dataset_path= + +# run the deployment +horovodrun -np 1 --mpi-args=--oversubscribe numactl --interleave=all \ + python -m deployment.deploy --hps_gpucacheper 0.1 \ + --checkpoint-dir $checkpoint_path --model-repository-path $deploy_path --num_gpus 1\ + --fused_embedding --model-name dlrm --model-precision fp16 --dense-format trt\ + --sparse-format hps +``` + +4. In a separate terminal start the Triton Inference Server: + +``` +deploy_path= + +docker run -v $deploy_path:$deploy_path -it --rm --network=host --detach --ipc=host \ + --shm-size=2g --ulimit memlock=-1 --ulimit stack=67108864 --gpus=all hps_triton \ + bash -c "tritonserver --model-repository=${deploy_path} --backend-config=hps,ps=${deploy_path}/sparse/sparse.json\ + --pinned-memory-pool-byte-size=4000000000 --cuda-memory-pool-byte-size=0:2000000000 2>&1" +``` + +5. Switch back to the first terminal with the training container. Warm up the server with some initial requests: + +``` +python -u -m deployment.evaluate_accuracy --max_steps 1000 --dataset_path $dataset_path \ + --fused_embedding --model_name dlrm --test_on_train --batch_size 16384 --sparse_input_format hps +``` + +6. Measure inference execution speed + +``` +python -u -m deployment.evaluate_latency --sparse-format hps --model-name dlrm --dataset_path $dataset_path \ + --fused-embedding --measurement-request-count 50 --measurement-interval 5000 \ + --batch-sizes 4096 --num-benchmark-samples 262144 +``` + +7. Measure the prediction quality of the deployed model + +``` +python -u -m deployment.evaluate_accuracy --dataset_path $dataset_path --fused_embedding \ + --model_name dlrm --batch_size 16384 --sparse_input_format hps" +``` + + +## Performance +The performance measurements in this document were conducted at the time of publication and may not reflect +the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to +[NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). + + +### Offline scenario + +The offline scenario assumes the client and server are located on the same host. The tests uses: +- tensors are passed through shared memory between client and server, the Perf Analyzer flag `shared-memory=system` is used +- single request is send from client to server with static size of batch + +#### Offline: DLRM on NVIDIA DGX A100 (1x A100 80GB), Merlin HPS + TensorRT with FP32 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 3.64e+05 | 22 | 175 | 0 | 35 | 393 | 71 | 0 | 689 | 713 | 718 | 794 | 696 | +| 1 | 1024 | 1 | 1.25e+06 | 23 | 169 | 0 | 46 | 506 | 69 | 0 | 787 | 849 | 1054 | 1128 | 813 | +| 2 | 4096 | 1 | 2.33e+06 | 24 | 236 | 0 | 100 | 1276 | 114 | 0 | 1717 | 1748 | 1893 | 2408 | 1750 | +| 3 | 16384 | 1 | 2.88e+06 | 86 | 648 | 0 | 337 | 4291 | 320 | 0 | 5527 | 5602 | 7016 | 8573 | 5682 | +| 4 | 65536 | 1 | 3.36e+06 | 31 | 1210 | 0 | 1228 | 15777 | 1144 | 0 | 19093 | 19277 | 21757 | 24888 | 19390 | + + +
+ + + +#### Offline: DLRM on NVIDIA DGX A100 (1x A100 80GB), Merlin HPS + TensorRT with FP16 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 4.01e+05 | 23 | 156 | 0 | 33 | 351 | 69 | 0 | 624 | 661 | 669 | 738 | 632 | +| 1 | 1024 | 1 | 1.25e+06 | 23 | 211 | 0 | 52 | 456 | 68 | 0 | 786 | 807 | 1057 | 1130 | 810 | +| 2 | 4096 | 1 | 2.62e+06 | 26 | 294 | 0 | 99 | 1028 | 109 | 0 | 1533 | 1568 | 1579 | 1743 | 1556 | +| 3 | 16384 | 1 | 4.00e+06 | 27 | 379 | 0 | 328 | 3042 | 309 | 0 | 4001 | 4098 | 4627 | 5833 | 4085 | +| 4 | 65536 | 1 | 4.30e+06 | 34 | 1660 | 0 | 1227 | 11150 | 1102 | 0 | 14941 | 15309 | 16989 | 20144 | 15173 | + + +
+ + + +#### Offline: DLRM on NVIDIA A30, Merlin HPS + TensorRT with FP32 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 3.07e+05 | 22 | 194 | 0 | 42 | 512 | 57 | 0 | 801 | 832 | 1001 | 1103 | 827 | +| 1 | 1024 | 1 | 9.60e+05 | 30 | 194 | 0 | 78 | 690 | 65 | 0 | 1040 | 1120 | 1154 | 1475 | 1057 | +| 2 | 4096 | 1 | 1.38e+06 | 53 | 482 | 0 | 233 | 2014 | 181 | 0 | 2941 | 3009 | 3021 | 3059 | 2963 | +| 3 | 16384 | 1 | 1.71e+06 | 47 | 467 | 0 | 894 | 7529 | 648 | 0 | 9534 | 9714 | 9783 | 11371 | 9585 | +| 4 | 65536 | 1 | 1.79e+06 | 76 | 4207 | 1 | 2574 | 27369 | 2307 | 0 | 34512 | 39707 | 39914 | 61100 | 36534 | + + +
+ + + +#### Offline: DLRM on NVIDIA A30, Merlin HPS + TensorRT with FP16 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 3.30e+05 | 21 | 210 | 0 | 37 | 447 | 54 | 0 | 757 | 773 | 790 | 1035 | 769 | +| 1 | 1024 | 1 | 1.06e+06 | 22 | 220 | 0 | 95 | 567 | 58 | 0 | 955 | 978 | 986 | 1138 | 962 | +| 2 | 4096 | 1 | 1.49e+06 | 36 | 664 | 0 | 244 | 1623 | 172 | 0 | 2735 | 2770 | 2781 | 2820 | 2739 | +| 3 | 16384 | 1 | 2.17e+06 | 66 | 607 | 0 | 903 | 5357 | 606 | 0 | 7558 | 7633 | 7641 | 7662 | 7539 | +| 4 | 65536 | 1 | 2.40e+06 | 73 | 3640 | 1 | 2584 | 18617 | 2292 | 0 | 25568 | 31138 | 31241 | 39514 | 27207 | + + +
+ + + +#### Offline: DLRM on NVIDIA T4, Merlin HPS + TensorRT with FP32 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.33e+05 | 53 | 523 | 0 | 104 | 1156 | 75 | 0 | 1916 | 2120 | 2170 | 2295 | 1911 | +| 1 | 1024 | 1 | 3.76e+05 | 50 | 405 | 0 | 131 | 1957 | 159 | 0 | 2697 | 2804 | 2836 | 2904 | 2702 | +| 2 | 4096 | 1 | 4.41e+05 | 46 | 759 | 0 | 479 | 7384 | 610 | 0 | 9228 | 9511 | 9645 | 10538 | 9278 | +| 3 | 16384 | 1 | 4.77e+05 | 48 | 1219 | 1 | 1865 | 29110 | 1942 | 0 | 33483 | 34759 | 35025 | 55576 | 34185 | +| 4 | 65536 | 1 | 4.93e+05 | 54 | 4437 | 0 | 7400 | 113167 | 7262 | 0 | 131638 | 133320 | 133731 | 142058 | 132320 | + + +
+ + + +#### Offline: DLRM on NVIDIA T4, Merlin HPS + TensorRT with FP16 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 2.36e+05 | 28 | 201 | 0 | 83 | 703 | 63 | 0 | 1039 | 1250 | 1355 | 1593 | 1078 | +| 1 | 1024 | 1 | 4.92e+05 | 49 | 622 | 0 | 190 | 1112 | 95 | 0 | 2061 | 2220 | 2259 | 2324 | 2068 | +| 2 | 4096 | 1 | 7.55e+05 | 43 | 657 | 0 | 483 | 3600 | 626 | 0 | 5402 | 5514 | 5533 | 5599 | 5409 | +| 3 | 16384 | 1 | 8.73e+05 | 46 | 1120 | 0 | 1884 | 13703 | 1966 | 0 | 18175 | 19323 | 23458 | 29656 | 18719 | +| 4 | 65536 | 1 | 9.34e+05 | 40 | 3691 | 0 | 7466 | 51644 | 7330 | 0 | 69254 | 71662 | 72009 | 86622 | 70171 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA DGX A100 (1x A100 80GB), Merlin HPS + TensorRT with FP32 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 2.63e+05 | 23 | 159 | 0 | 36 | 681 | 69 | 0 | 955 | 983 | 1098 | 1137 | 968 | +| 1 | 1024 | 1 | 8.19e+05 | 22 | 204 | 0 | 50 | 897 | 68 | 0 | 1234 | 1254 | 1261 | 1384 | 1241 | +| 2 | 4096 | 1 | 1.25e+06 | 33 | 349 | 0 | 107 | 2681 | 105 | 0 | 3204 | 3316 | 4108 | 4271 | 3275 | +| 3 | 16384 | 1 | 1.31e+06 | 32 | 468 | 0 | 326 | 11346 | 329 | 0 | 12338 | 12459 | 14463 | 14674 | 12501 | +| 4 | 65536 | 1 | 1.33e+06 | 35 | 1180 | 0 | 1260 | 45518 | 1183 | 0 | 48985 | 49121 | 49142 | 54691 | 49176 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA DGX A100 (1x A100 80GB), Merlin HPS + TensorRT with FP16 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 3.17e+05 | 23 | 172 | 0 | 36 | 501 | 69 | 0 | 797 | 809 | 815 | 942 | 801 | +| 1 | 1024 | 1 | 1.03e+06 | 24 | 181 | 0 | 48 | 667 | 69 | 0 | 960 | 1018 | 1277 | 1337 | 989 | +| 2 | 4096 | 1 | 1.85e+06 | 24 | 276 | 0 | 101 | 1708 | 101 | 0 | 2144 | 2184 | 2485 | 3562 | 2210 | +| 3 | 16384 | 1 | 2.24e+06 | 82 | 429 | 0 | 327 | 6081 | 383 | 0 | 7056 | 7145 | 8028 | 9417 | 7302 | +| 4 | 65536 | 1 | 2.45e+06 | 33 | 1262 | 0 | 1237 | 23144 | 1102 | 0 | 26602 | 26709 | 26800 | 33534 | 26778 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA A30, Merlin HPS + TensorRT with FP32 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.85e+05 | 22 | 207 | 0 | 42 | 1036 | 70 | 0 | 1355 | 1377 | 1388 | 1442 | 1377 | +| 1 | 1024 | 1 | 5.64e+05 | 24 | 180 | 0 | 79 | 1458 | 66 | 0 | 1806 | 1824 | 1832 | 1866 | 1807 | +| 2 | 4096 | 1 | 7.55e+05 | 57 | 323 | 0 | 245 | 4629 | 156 | 0 | 5399 | 5484 | 5519 | 5588 | 5410 | +| 3 | 16384 | 1 | 8.16e+05 | 74 | 1249 | 1 | 899 | 17135 | 674 | 0 | 19579 | 20101 | 24995 | 27916 | 20032 | +| 4 | 65536 | 1 | 8.79e+05 | 78 | 1603 | 1 | 3586 | 66689 | 2346 | 0 | 73906 | 74311 | 74558 | 85554 | 74303 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA A30, Merlin HPS + TensorRT with FP16 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 2.72e+05 | 30 | 177 | 0 | 37 | 636 | 55 | 0 | 918 | 961 | 1108 | 1144 | 935 | +| 1 | 1024 | 1 | 7.02e+05 | 22 | 309 | 0 | 95 | 964 | 62 | 0 | 1436 | 1455 | 1462 | 1629 | 1452 | +| 2 | 4096 | 1 | 1.14e+06 | 57 | 319 | 1 | 243 | 2788 | 166 | 0 | 3579 | 3630 | 3647 | 3672 | 3574 | +| 3 | 16384 | 1 | 1.25e+06 | 72 | 1942 | 1 | 856 | 9644 | 626 | 0 | 13295 | 13556 | 13650 | 16335 | 13141 | +| 4 | 65536 | 1 | 1.42e+06 | 80 | 2698 | 1 | 2700 | 38237 | 2331 | 0 | 44644 | 48730 | 49194 | 61910 | 46047 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA T4, Merlin HPS + TensorRT with FP32 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 7.73e+04 | 46 | 523 | 0 | 101 | 2419 | 207 | 0 | 3272 | 3466 | 3528 | 3906 | 3296 | +| 1 | 1024 | 1 | 1.04e+05 | 51 | 556 | 0 | 195 | 8733 | 243 | 0 | 9477 | 10197 | 11500 | 15047 | 9778 | +| 2 | 4096 | 1 | 1.11e+05 | 63 | 936 | 0 | 473 | 34713 | 594 | 0 | 35969 | 38166 | 40363 | 55363 | 36779 | +| 3 | 16384 | 1 | 1.13e+05 | 159 | 1216 | 0 | 1834 | 138852 | 1952 | 0 | 143232 | 145827 | 147995 | 150841 | 144013 | +| 4 | 65536 | 1 | 1.12e+05 | 60 | 4961 | 0 | 7310 | 561876 | 7248 | 0 | 581850 | 585347 | 586993 | 593200 | 581455 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA T4, Merlin HPS + TensorRT with FP16 +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |NVDIA Merlin HPS + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (NVDIA Merlin HPS + NVIDIA TensorRT)| +| Max batch size |65536| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.42e+05 | 52 | 362 | 0 | 74 | 1222 | 73 | 0 | 1778 | 1915 | 1961 | 2032 | 1783 | +| 1 | 1024 | 1 | 3.27e+05 | 46 | 558 | 0 | 147 | 2097 | 264 | 0 | 3084 | 3241 | 3266 | 3584 | 3112 | +| 2 | 4096 | 1 | 4.09e+05 | 47 | 728 | 0 | 474 | 8106 | 638 | 0 | 9993 | 10239 | 10318 | 10551 | 9993 | +| 3 | 16384 | 1 | 4.30e+05 | 68 | 1695 | 0 | 1836 | 32338 | 1990 | 0 | 37402 | 39030 | 40043 | 50287 | 37927 | +| 4 | 65536 | 1 | 4.23e+05 | 54 | 4446 | 0 | 7287 | 135833 | 7202 | 0 | 154310 | 157113 | 157725 | 161462 | 154822 | + + +
+ +## Advanced +### Latency explanation +A typical Triton Inference Server pipeline can be broken down into the following steps: + +1. The client serializes the inference request into a message and sends it to +the server (Client Send). +2. The message travels over the network from the client to the server (Network). +3. The message arrives at the server and is deserialized (Server Receive). +4. The request is placed on the queue (Server Queue). +5. The request is removed from the queue and computed (Server Compute). +6. The completed request is serialized in a message and sent back to +the client (Server Send). +7. The completed message then travels over the network from the server +to the client (Network). +8. The completed message is deserialized by the client and processed as +a completed inference request (Client Receive). + +Generally, for local clients, steps 1-4 and 6-8 will only occupy +a small fraction of time compared to step 5. In distributed systems and online processing +where the client and server side are connected through a network, the send and receive steps might have an impact +on overall processing performance. In order to analyze the possible bottlenecks, detailed +charts are presented in online scenario cases. + + + +## Release Notes +We’re constantly refining and improving our performance on AI +and HPC workloads, even on the same hardware, with frequent updates +to our software stack. For our latest performance data, refer +to these pages for +[AI](https://developer.nvidia.com/deep-learning-performance-training-inference) +and [HPC](https://developer.nvidia.com/hpc-application-performance) benchmarks. + +### Changelog + +April 2023 +- Initial release + +### Known issues + +- There are no known issues with this model. diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/multidataset.md b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/multidataset.md new file mode 100644 index 000000000..1763eb4e3 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/multidataset.md @@ -0,0 +1,308 @@ +# BYO dataset functionality overview + +This section describes how you can train the DeepLearningExamples RecSys models on your own datasets without changing +the model or data loader and with similar performance to the one published in each repository. +This can be achieved thanks to Dataset Feature Specification, which describes how the dataset, data loader and model +interact with each other during training, inference and evaluation. +Dataset Feature Specification has a consistent format across all recommendation models in NVIDIA’s DeepLearningExamples +repository, regardless of dataset file type and the data loader, +giving you the flexibility to train RecSys models on your own datasets. + +- [Glossary](#glossary) +- [Dataset Feature Specification](#dataset-feature-specification) +- [Data Flow in Recommendation Models in DeepLearning examples](#data-flow-in-nvidia-deep-learning-examples-recommendation-models) +- [Example of Dataset Feature Specification](#example-of-dataset-feature-specification) +- [BYO dataset functionality](#byo-dataset-functionality) + +## Glossary + +The Dataset Feature Specification consists of three mandatory and one optional section: + +feature_spec provides a base of features that may be referenced in other sections, along with their metadata. + Format: dictionary (feature name) => (metadata name => metadata value)
+ +source_spec provides information necessary to extract features from the files that store them. + Format: dictionary (mapping name) => (list of chunks)
+ +* Mappings are used to represent different versions of the dataset (think: train/validation/test, k-fold splits). A mapping is a list of chunks.
+* Chunks are subsets of features that are grouped together for saving. For example, some formats may constrain data saved in one file to a single data type. In that case, each data type would correspond to at least one chunk. Another example where this might be used is to reduce file size and enable more parallel loading. Chunk description is a dictionary of three keys:
+ * type provides information about the format in which the data is stored. Not all formats are supported by all models.
+ * features is a list of features that are saved in a given chunk. Order of this list may matter: for some formats, it is crucial for assigning read data to the proper feature.
+ * files is a list of paths to files where the data is saved. For Feature Specification in yaml format, these paths are assumed to be relative to the yaml file’s directory (basename). Order of this list matters: It is assumed that rows 1 to i appear in the first file, rows i+1 to j in the next one, etc.
+ +channel_spec determines how features are used. It is a mapping (channel name) => (list of feature names). + +Channels are model specific magic constants. In general, data within a channel is processed using the same logic. Example channels: model output (labels), categorical ids, numerical inputs, user data, and item data. + +metadata is a catch-all, wildcard section: If there is some information about the saved dataset that does not fit into the other sections, you can store it here. + +## Dataset feature specification + +Data flow can be described abstractly: +Input data consists of a list of rows. Each row has the same number of columns; each column represents a feature. +The columns are retrieved from the input files, loaded, aggregated into channels and supplied to the model/training script. + +FeatureSpec contains metadata to configure this process and can be divided into three parts: + +* Specification of how data is organized on disk (source_spec). It describes which feature (from feature_spec) is stored in which file and how files are organized on disk. + +* Specification of features (feature_spec). Describes a dictionary of features, where key is feature name and values are features’ characteristics such as dtype and other metadata (for example, cardinalities for categorical features) + +* Specification of model’s inputs and outputs (channel_spec). Describes a dictionary of model’s inputs where keys specify model channel’s names and values specify lists of features to be loaded into that channel. Model’s channels are groups of data streams to which common model logic is applied, for example categorical/continuous data, user/item ids. Required/available channels depend on the model + + +The FeatureSpec is a common form of description regardless of underlying dataset format, dataset data loader form and model. + + +## Data flow in NVIDIA Deep Learning Examples recommendation models + +The typical data flow is as follows: +* S.0. Original dataset is downloaded to a specific folder. +* S.1. Original dataset is preprocessed into Intermediary Format. For each model, the preprocessing is done differently, using different tools. The Intermediary Format also varies (for example, for DLRM PyTorch, the Intermediary Format is a custom binary one.) +* S.2. The Preprocessing Step outputs Intermediary Format with dataset split into training and validation/testing parts along with the Dataset Feature Specification yaml file. Metadata in the preprocessing step is automatically calculated. +* S.3. Intermediary Format data together with Dataset Feature Specification are fed into training/evaluation scripts. Data loader reads Intermediary Format and feeds the data into the model according to the description in the Dataset Feature Specification. +* S.4. The model is trained and evaluated + + + +

+ +
+ +Fig.1. Data flow in Recommender models in NVIDIA Deep Learning Examples repository. Channels of the model are drawn in green. +

+ + +### Example of dataset feature specification + +As an example, let’s consider a Dataset Feature Specification for a small CSV dataset for some abstract model. + +```yaml +feature_spec: + user_gender: + dtype: torch.int8 + cardinality: 3 #M,F,Other + user_age: #treated as numeric value + dtype: torch.int8 + user_id: + dtype: torch.int32 + cardinality: 2655 + item_id: + dtype: torch.int32 + cardinality: 856 + label: + dtype: torch.float32 + +source_spec: + train: + - type: csv + features: + - user_gender + - user_age + files: + - train_data_0_0.csv + - train_data_0_1.csv + - type: csv + features: + - user_id + - item_id + - label + files: + - train_data_1.csv + test: + - type: csv + features: + - user_id + - item_id + - label + - user_gender + - user_age + + files: + - test_data.csv + +channel_spec: + numeric_inputs: + - user_age + categorical_user_inputs: + - user_gender + - user_id + categorical_item_inputs: + - item_id + label_ch: + - label +``` + + +The data contains five features: (user_gender, user_age, user_id, item_id, label). Their data types and necessary metadata are described in the feature specification section. + +In the source mapping section, two mappings are provided: one describes the layout of the training data, the other of the testing data. The layout for training data has been chosen arbitrarily to showcase the flexibility. +The train mapping consists of two chunks. The first one contains user_gender and user_age, saved as a CSV, and is further broken down into two files. For specifics of the layout, refer to the following example and consult the glossary. The second chunk contains the remaining columns and is saved in a single file. Notice that the order of columns is different in the second chunk - this is alright, as long as the order matches the order in that file (that is, columns in the .csv are also switched) + + +Let’s break down the train source mapping. The table contains example data color-paired to the files containing it. + +

+ +

+ + + +The channel spec describes how the data will be consumed. Four streams will be produced and available to the script/model. +The feature specification does not specify what happens further: names of these streams are only lookup constants defined by the model/script. +Based on this example, we can speculate that the model has three input channels: numeric_inputs, categorical_user_inputs, +categorical_item_inputs, and one output channel: label. +Feature names are internal to the FeatureSpec and can be freely modified. + + +### BYO dataset functionality + +In order to train any Recommendation model in NVIDIA Deep Learning Examples one can follow one of three possible ways: +* One delivers already preprocessed dataset in the Intermediary Format supported by data loader used by the training script +(different models use different data loaders) together with FeatureSpec yaml file describing at least specification of dataset, features and model channels + +* One uses a transcoding script + +* One delivers dataset in non-preprocessed form and uses preprocessing scripts that are a part of the model repository. +In order to use already existing preprocessing scripts, the format of the dataset needs to match the one of the original datasets. +This way, the FeatureSpec file will be generated automatically, but the user will have the same preprocessing as in the original model repository. + + + +### BYO dataset + +The BYO dataset functionality allows users to plug in their dataset in a common fashion for all Recommender models +that support this functionality. Using BYO dataset functionality, the user does not have to modify the source code of +the model thanks to the Feature Specification file. For general information on how BYO dataset works, refer to the +[BYO dataset overview section](#byo-dataset-functionality-overview). + +There are three ways to plug in user's dataset: +
+1. Provide an unprocessed dataset in a format matching the one used by Criteo 1TB, then use Criteo 1TB's preprocessing. Feature Specification file is then generated automatically. +The required format of the user's dataset is: + +The data should be split into text files. Each line of those text files should contain a single training example. +An example should consist of multiple fields separated by tabulators: + +* The first field is the label – 1 for a positive example and 0 for negative. +* The next N tokens should contain the numerical features separated by tabs. +* The next M tokens should contain the hashed categorical features separated by tabs. + +The correct dataset files together with the Feature Specification yaml file will be generated automatically by preprocessing script. + +For an example of using this process, refer to the [Quick Start Guide](#quick-start-guide) + +
+ +
+2. Provide a CSV containing preprocessed data and a simplified Feature Specification yaml file, then transcode the data with `transcode.py` script +This option should be used if the user has their own CSV file with a preprocessed dataset they want to train on. + +The required format of the user's dataset is: +* CSV files containing the data, already split into train and test sets. +* Feature Specification yaml file describing the layout of the CSV data + +For an example of a feature specification file, refer to the `tests/transcoding` folder. + +The CSV containing the data: +* should be already split into train and test +* should contain no header +* should contain one column per feature, in the order specified by the list of features for that chunk + in the source_spec section of the feature specification file +* categorical features should be non-negative integers in the range [0,cardinality-1] if cardinality is specified + +The Feature Specification yaml file: +* needs to describe the layout of data in CSV files +* may contain information about cardinalities. However, if set to `auto`, they will be inferred from the data by the transcoding script. + +Refer to `tests/transcoding/small_csv.yaml` for an example of the yaml Feature Specification. + +The following example shows how to use this way of plugging user's dataset: + +Prepare your data and save the path: +```bash +DATASET_PARENT_DIRECTORY=/raid/dlrm +``` + +Build the DLRM image with: +```bash +docker build -t nvidia_dlrm_tf . +``` +Launch the container with: +```bash +docker run --cap-add SYS_NICE --runtime=nvidia -it --rm --ipc=host -v ${DATASET_PARENT_DIRECTORY}/data:/data nvidia_dlrm_tf bash +``` + +If you are just testing the process, you can create synthetic csv data: +```bash +python gen_csv.py --feature_spec_in tests/transcoding/small_csv.yaml +``` + +Convert the data: +```bash +mkdir /data/conversion_output +cp tests/transcoding/small_csv.yaml /data/feature_spec.yaml +python transcode.py --input /data --output /data/converted +``` +You may need to tune the --chunk_size parameter. Higher values speed up the conversion but require more RAM. + +This will convert the data from `/data` and save the output in `/data/converted`. +A feature specification file describing the new data will be automatically generated. + +To run the training on 1 GPU: +```bash +horovodrun -np 1 -H localhost:1 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla +``` + +- multi-GPU for DGX A100: +```bash +horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla +``` + +- multi-GPU for DGX-1 and DGX-2: +```bash +horovodrun -np 8 -H localhost:8 --mpi-args=--oversubscribe numactl --interleave=all -- python -u main.py --dataset_path /data/converted --amp --xla +``` +
+
+3. Provide a fully preprocessed dataset, saved in split binary files, and a Feature Specification yaml file +This is the option to choose if you want full control over preprocessing and/or want to preprocess data directly to the target format. + +Your final output will need to contain a Feature Specification yaml describing data and file layout. +For an example feature specification file, refer to `tests/feature_specs/criteo_f15.yaml` + +For details, refer to the [BYO dataset overview section](#byo-dataset-functionality-overview). +
+ + + +#### Channel definitions and requirements + +This model defines three channels: + +- categorical, accepting an arbitrary number of features +- numerical, accepting an arbitrary number of features +- label, accepting a single feature + + +The training script expects two mappings: + +- train +- test + +For performance reasons: +* The only supported dataset type is split binary +* Splitting chunks into multiple files is not supported. +* Each categorical feature has to be provided in a separate chunk +* All numerical features have to be provided in a single chunk +* All numerical features have to appear in the same order in channel_spec and source_spec +* Only integer types are supported for categorical features +* Only float16 is supported for numerical features + +#### BYO dataset constraints for the model + +There are the following constraints of BYO dataset functionality for this model: +1. The performance of the model depends on the dataset size. Generally, the model should scale better for datasets containing more data points. For a smaller dataset, you might experience slower performance than the one reported for Criteo +2. Using other datasets might require tuning some hyperparameters (for example, learning rate, beta1 and beta2) to reach desired accuracy. +3. The optimized cuda interaction kernels for FP16 and TF32 assume that the number of categorical variables is smaller than WARP_SIZE=32 and embedding size is <=128 + diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/tensorflow_inference.md b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/tensorflow_inference.md new file mode 100644 index 000000000..2a87d9c17 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/doc/tensorflow_inference.md @@ -0,0 +1,1079 @@ +# Deploying Large Recommender models with TensorFlow and Triton Inference Server + +This file contains instructions to run inference +on Triton Inference Server as well as detailed performance analysis for DLRM and DCNv2 +with TensorFlow and TensorRT. It is intended to provide the best possible performance for +models that fit into a single GPU or, for some reason, cannot use Merlin HPS. + +When the best possible performance is required for models larger than single GPU memory, +we recommend the solution described [here](merlin_hps_inference.md) instead + +## Solution overview +### Introduction + +The [NVIDIA Triton Inference Server](https://github.com/NVIDIA/triton-inference-server) +provides a data center and cloud inferencing solution optimized for NVIDIA GPUs. +The server provides an inference service via an HTTP or gRPC endpoint, +allowing remote clients to request inferencing for any number of GPU +or CPU models being managed by the server. + +This README provides step-by-step deployment instructions for models generated +during training (as described in the [model README](../README.md)). +Additionally, this README provides the corresponding deployment scripts that +ensure optimal GPU utilization during inferencing on Triton Inference Server. + +### Deployment using a TensorFlow SavedModel + TensorRT ensemble + +Embedding tables used in recommender models can often get so large that serving them becomes challenging. In this example, +we show a way to serve a model that is larger than a GPU-memory device using CPU offloading. As opposed to the solution +shown in [the Merlin HPS inference guide](merlin_hps_inference.md), this guide does not use any custom Triton backends. + +The solution below also efficiently handles models that are large but can still fit into GPU memory. + +The first step is to sort the embedding tables by their size (from smallest to largest) and decide the amount of GPU memory to be spent +on storing the embeddings. First N smallest embedding tables that can be fit in this amount will be placed in GPU memory, +while the rest will be run on the CPU. This ensures that a large proportion of embedding lookups will be performed on the GPU. +This process is depicted in Figure 1. +The resulting part of the model that contains the embedding with encoded device placement is then saved in the TensorFlow +SavedModel format. We will refer to it as the "sparse submodel." + + +

+ +
+Figure 1. Sorting the embedding tables by size as a way to serve very large recommender models. +

+ + +The other part of the network that contains the interaction layer and the MLPs can benefit significantly from running it +with NVIDIA TensorRT. We, therefore, save it to a separate SavedModel file and then convert it first to the ONNX format +and then from the ONNX format to a TensorRT engine. We refer to this part as the "dense submodel." + +The entire model is run as a Triton Ensemble of the sparse and dense submodel. The communication between +the two parts is managed efficiently with CUDA memcopies by Triton. The overall architecture of this solution +is depicted in Figure 2. + +

+ +
+Figure 2. Overall architecture of the TF SavedModel + TensorRT ensemble for running large recommender inference. +

+ + +### Deployment process + +The deployment process consists of two steps: + +1. Conversion. + + The purpose of conversion is to transform the checkpoint saved during training into a ready-to-serve model. + +2. Configuration. + + Model configuration on Triton Inference Server, which generates + necessary [configuration files](https://github.com/triton-inference-server/server/blob/master/docs/model_configuration.md). + +After deployment, the Triton inference server is used for the evaluation of the converted model in two steps: + +1. Correctness tests. + + Produce results that are tested against given correctness thresholds. + +2. Performance tests. + + Produce latency and throughput results for offline (static batching) + and online (dynamic batching) scenarios. + + +Refer to [Quick Start Guide](#quick-start-guide) for further instructions on performing these tests. + +## Setup +Ensure you have the following components: +* [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) +* [NVIDIA TensorFlow NGC container 22.02](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tensorflow) +* [NVIDIA Triton Inference Server NGC container 22.02](https://ngc.nvidia.com/catalog/containers/nvidia:tritonserver) +* [NVIDIA CUDA](https://docs.nvidia.com/cuda/archive//index.html) +* [NVIDIA Ampere](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/), [Volta](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) or [Turing](https://www.nvidia.com/en-us/geforce/turing/) based GPU + + + +## Quick Start Guide +The instructions below assume you have already cloned the repository, +built the training docker container, preprocessed the Criteo +1TB dataset, run the training and saved a model checkpoint. +If you haven't completed those steps, refer +to the [Quick Start Guide for DLRM](DLRM.md#quick-start-guide) +or the [Quick Start Guide to DCNv2](DCNv2.md#quick-start-guide), +depending on which model you'd like to deploy. + + +1. Run the training docker container built during the training stage: + +``` +# set input variables +checkpoint_path= +deploy_path= +dataset_path= + +mkdir -p $deploy_path +docker run -v $checkpoint_path:$checkpoint_path -v $deploy_path:$deploy_path -v $dataset_path:$dataset_path -it --rm --network=host --ipc=host \ + --shm-size=2g --ulimit memlock=-1 --ulimit stack=67108864 --gpus=all --cap-add SYS_NICE train_docker_image \ + bash +``` + +2. Convert the model checkpoint into a Triton model repository: + +``` +# set input variables inside the container +checkpoint_path= +deploy_path= +dataset_path= + +# run the deployment +horovodrun -np 1 --mpi-args=--oversubscribe numactl --interleave=all \ + python -m deployment.deploy --checkpoint-dir $checkpoint_path --model-repository-path $deploy_path \ + --num_gpus 1 --fused_embedding --model-name dlrm --model-precision fp16 --dense-format trt \ + --sparse-format tf-savedmodel --memory-threshold-gb 60 +``` + +3. In a separate terminal, start the Triton Inference Server: + +``` +deploy_path= + +docker run -v $deploy_path:$deploy_path -it --rm --network=host --detach --ipc=host \ + --shm-size=2g --ulimit memlock=-1 --ulimit stack=67108864 --gpus=all nvcr.io/nvidia/tritonserver:23.02-py3 \ + bash -c "tritonserver --model-repository=${deploy_path} \ + --pinned-memory-pool-byte-size=4000000000 --cuda-memory-pool-byte-size=0:2000000000 2>&1" +``` + +4. Measure inference execution speed + +``` +python -u -m deployment.evaluate_latency --sparse-format tf-savedmodel --model-name dlrm --dataset_path $dataset_path \ + --fused-embedding --measurement-request-count 50 --measurement-interval 5000 \ + --num-benchmark-samples 262144 +``` + +5. Measure the prediction quality of the deployed model + +``` +python -u -m deployment.evaluate_accuracy --dataset_path $dataset_path --fused_embedding \ + --model_name dlrm --batch_size 16384 --sparse_input_format tf-savedmodel" +``` + + +## Performance +The performance measurements in this document were conducted at the time of publication and may not reflect +the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to +[NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). + + +### Offline scenario + +#### Offline: DLRM on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP32, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DLRM | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 3.99e+05 | 24 | 143 | 0 | 44 | 336 | 88 | 0 | 626 | 672 | 688 | 729 | 635 | +| 1 | 512 | 1 | 6.90e+05 | 31 | 152 | 0 | 55 | 406 | 91 | 0 | 738 | 770 | 789 | 814 | 735 | +| 2 | 1024 | 1 | 1.22e+06 | 34 | 162 | 0 | 72 | 472 | 94 | 0 | 830 | 863 | 884 | 906 | 834 | +| 3 | 2048 | 1 | 1.68e+06 | 26 | 164 | 0 | 127 | 772 | 124 | 0 | 1199 | 1274 | 1317 | 1341 | 1213 | +| 4 | 4096 | 1 | 2.46e+06 | 36 | 176 | 0 | 160 | 1128 | 157 | 0 | 1653 | 1669 | 1675 | 1716 | 1657 | +| 5 | 8192 | 1 | 3.08e+06 | 37 | 182 | 0 | 327 | 1879 | 222 | 0 | 2612 | 2721 | 2915 | 3135 | 2647 | +| 6 | 16384 | 1 | 3.36e+06 | 39 | 193 | 0 | 668 | 3623 | 349 | 0 | 4822 | 4979 | 5357 | 5505 | 4872 | +| 7 | 32768 | 1 | 3.85e+06 | 42 | 204 | 0 | 991 | 6623 | 627 | 0 | 8439 | 8584 | 8613 | 8768 | 8487 | + + +
+ + + +#### Offline: DLRM on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP16, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DLRM | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 4.00e+05 | 26 | 144 | 0 | 48 | 326 | 90 | 0 | 631 | 645 | 651 | 679 | 634 | +| 1 | 512 | 1 | 6.65e+05 | 23 | 161 | 0 | 62 | 417 | 99 | 0 | 762 | 779 | 786 | 803 | 762 | +| 2 | 1024 | 1 | 1.23e+06 | 23 | 160 | 0 | 80 | 457 | 106 | 0 | 821 | 837 | 843 | 865 | 826 | +| 3 | 2048 | 1 | 1.95e+06 | 25 | 158 | 0 | 125 | 615 | 123 | 0 | 1030 | 1102 | 1123 | 1157 | 1046 | +| 4 | 4096 | 1 | 2.89e+06 | 26 | 160 | 0 | 204 | 866 | 154 | 0 | 1393 | 1444 | 1515 | 1641 | 1410 | +| 5 | 8192 | 1 | 3.80e+06 | 35 | 173 | 0 | 364 | 1360 | 215 | 0 | 2115 | 2270 | 2377 | 2484 | 2147 | +| 6 | 16384 | 1 | 4.32e+06 | 38 | 209 | 0 | 751 | 2440 | 347 | 0 | 3741 | 3914 | 4060 | 4352 | 3785 | +| 7 | 32768 | 1 | 4.95e+06 | 44 | 223 | 0 | 1294 | 4449 | 614 | 0 | 6604 | 6758 | 6820 | 7107 | 6624 | + + +
+ + + +#### Offline: DLRM on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP32, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 2.44e+05 | 24 | 153 | 0 | 51 | 715 | 100 | 0 | 1029 | 1077 | 1103 | 1468 | 1043 | +| 1 | 512 | 1 | 4.10e+05 | 30 | 160 | 0 | 63 | 891 | 98 | 0 | 1241 | 1277 | 1289 | 1448 | 1242 | +| 2 | 1024 | 1 | 6.45e+05 | 24 | 157 | 0 | 88 | 1204 | 109 | 0 | 1559 | 1665 | 1705 | 2289 | 1582 | +| 3 | 2048 | 1 | 8.00e+05 | 23 | 160 | 0 | 179 | 2051 | 139 | 0 | 2478 | 2761 | 2880 | 3978 | 2552 | +| 4 | 4096 | 1 | 1.07e+06 | 34 | 190 | 0 | 305 | 3104 | 179 | 0 | 3514 | 4683 | 5312 | 7935 | 3812 | +| 5 | 8192 | 1 | 1.52e+06 | 39 | 201 | 0 | 425 | 4484 | 218 | 0 | 5213 | 5486 | 5567 | 7479 | 5367 | +| 6 | 16384 | 1 | 1.69e+06 | 43 | 221 | 0 | 853 | 8189 | 354 | 0 | 9473 | 10195 | 10620 | 12676 | 9660 | +| 7 | 32768 | 1 | 1.88e+06 | 53 | 267 | 0 | 1199 | 15221 | 631 | 0 | 16969 | 18753 | 20200 | 22143 | 17371 | + + +
+ + + +#### Offline: DLRM on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP16, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 2.58e+05 | 23 | 159 | 0 | 47 | 661 | 96 | 0 | 981 | 1000 | 1010 | 1103 | 986 | +| 1 | 512 | 1 | 4.33e+05 | 26 | 152 | 0 | 60 | 841 | 95 | 0 | 1182 | 1211 | 1220 | 1264 | 1174 | +| 2 | 1024 | 1 | 7.24e+05 | 23 | 130 | 0 | 76 | 1076 | 103 | 0 | 1402 | 1426 | 1435 | 1609 | 1408 | +| 3 | 2048 | 1 | 9.36e+05 | 24 | 134 | 0 | 124 | 1776 | 125 | 0 | 2131 | 2422 | 2486 | 2556 | 2183 | +| 4 | 4096 | 1 | 1.20e+06 | 27 | 141 | 0 | 215 | 2853 | 161 | 0 | 3236 | 4163 | 4436 | 4952 | 3397 | +| 5 | 8192 | 1 | 1.38e+06 | 38 | 196 | 0 | 398 | 5079 | 224 | 0 | 5625 | 7542 | 8188 | 10051 | 5935 | +| 6 | 16384 | 1 | 1.89e+06 | 45 | 225 | 0 | 797 | 7226 | 347 | 0 | 8472 | 9362 | 10036 | 11189 | 8640 | +| 7 | 32768 | 1 | 2.16e+06 | 43 | 246 | 0 | 1049 | 13171 | 620 | 0 | 14827 | 16124 | 16971 | 18651 | 15129 | + + +
+ + + +#### Offline: DLRM on NVIDIA A30, TensorFlow + TensorRT with FP32, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DLRM | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 2.31e+05 | 24 | 147 | 0 | 47 | 804 | 77 | 0 | 1086 | 1148 | 1224 | 1266 | 1099 | +| 1 | 512 | 1 | 3.67e+05 | 26 | 145 | 0 | 63 | 1070 | 82 | 0 | 1353 | 1552 | 1586 | 1740 | 1386 | +| 2 | 1024 | 1 | 5.36e+05 | 27 | 152 | 0 | 107 | 1517 | 101 | 0 | 1897 | 1977 | 1993 | 2068 | 1904 | +| 3 | 2048 | 1 | 5.53e+05 | 68 | 248 | 0 | 236 | 2997 | 142 | 0 | 3661 | 3928 | 4044 | 4351 | 3691 | +| 4 | 4096 | 1 | 6.18e+05 | 51 | 275 | 0 | 686 | 5374 | 220 | 0 | 6407 | 7397 | 8148 | 10301 | 6606 | +| 5 | 8192 | 1 | 7.94e+05 | 57 | 379 | 0 | 625 | 8812 | 410 | 0 | 9833 | 13872 | 15165 | 15940 | 10283 | +| 6 | 16384 | 1 | 9.77e+05 | 61 | 459 | 1 | 1251 | 14220 | 690 | 0 | 15220 | 20960 | 23930 | 27304 | 16682 | +| 7 | 32768 | 1 | 1.02e+06 | 101 | 577 | 2 | 2188 | 28085 | 1294 | 2 | 30168 | 43267 | 48349 | 54028 | 32249 | + + +
+ + + +#### Offline: DLRM on NVIDIA A30, TensorFlow + TensorRT with FP16, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DLRM | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.93e+05 | 59 | 237 | 1 | 65 | 852 | 100 | 1 | 1308 | 1346 | 1360 | 1428 | 1315 | +| 1 | 512 | 1 | 3.16e+05 | 60 | 244 | 1 | 91 | 1110 | 105 | 1 | 1606 | 1675 | 1699 | 1750 | 1612 | +| 2 | 1024 | 1 | 4.98e+05 | 64 | 253 | 1 | 147 | 1458 | 125 | 1 | 2013 | 2191 | 2275 | 2472 | 2049 | +| 3 | 2048 | 1 | 5.87e+05 | 105 | 323 | 1 | 258 | 2621 | 160 | 1 | 3436 | 3631 | 3813 | 4128 | 3469 | +| 4 | 4096 | 1 | 5.43e+05 | 108 | 423 | 2 | 1041 | 5735 | 237 | 1 | 7142 | 9926 | 10563 | 11887 | 7547 | +| 5 | 8192 | 1 | 7.86e+05 | 96 | 439 | 2 | 1155 | 8309 | 380 | 1 | 10056 | 14265 | 15897 | 18104 | 10382 | +| 6 | 16384 | 1 | 1.13e+06 | 96 | 471 | 2 | 1321 | 11777 | 729 | 1 | 13512 | 18506 | 19884 | 23454 | 14397 | +| 7 | 32768 | 1 | 1.27e+06 | 96 | 491 | 2 | 2062 | 22107 | 1272 | 1 | 23498 | 33255 | 38954 | 65158 | 26031 | + + +
+ + + +#### Offline: DLRM on NVIDIA A30, TensorFlow + TensorRT with FP32, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.93e+05 | 23 | 186 | 0 | 56 | 986 | 71 | 0 | 1307 | 1435 | 1481 | 1545 | 1322 | +| 1 | 512 | 1 | 2.80e+05 | 26 | 206 | 0 | 86 | 1423 | 79 | 0 | 1814 | 1884 | 1914 | 1973 | 1820 | +| 2 | 1024 | 1 | 1.99e+05 | 62 | 339 | 2 | 165 | 4453 | 119 | 0 | 5200 | 6259 | 6428 | 6966 | 5140 | +| 3 | 2048 | 1 | 3.00e+05 | 50 | 301 | 1 | 721 | 5571 | 167 | 0 | 6006 | 9340 | 10103 | 11385 | 6811 | +| 4 | 4096 | 1 | 3.49e+05 | 61 | 408 | 1 | 1782 | 9183 | 299 | 0 | 11165 | 15907 | 17936 | 23733 | 11734 | +| 5 | 8192 | 1 | 5.87e+05 | 65 | 380 | 1 | 1106 | 12027 | 360 | 0 | 13332 | 18063 | 21316 | 24739 | 13939 | +| 6 | 16384 | 1 | 6.85e+05 | 56 | 398 | 1 | 3061 | 19763 | 674 | 0 | 23218 | 31017 | 34275 | 38914 | 23953 | +| 7 | 32768 | 1 | 7.61e+05 | 69 | 496 | 1 | 9223 | 31973 | 1266 | 0 | 41964 | 55256 | 59519 | 65834 | 43028 | + + +
+ + + +#### Offline: DLRM on NVIDIA A30, TensorFlow + TensorRT with FP16, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.79e+05 | 57 | 244 | 1 | 60 | 969 | 93 | 1 | 1416 | 1497 | 1527 | 1637 | 1425 | +| 1 | 512 | 1 | 2.69e+05 | 63 | 264 | 1 | 88 | 1373 | 104 | 1 | 1865 | 1999 | 2050 | 2375 | 1894 | +| 2 | 1024 | 1 | 3.63e+05 | 67 | 253 | 1 | 133 | 2228 | 129 | 1 | 2806 | 2909 | 2933 | 3047 | 2812 | +| 3 | 2048 | 1 | 4.04e+05 | 113 | 344 | 1 | 262 | 4155 | 170 | 1 | 4996 | 5287 | 5401 | 5799 | 5046 | +| 4 | 4096 | 1 | 5.54e+05 | 72 | 277 | 1 | 643 | 6119 | 248 | 1 | 7329 | 9277 | 10541 | 12213 | 7361 | +| 5 | 8192 | 1 | 7.18e+05 | 74 | 313 | 2 | 1193 | 9424 | 382 | 1 | 10820 | 14038 | 15253 | 19589 | 11389 | +| 6 | 16384 | 1 | 8.89e+05 | 82 | 329 | 2 | 1646 | 15666 | 685 | 1 | 17436 | 23288 | 24813 | 27289 | 18411 | +| 7 | 32768 | 1 | 9.44e+05 | 87 | 420 | 2 | 4725 | 28180 | 1277 | 1 | 32825 | 44277 | 49607 | 56222 | 34692 | + + +
+ + + +#### Offline: DLRM on NVIDIA T4, TensorFlow + TensorRT with FP32, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DLRM | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.38e+05 | 47 | 282 | 0 | 75 | 1341 | 95 | 0 | 1788 | 2072 | 2144 | 2319 | 1840 | +| 1 | 512 | 1 | 1.87e+05 | 52 | 356 | 0 | 109 | 2078 | 131 | 0 | 2708 | 2936 | 3023 | 3190 | 2726 | +| 2 | 1024 | 1 | 2.34e+05 | 44 | 455 | 0 | 240 | 3395 | 227 | 0 | 4323 | 4653 | 4805 | 5763 | 4361 | +| 3 | 2048 | 1 | 2.59e+05 | 45 | 553 | 0 | 418 | 6382 | 498 | 0 | 7879 | 8220 | 8424 | 9091 | 7896 | +| 4 | 4096 | 1 | 3.15e+05 | 45 | 535 | 0 | 718 | 10922 | 744 | 0 | 12784 | 13496 | 13736 | 17274 | 12964 | +| 5 | 8192 | 1 | 3.47e+05 | 49 | 600 | 0 | 1293 | 20431 | 1183 | 0 | 23484 | 24332 | 24569 | 25045 | 23556 | +| 6 | 16384 | 1 | 3.57e+05 | 58 | 670 | 0 | 2448 | 40605 | 2077 | 0 | 45913 | 47110 | 47411 | 47908 | 45858 | +| 7 | 32768 | 1 | 3.63e+05 | 72 | 769 | 1 | 4837 | 80249 | 3924 | 0 | 89881 | 91684 | 92614 | 94206 | 89852 | + + +
+ + + +#### Offline: DLRM on NVIDIA T4, TensorFlow + TensorRT with FP16, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DLRM | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.86e+05 | 35 | 191 | 0 | 75 | 965 | 103 | 0 | 1356 | 1456 | 1501 | 1606 | 1369 | +| 1 | 512 | 1 | 2.48e+05 | 43 | 221 | 0 | 110 | 1513 | 172 | 0 | 2017 | 2263 | 2353 | 2565 | 2059 | +| 2 | 1024 | 1 | 2.81e+05 | 53 | 470 | 0 | 205 | 2676 | 224 | 0 | 3576 | 3950 | 4047 | 4400 | 3628 | +| 3 | 2048 | 1 | 3.38e+05 | 51 | 524 | 0 | 341 | 4735 | 380 | 0 | 5833 | 6743 | 7420 | 8829 | 6031 | +| 4 | 4096 | 1 | 4.29e+05 | 47 | 548 | 0 | 621 | 7603 | 720 | 0 | 9480 | 9910 | 10013 | 12769 | 9539 | +| 5 | 8192 | 1 | 4.75e+05 | 49 | 585 | 0 | 1202 | 14118 | 1191 | 0 | 16936 | 17653 | 18283 | 20753 | 17145 | +| 6 | 16384 | 1 | 5.08e+05 | 55 | 667 | 0 | 2371 | 26920 | 2094 | 0 | 32044 | 33005 | 33383 | 35777 | 32107 | +| 7 | 32768 | 1 | 5.27e+05 | 63 | 747 | 1 | 4668 | 52568 | 3899 | 0 | 62101 | 63747 | 64063 | 66173 | 61946 | + + +
+ + + +#### Offline: DLRM on NVIDIA T4, TensorFlow + TensorRT with FP32, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.47e+05 | 35 | 177 | 0 | 80 | 1357 | 91 | 0 | 1697 | 1948 | 2039 | 2342 | 1740 | +| 1 | 512 | 1 | 1.81e+05 | 57 | 238 | 0 | 123 | 2257 | 135 | 0 | 2801 | 3042 | 3118 | 3281 | 2810 | +| 2 | 1024 | 1 | 2.28e+05 | 48 | 490 | 0 | 236 | 3478 | 224 | 0 | 4448 | 4776 | 4885 | 5811 | 4476 | +| 3 | 2048 | 1 | 2.57e+05 | 44 | 530 | 0 | 364 | 6548 | 490 | 0 | 7966 | 8273 | 8391 | 9240 | 7976 | +| 4 | 4096 | 1 | 3.06e+05 | 45 | 518 | 0 | 648 | 11450 | 729 | 0 | 13389 | 13797 | 14082 | 14728 | 13390 | +| 5 | 8192 | 1 | 3.25e+05 | 49 | 570 | 0 | 1253 | 22088 | 1181 | 0 | 24847 | 25946 | 26689 | 36261 | 25141 | +| 6 | 16384 | 1 | 3.37e+05 | 67 | 654 | 1 | 2507 | 43155 | 2069 | 0 | 48132 | 49830 | 50316 | 54283 | 48453 | +| 7 | 32768 | 1 | 3.47e+05 | 77 | 763 | 1 | 4675 | 84544 | 3899 | 0 | 93086 | 96342 | 97109 | 101241 | 93959 | + + +
+ + + +#### Offline: DLRM on NVIDIA T4, TensorFlow + TensorRT with FP16, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DLRM | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.72e+05 | 44 | 249 | 0 | 75 | 1006 | 106 | 0 | 1472 | 1623 | 1670 | 1807 | 1480 | +| 1 | 512 | 1 | 2.40e+05 | 50 | 249 | 0 | 108 | 1535 | 180 | 0 | 2085 | 2355 | 2443 | 2656 | 2122 | +| 2 | 1024 | 1 | 2.83e+05 | 52 | 483 | 0 | 222 | 2574 | 272 | 0 | 3560 | 3879 | 4013 | 4351 | 3603 | +| 3 | 2048 | 1 | 3.44e+05 | 49 | 534 | 0 | 346 | 4634 | 376 | 0 | 5863 | 6467 | 6891 | 7474 | 5939 | +| 4 | 4096 | 1 | 4.04e+05 | 46 | 594 | 0 | 713 | 8003 | 735 | 0 | 10131 | 10606 | 10838 | 11176 | 10091 | +| 5 | 8192 | 1 | 4.61e+05 | 47 | 612 | 0 | 1220 | 14633 | 1226 | 0 | 17645 | 18614 | 18848 | 21215 | 17738 | +| 6 | 16384 | 1 | 4.91e+05 | 54 | 651 | 0 | 2406 | 28024 | 2112 | 0 | 33225 | 34406 | 34675 | 35664 | 33247 | +| 7 | 32768 | 1 | 4.94e+05 | 65 | 737 | 1 | 4816 | 56577 | 3944 | 0 | 65870 | 68351 | 69091 | 70905 | 66140 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP32, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DCNv2 | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 2.70e+05 | 23 | 149 | 0 | 49 | 630 | 93 | 0 | 929 | 953 | 1047 | 1112 | 944 | +| 1 | 512 | 1 | 4.95e+05 | 23 | 151 | 0 | 59 | 705 | 90 | 0 | 1032 | 1058 | 1172 | 1191 | 1028 | +| 2 | 1024 | 1 | 8.42e+05 | 23 | 152 | 0 | 76 | 862 | 96 | 0 | 1193 | 1233 | 1354 | 1396 | 1209 | +| 3 | 2048 | 1 | 1.08e+06 | 30 | 172 | 0 | 123 | 1421 | 150 | 0 | 1810 | 2047 | 2069 | 4216 | 1896 | +| 4 | 4096 | 1 | 1.37e+06 | 32 | 167 | 0 | 200 | 2414 | 166 | 0 | 2927 | 3072 | 3295 | 3435 | 2979 | +| 5 | 8192 | 1 | 1.49e+06 | 40 | 200 | 0 | 342 | 4649 | 239 | 0 | 5419 | 5587 | 5618 | 5749 | 5470 | +| 6 | 16384 | 1 | 1.41e+06 | 29 | 186 | 0 | 661 | 10358 | 348 | 0 | 11501 | 11719 | 12265 | 12401 | 11582 | +| 7 | 32768 | 1 | 1.37e+06 | 43 | 232 | 0 | 1379 | 21628 | 616 | 0 | 23233 | 23738 | 24043 | 24865 | 23898 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP16, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DCNv2 | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 3.39e+05 | 24 | 152 | 0 | 46 | 440 | 88 | 0 | 732 | 791 | 800 | 827 | 750 | +| 1 | 512 | 1 | 6.15e+05 | 23 | 150 | 0 | 58 | 505 | 91 | 0 | 826 | 854 | 905 | 935 | 827 | +| 2 | 1024 | 1 | 1.12e+06 | 23 | 150 | 0 | 74 | 566 | 98 | 0 | 901 | 929 | 1002 | 1034 | 911 | +| 3 | 2048 | 1 | 1.55e+06 | 23 | 154 | 0 | 122 | 894 | 121 | 0 | 1302 | 1332 | 1434 | 1465 | 1314 | +| 4 | 4096 | 1 | 2.16e+06 | 24 | 155 | 0 | 166 | 1387 | 157 | 0 | 1871 | 1909 | 2096 | 2173 | 1889 | +| 5 | 8192 | 1 | 2.53e+06 | 30 | 180 | 0 | 333 | 2458 | 231 | 0 | 3195 | 3399 | 3544 | 3731 | 3232 | +| 6 | 16384 | 1 | 2.48e+06 | 40 | 204 | 0 | 765 | 5201 | 367 | 0 | 6501 | 6684 | 7033 | 7235 | 6577 | +| 7 | 32768 | 1 | 2.67e+06 | 42 | 235 | 0 | 1243 | 10114 | 622 | 0 | 12115 | 12815 | 13240 | 14024 | 12256 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP32, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.92e+05 | 24 | 149 | 0 | 52 | 1012 | 91 | 0 | 1300 | 1411 | 1434 | 1555 | 1328 | +| 1 | 512 | 1 | 3.36e+05 | 24 | 152 | 0 | 62 | 1184 | 93 | 0 | 1511 | 1587 | 1658 | 1717 | 1515 | +| 2 | 1024 | 1 | 5.49e+05 | 24 | 155 | 0 | 79 | 1498 | 101 | 0 | 1836 | 1906 | 2009 | 2139 | 1857 | +| 3 | 2048 | 1 | 6.99e+05 | 26 | 156 | 0 | 124 | 2487 | 130 | 0 | 2857 | 3174 | 3308 | 3655 | 2923 | +| 4 | 4096 | 1 | 8.30e+05 | 30 | 177 | 0 | 215 | 4348 | 153 | 0 | 4812 | 5567 | 5971 | 6442 | 4923 | +| 5 | 8192 | 1 | 9.85e+05 | 45 | 209 | 0 | 414 | 7393 | 225 | 0 | 8177 | 8742 | 9208 | 10278 | 8286 | +| 6 | 16384 | 1 | 9.93e+05 | 49 | 233 | 0 | 843 | 14939 | 352 | 0 | 16206 | 17388 | 17870 | 18617 | 16416 | +| 7 | 32768 | 1 | 1.06e+06 | 49 | 259 | 0 | 1131 | 28711 | 628 | 0 | 30315 | 32463 | 33532 | 36270 | 30778 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA DGX A100 (1x A100 80GB), TensorFlow + TensorRT with FP16, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA DGX A100 (1x A100 80GB) | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.98e+05 | 34 | 198 | 0 | 61 | 884 | 106 | 0 | 1269 | 1327 | 1368 | 1480 | 1283 | +| 1 | 512 | 1 | 3.45e+05 | 29 | 191 | 0 | 76 | 1077 | 104 | 0 | 1467 | 1516 | 1539 | 1596 | 1477 | +| 2 | 1024 | 1 | 5.67e+05 | 36 | 192 | 0 | 101 | 1354 | 113 | 0 | 1782 | 1829 | 1848 | 2143 | 1796 | +| 3 | 2048 | 1 | 7.91e+05 | 36 | 183 | 0 | 158 | 2072 | 131 | 0 | 2553 | 2703 | 2800 | 3127 | 2580 | +| 4 | 4096 | 1 | 1.16e+06 | 36 | 179 | 0 | 254 | 2895 | 166 | 0 | 3449 | 3809 | 3965 | 5094 | 3530 | +| 5 | 8192 | 1 | 1.29e+06 | 55 | 261 | 0 | 449 | 5356 | 224 | 0 | 6194 | 7174 | 7493 | 8730 | 6345 | +| 6 | 16384 | 1 | 1.46e+06 | 46 | 250 | 0 | 748 | 9808 | 369 | 0 | 10971 | 12202 | 12713 | 14880 | 11221 | +| 7 | 32768 | 1 | 1.61e+06 | 44 | 266 | 0 | 1214 | 18171 | 659 | 0 | 19841 | 20937 | 23008 | 28718 | 20354 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA A30, TensorFlow + TensorRT with FP32, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DCNv2 | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.40e+05 | 60 | 222 | 1 | 51 | 1396 | 92 | 1 | 1789 | 1869 | 2256 | 2394 | 1823 | +| 1 | 512 | 1 | 2.35e+05 | 60 | 217 | 1 | 66 | 1721 | 100 | 1 | 2123 | 2375 | 2530 | 2916 | 2166 | +| 2 | 1024 | 1 | 3.43e+05 | 76 | 244 | 1 | 118 | 2410 | 124 | 1 | 2980 | 3053 | 3084 | 3226 | 2974 | +| 3 | 2048 | 1 | 3.72e+05 | 90 | 361 | 1 | 208 | 4646 | 169 | 1 | 5452 | 5804 | 6076 | 6376 | 5476 | +| 4 | 4096 | 1 | 5.14e+05 | 96 | 429 | 1 | 368 | 6770 | 262 | 1 | 7888 | 8321 | 8427 | 8842 | 7927 | +| 5 | 8192 | 1 | 6.25e+05 | 94 | 442 | 2 | 692 | 11322 | 537 | 1 | 13014 | 13343 | 13442 | 14706 | 13090 | +| 6 | 16384 | 1 | 6.41e+05 | 103 | 581 | 2 | 1292 | 22762 | 760 | 1 | 25280 | 27910 | 28633 | 29536 | 25501 | +| 7 | 32768 | 1 | 6.88e+05 | 112 | 641 | 2 | 2666 | 42753 | 1336 | 2 | 46470 | 50954 | 52078 | 56703 | 47512 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA A30, TensorFlow + TensorRT with FP16, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DCNv2 | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.84e+05 | 59 | 234 | 1 | 52 | 937 | 98 | 1 | 1369 | 1513 | 1569 | 1640 | 1382 | +| 1 | 512 | 1 | 2.99e+05 | 64 | 231 | 1 | 68 | 1231 | 107 | 1 | 1678 | 1849 | 1956 | 2055 | 1703 | +| 2 | 1024 | 1 | 4.25e+05 | 73 | 271 | 1 | 147 | 1781 | 127 | 1 | 2368 | 2578 | 2644 | 2786 | 2401 | +| 3 | 2048 | 1 | 4.97e+05 | 104 | 337 | 1 | 258 | 3224 | 171 | 1 | 4019 | 4501 | 4761 | 5127 | 4096 | +| 4 | 4096 | 1 | 4.71e+05 | 77 | 306 | 2 | 517 | 7521 | 256 | 1 | 8184 | 10650 | 12194 | 15546 | 8680 | +| 5 | 8192 | 1 | 7.56e+05 | 92 | 383 | 2 | 672 | 9269 | 391 | 1 | 9902 | 13945 | 14758 | 17802 | 10810 | +| 6 | 16384 | 1 | 9.28e+05 | 96 | 500 | 2 | 1141 | 15117 | 723 | 1 | 16894 | 21048 | 22180 | 25198 | 17580 | +| 7 | 32768 | 1 | 1.03e+06 | 103 | 589 | 2 | 2228 | 27519 | 1320 | 1 | 30467 | 35800 | 36760 | 39742 | 31762 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA A30, TensorFlow + TensorRT with FP32, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.41e+05 | 34 | 201 | 0 | 68 | 1422 | 86 | 0 | 1798 | 1937 | 2161 | 2380 | 1811 | +| 1 | 512 | 1 | 2.50e+05 | 37 | 193 | 0 | 91 | 1629 | 91 | 0 | 2015 | 2233 | 2318 | 2554 | 2041 | +| 2 | 1024 | 1 | 2.38e+05 | 39 | 248 | 0 | 149 | 3730 | 127 | 0 | 4226 | 5017 | 5430 | 6047 | 4293 | +| 3 | 2048 | 1 | 3.25e+05 | 64 | 331 | 0 | 209 | 5504 | 182 | 0 | 5933 | 7999 | 8351 | 9265 | 6290 | +| 4 | 4096 | 1 | 4.33e+05 | 60 | 336 | 0 | 345 | 8492 | 224 | 0 | 8519 | 12891 | 13500 | 14957 | 9457 | +| 5 | 8192 | 1 | 5.05e+05 | 69 | 328 | 0 | 757 | 14507 | 489 | 0 | 15555 | 20018 | 21217 | 24015 | 16150 | +| 6 | 16384 | 1 | 5.29e+05 | 70 | 452 | 1 | 1861 | 27757 | 729 | 0 | 30222 | 36890 | 38138 | 42585 | 30870 | +| 7 | 32768 | 1 | 5.61e+05 | 85 | 602 | 1 | 3301 | 52915 | 1302 | 0 | 57743 | 66789 | 69415 | 80008 | 58206 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA A30, TensorFlow + TensorRT with FP16, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA A30 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.75e+05 | 31 | 155 | 0 | 52 | 1136 | 78 | 0 | 1419 | 1591 | 1640 | 1831 | 1452 | +| 1 | 512 | 1 | 2.71e+05 | 33 | 163 | 0 | 82 | 1520 | 80 | 0 | 1849 | 1924 | 1958 | 3602 | 1878 | +| 2 | 1024 | 1 | 3.14e+05 | 73 | 260 | 0 | 148 | 2651 | 110 | 0 | 3218 | 3445 | 3536 | 5800 | 3242 | +| 3 | 2048 | 1 | 2.80e+05 | 58 | 209 | 0 | 245 | 6634 | 156 | 0 | 6994 | 10021 | 10424 | 10919 | 7302 | +| 4 | 4096 | 1 | 4.48e+05 | 68 | 283 | 0 | 346 | 8211 | 219 | 0 | 8385 | 12535 | 13358 | 16307 | 9127 | +| 5 | 8192 | 1 | 5.62e+05 | 77 | 271 | 0 | 650 | 13167 | 366 | 0 | 14355 | 18585 | 19638 | 22077 | 14531 | +| 6 | 16384 | 1 | 6.11e+05 | 83 | 377 | 0 | 2297 | 23271 | 680 | 0 | 26604 | 34647 | 36354 | 39316 | 26708 | +| 7 | 32768 | 1 | 7.17e+05 | 73 | 514 | 1 | 5409 | 38366 | 1279 | 0 | 44389 | 55813 | 58518 | 70669 | 45642 | + + +
+ + + +/tmp/ipykernel_771557/1052116882.py:9: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). + fig, axarr = plt.subplots(1, 2, figsize=[15, 3.5], dpi=100) +#### Offline: DCNv2 on NVIDIA T4, TensorFlow + TensorRT with FP32, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DCNv2 | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 7.86e+04 | 44 | 375 | 0 | 92 | 2501 | 236 | 0 | 3248 | 3415 | 3457 | 3569 | 3248 | +| 1 | 512 | 1 | 9.13e+04 | 44 | 433 | 0 | 131 | 4681 | 301 | 0 | 5447 | 5701 | 5830 | 9042 | 5590 | +| 2 | 1024 | 1 | 1.04e+05 | 45 | 435 | 0 | 203 | 8767 | 382 | 0 | 9849 | 10118 | 10238 | 11009 | 9832 | +| 3 | 2048 | 1 | 1.08e+05 | 46 | 407 | 0 | 341 | 17573 | 481 | 0 | 19072 | 19665 | 19791 | 20127 | 18848 | +| 4 | 4096 | 1 | 1.11e+05 | 49 | 433 | 0 | 620 | 34940 | 753 | 0 | 36648 | 38501 | 39238 | 40913 | 36795 | +| 5 | 8192 | 1 | 1.11e+05 | 54 | 520 | 0 | 1183 | 70303 | 1170 | 0 | 72605 | 75982 | 76263 | 80393 | 73230 | +| 6 | 16384 | 1 | 1.10e+05 | 67 | 587 | 0 | 2425 | 143325 | 2060 | 0 | 148529 | 150641 | 151048 | 154147 | 148464 | +| 7 | 32768 | 1 | 1.07e+05 | 98 | 846 | 1 | 4860 | 295283 | 3870 | 0 | 305032 | 308246 | 310093 | 311552 | 304958 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA T4, TensorFlow + TensorRT with FP16, 4B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DCNv2 | +| Model size | 4B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.09e+05 | 49 | 439 | 0 | 94 | 1579 | 171 | 0 | 2330 | 2553 | 2604 | 2704 | 2332 | +| 1 | 512 | 1 | 1.77e+05 | 51 | 367 | 0 | 124 | 2113 | 225 | 0 | 2880 | 3038 | 3080 | 3219 | 2880 | +| 2 | 1024 | 1 | 2.54e+05 | 40 | 361 | 0 | 198 | 3053 | 360 | 0 | 4000 | 4132 | 4192 | 4341 | 4012 | +| 3 | 2048 | 1 | 2.77e+05 | 49 | 535 | 0 | 348 | 5934 | 514 | 0 | 7334 | 7648 | 7793 | 9272 | 7380 | +| 4 | 4096 | 1 | 3.11e+05 | 48 | 541 | 0 | 644 | 11095 | 796 | 0 | 12911 | 13438 | 15733 | 18127 | 13124 | +| 5 | 8192 | 1 | 3.34e+05 | 50 | 576 | 0 | 1180 | 21472 | 1187 | 0 | 24101 | 25307 | 27011 | 30350 | 24465 | +| 6 | 16384 | 1 | 3.48e+05 | 59 | 662 | 0 | 2345 | 41747 | 2110 | 0 | 46995 | 47956 | 48105 | 48710 | 46923 | +| 7 | 32768 | 1 | 3.49e+05 | 69 | 756 | 1 | 4705 | 83982 | 3881 | 0 | 93290 | 95408 | 96025 | 97009 | 93394 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA T4, TensorFlow + TensorRT with FP32, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP32 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 7.24e+04 | 46 | 377 | 0 | 94 | 2710 | 297 | 0 | 3514 | 3707 | 3770 | 3848 | 3524 | +| 1 | 512 | 1 | 8.90e+04 | 48 | 467 | 0 | 133 | 4741 | 345 | 0 | 5717 | 5959 | 6026 | 6227 | 5734 | +| 2 | 1024 | 1 | 1.01e+05 | 46 | 562 | 0 | 217 | 8898 | 418 | 0 | 10061 | 10551 | 10735 | 12662 | 10141 | +| 3 | 2048 | 1 | 9.99e+04 | 46 | 612 | 0 | 431 | 18812 | 562 | 0 | 20075 | 21090 | 22357 | 31101 | 20463 | +| 4 | 4096 | 1 | 1.06e+05 | 46 | 655 | 0 | 727 | 36089 | 753 | 0 | 38056 | 39816 | 40214 | 48450 | 38270 | +| 5 | 8192 | 1 | 1.09e+05 | 49 | 668 | 1 | 1272 | 71380 | 1213 | 0 | 74280 | 75644 | 76134 | 77127 | 74583 | +| 6 | 16384 | 1 | 1.06e+05 | 72 | 817 | 1 | 2419 | 147768 | 2099 | 0 | 153166 | 155120 | 155385 | 156117 | 153176 | +| 7 | 32768 | 1 | 1.02e+05 | 89 | 940 | 1 | 4824 | 311509 | 3941 | 0 | 321135 | 325901 | 327276 | 330134 | 321304 | + + +
+ + + +#### Offline: DCNv2 on NVIDIA T4, TensorFlow + TensorRT with FP16, 22B parameters +Our results were obtained using the following configuration: + +| Parameter Name | Parameter Value | +|:-----------------------------|:-----------------------------| +| GPU |NVIDIA T4 | +| Model architecture | DCNv2 | +| Model size | 22B parameters | +| Backend |TensorFlow + NVIDIA TensorRT| +| Backend accelerator |-| +| Precision |FP16 | +| Model format |NVIDIA Triton Ensemble (TensorFlow SavedModel + NVIDIA TensorRT)| +| Max batch size |32768| +| Number of model instances |1| +| Export Format | TensorFlow SavedModel| +| NVIDIA TensorRT Capture CUDA Graph | Enabled| +| Device Kind | gpu| + +
Results Table + +| | Batch | Concurrency | Inferences/Second | Client Send | Network+Server Send/Recv | Server Queue | Server Compute Input | Server Compute Infer | Server Compute Output | Client Recv | p50 latency | p90 latency | p95 latency | p99 latency | avg latency | +|---:|--------:|--------------:|--------------------:|--------------:|---------------------------:|---------------:|-----------------------:|-----------------------:|------------------------:|--------------:|--------------:|--------------:|--------------:|--------------:|--------------:| +| 0 | 256 | 1 | 1.08e+05 | 44 | 398 | 0 | 93 | 1710 | 119 | 0 | 2341 | 2613 | 2725 | 3053 | 2364 | +| 1 | 512 | 1 | 1.57e+05 | 62 | 485 | 0 | 131 | 2418 | 147 | 0 | 3229 | 3460 | 3530 | 3859 | 3243 | +| 2 | 1024 | 1 | 2.15e+05 | 68 | 513 | 0 | 208 | 3619 | 339 | 0 | 4692 | 5164 | 5571 | 5999 | 4747 | +| 3 | 2048 | 1 | 2.64e+05 | 71 | 570 | 0 | 406 | 6183 | 504 | 0 | 7687 | 8198 | 8412 | 9083 | 7734 | +| 4 | 4096 | 1 | 3.02e+05 | 62 | 618 | 0 | 677 | 11380 | 792 | 0 | 13459 | 13972 | 14300 | 15488 | 13529 | +| 5 | 8192 | 1 | 3.21e+05 | 68 | 618 | 0 | 1257 | 22300 | 1193 | 0 | 25401 | 26175 | 26493 | 27150 | 25436 | +| 6 | 16384 | 1 | 3.37e+05 | 69 | 704 | 1 | 2488 | 43214 | 2089 | 0 | 48548 | 49881 | 50164 | 50964 | 48565 | +| 7 | 32768 | 1 | 3.36e+05 | 69 | 838 | 1 | 4720 | 87391 | 3864 | 0 | 96664 | 98617 | 99489 | 100986 | 96883 | + + +
+ + +## Advanced +### Latency explanation +A typical Triton Inference Server pipeline can be broken down into the following steps: + +1. The client serializes the inference request into a message and sends it to +the server (Client Send). +2. The message travels over the network from the client to the server (Network). +3. The message arrives at the server and is deserialized (Server Receive). +4. The request is placed on the queue (Server Queue). +5. The request is removed from the queue and computed (Server Compute). +6. The completed request is serialized in a message and sent back to +the client (Server Send). +7. The completed message then travels over the network from the server +to the client (Network). +8. The completed message is deserialized by the client and processed as +a completed inference request (Client Receive). + +Generally, for local clients, steps 1-4 and 6-8 will only occupy +a small fraction of time compared to step 5. In distributed systems and online processing +where the client and the server side are connected through a network, the send and receive steps might have an impact +on overall processing performance. In order to analyze the possible bottlenecks, detailed +charts are presented in online scenario cases. + + + +## Release Notes +We’re constantly refining and improving our performance on AI +and HPC workloads, even on the same hardware, with frequent updates +to our software stack. For our latest performance data, refer +to these pages for +[AI](https://developer.nvidia.com/deep-learning-performance-training-inference) +and [HPC](https://developer.nvidia.com/hpc-application-performance) benchmarks. + +### Changelog + +April 2023 +- Initial release + +### Known issues + +- There are no known issues with this model. diff --git a/TensorFlow2/Recommendation/DLRM/main.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/main.py similarity index 54% rename from TensorFlow2/Recommendation/DLRM/main.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/main.py index ef486d6a6..5af159831 100644 --- a/TensorFlow2/Recommendation/DLRM/main.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/main.py @@ -18,111 +18,111 @@ from absl import app, flags import os import sys +import json from distributed_embeddings.python.layers import dist_model_parallel as dmp + # Define the flags first before importing TensorFlow. # Otherwise, enabling XLA-Lite would be impossible with a command-line flag -def define_command_line_flags(): - flags.DEFINE_enum("mode", default="train", enum_values=['inference', 'eval', 'train', 'deploy'], +def define_common_flags(): + flags.DEFINE_enum("mode", default="train", enum_values=['inference', 'eval', 'train'], help='Choose "train" to train the model, "inference" to benchmark inference' ' and "eval" to run validation') - flags.DEFINE_float("learning_rate", default=24, help="Learning rate") - flags.DEFINE_integer("batch_size", default=64 * 1024, help="Batch size used for training") + # Debug parameters flags.DEFINE_bool("run_eagerly", default=False, help="Disable all tf.function decorators for debugging") + + flags.DEFINE_bool("tfdata_debug", default=False, help="Run tf.data operations eagerly (experimental)") - flags.DEFINE_bool("dummy_model", default=False, help="Use a dummy model for benchmarking and debugging") + flags.DEFINE_integer("seed", default=None, help="Random seed") - flags.DEFINE_list("top_mlp_dims", [1024, 1024, 512, 256, 1], "Linear layer sizes for the top MLP") - flags.DEFINE_list("bottom_mlp_dims", [512, 256, 128], "Linear layer sizes for the bottom MLP") + flags.DEFINE_bool("embedding_zeros_initializer", default=False, + help="Initialize the embeddings to zeros. This takes much less time so it's useful" + " for benchmarking and debugging.") - flags.DEFINE_enum("optimizer", default="sgd", enum_values=['sgd', 'adam'], - help='The optimization algorithm to be used.') + flags.DEFINE_bool("embedding_trainable", default=True, help="If True the embeddings will be trainable, otherwise frozen") - flags.DEFINE_string("save_checkpoint_path", default=None, - help="Path to which to save a checkpoint file at the end of the training") - flags.DEFINE_string("restore_checkpoint_path", default=None, - help="Path from which to restore a checkpoint before training") + # Hardware and performance features + flags.DEFINE_bool("amp", default=False, help="Enable automatic mixed precision") + flags.DEFINE_bool("use_mde_embeddings", default=True, + help="Use the embedding implementation from the TensorFlow Distributed Embeddings package") + flags.DEFINE_bool("concat_embedding", default=False, + help="Concatenate embeddings with the same dimension. Only supported for singleGPU.") + flags.DEFINE_string("dist_strategy", default='memory_balanced', + help="Strategy for the Distributed Embeddings to use. Supported options are" + "'memory_balanced', 'basic' and 'memory_optimized'") + flags.DEFINE_integer("column_slice_threshold", default=5*1000*1000*1000, + help='Number of elements above which a distributed embedding will be sliced across' + 'multiple devices') + flags.DEFINE_integer("row_slice_threshold", default=10*1000*1000*1000, + help='Number of elements above which a distributed embedding will be sliced across' + 'multiple devices') + flags.DEFINE_integer("data_parallel_threshold", default=None, + help='Number of elements above which a distributed embedding will be sliced across' + 'multiple devices') - flags.DEFINE_string("saved_model_output_path", default=None, - help='Path for storing the model in TensorFlow SavedModel format') - flags.DEFINE_bool("save_input_signature", default=False, - help="Save input signature in the SavedModel") - flags.DEFINE_string("saved_model_input_path", default=None, - help='Path for loading the model in TensorFlow SavedModel format') + flags.DEFINE_integer("cpu_offloading_threshold_gb", default=75, + help='Size of the embedding tables in GB above which ' + 'offloading to CPU memory should be employed.' + 'Applies only to singleGPU at the moment.') flags.DEFINE_bool('cpu', default=False, help='Place the entire model on CPU') - flags.DEFINE_bool("amp", default=False, help="Enable automatic mixed precision") - flags.DEFINE_bool("fp16", default=False, - help="Create the model in pure FP16 precision, suitable only for inference and deployment") flags.DEFINE_bool("xla", default=False, help="Enable XLA") - flags.DEFINE_integer("loss_scale", default=1024, help="Static loss scale to use with mixed precision training") + flags.DEFINE_integer("loss_scale", default=65536, help="Static loss scale to use with mixed precision training") + + flags.DEFINE_integer("inter_op_parallelism", default=None, help='Number of inter op threads') + flags.DEFINE_integer("intra_op_parallelism", default=None, help='Number of intra op threads') + + # Checkpointing + flags.DEFINE_string("save_checkpoint_path", default=None, + help="Path to which to save a checkpoint file at the end of the training") + flags.DEFINE_string("restore_checkpoint_path", default=None, + help="Path from which to restore a checkpoint before training") + # Evaluation, logging, profiling flags.DEFINE_integer("auc_thresholds", default=8000, help="Number of thresholds for the AUC computation") flags.DEFINE_integer("epochs", default=1, help="Number of epochs to train for") flags.DEFINE_integer("max_steps", default=-1, help="Stop the training/inference after this many optimiation steps") - flags.DEFINE_bool("embedding_trainable", default=True, help="If True the embeddings will be trainable, otherwise frozen") - - flags.DEFINE_enum("dot_interaction", default="custom_cuda", enum_values=["custom_cuda", "tensorflow", "dummy"], - help="Dot interaction implementation to use") - - flags.DEFINE_integer("embedding_dim", default=128, help='Number of columns in the embedding tables') - flags.DEFINE_integer("evals_per_epoch", default=1, help='Number of evaluations per epoch') flags.DEFINE_float("print_freq", default=100, help='Number of steps between debug prints') - flags.DEFINE_integer("warmup_steps", default=8000, - help='Number of steps over which to linearly increase the LR at the beginning') - flags.DEFINE_integer("decay_start_step", default=48000, help='Optimization step at which to start the poly LR decay') - flags.DEFINE_integer("decay_steps", default=24000, help='Number of steps over which to decay from base LR to 0') - flags.DEFINE_integer("profiler_start_step", default=None, help='Step at which to start profiling') flags.DEFINE_integer("profiled_rank", default=1, help='Rank to profile') - flags.DEFINE_integer("inter_op_parallelism", default=None, help='Number of inter op threads') - flags.DEFINE_integer("intra_op_parallelism", default=None, help='Number of intra op threads') - - flags.DEFINE_string("dist_strategy", default='memory_balanced', - help="Strategy for the Distributed Embeddings to use. Supported options are" - "'memory_balanced', 'basic' and 'memory_optimized'") - - flags.DEFINE_bool("use_merlin_de_embeddings", default=False, - help="Use the embedding implementation from the TensorFlow Distributed Embeddings package") - - - flags.DEFINE_integer("column_slice_threshold", default=10*1000*1000*1000, - help='Number of elements above which a distributed embedding will be sliced across' - 'multiple devices') - flags.DEFINE_string("log_path", default='dlrm_tf_log.json', help="Path to JSON file for storing benchmark results") - #dataset and dataloading settings + # dataset and dataloading settings flags.DEFINE_string("dataset_path", default=None, help="Path to dataset directory") flags.DEFINE_string("feature_spec", default="feature_spec.yaml", help="Name of the feature spec file in the dataset directory") - flags.DEFINE_enum("dataset_type", default="tf_raw", enum_values=['tf_raw', 'synthetic'], + flags.DEFINE_enum("dataset_type", default="tf_raw", + enum_values=['tf_raw', 'synthetic', 'split_tfrecords'], help='The type of the dataset to use') + flags.DEFINE_boolean("data_parallel_input", default=False, help="Use a data-parallel dataloader," + " i.e., load a local batch of of data for all input features") # Synthetic dataset settings flags.DEFINE_boolean("synthetic_dataset_use_feature_spec", default=False, help="Create a temporary synthetic dataset based on a real one. " "Uses --dataset_path and --feature_spec" - "Overrides synthetic dataset dimension flags, other than the number of batches") + "Overrides synthetic dataset dimension flags, except the number of batches") flags.DEFINE_integer('synthetic_dataset_train_batches', default=64008, help='Number of training batches in the synthetic dataset') flags.DEFINE_integer('synthetic_dataset_valid_batches', default=1350, help='Number of validation batches in the synthetic dataset') flags.DEFINE_list('synthetic_dataset_cardinalities', default=26*[1000], help='Number of categories for each embedding table of the synthetic dataset') + flags.DEFINE_list('synthetic_dataset_hotness', default=26*[20], + help='Number of categories for each embedding table of the synthetic dataset') flags.DEFINE_integer('synthetic_dataset_num_numerical_features', default=13, help='Number of numerical features of the synthetic dataset') -define_command_line_flags() +define_common_flags() FLAGS = flags.FLAGS app.define_help_flags() @@ -136,17 +136,22 @@ def define_command_line_flags(): import time -from lr_scheduler import LearningRateScheduler import tensorflow as tf import tensorflow_addons as tfa import numpy as np -from utils import IterTimer, init_logging, dist_print -from dataloader import create_input_pipelines, get_dataset_metadata -from model import Dlrm, DummyDlrm, DlrmTrainer, evaluate import horovod.tensorflow as hvd from tensorflow.keras.mixed_precision import LossScaleOptimizer + import dllogger +from utils.logging import IterTimer, init_logging +from utils.distributed import dist_print +from dataloading.dataloader import create_input_pipelines, get_dataset_metadata +from nn.lr_scheduler import LearningRateScheduler +from nn.model import Model +from nn.evaluator import Evaluator +from nn.trainer import Trainer + def init_tf(FLAGS): """ @@ -166,18 +171,46 @@ def init_tf(FLAGS): policy = tf.keras.mixed_precision.Policy("mixed_float16") tf.keras.mixed_precision.set_global_policy(policy) - if FLAGS.fp16: - policy = tf.keras.mixed_precision.Policy("float16") - tf.keras.mixed_precision.experimental.set_global_policy(policy) - tf.config.run_functions_eagerly(FLAGS.run_eagerly) + if FLAGS.tfdata_debug: + tf.data.experimental.enable_debug_mode() + if FLAGS.inter_op_parallelism: tf.config.threading.set_inter_op_parallelism_threads(FLAGS.inter_op_parallelism) if FLAGS.intra_op_parallelism: tf.config.threading.set_intra_op_parallelism_threads(FLAGS.intra_op_parallelism) + tf.random.set_seed(hash((FLAGS.seed, hvd.rank()))) + + +def parse_embedding_dimension(embedding_dim, num_embeddings): + try: + embedding_dim = int(embedding_dim) + embedding_dim = [embedding_dim] * num_embeddings + return embedding_dim + except: + pass + + if not isinstance(embedding_dim, str): + return ValueError(f'Unsupported embedding_dimension type: f{type(embedding_dim)}') + + if os.path.exists(embedding_dim): + # json file with a list of dimensions for each feature + with open(embedding_dim) as f: + edim = json.load(f) + else: + edim = embedding_dim.split(',') + + edim = [int(d) for d in edim] + + if len(edim) != num_embeddings: + raise ValueError(f'Length of specified embedding dimensions ({len(edim)}) does not match' + f' the number of embedding layers in the neural network ({num_embeddings})') + + return edim + def compute_eval_points(train_batches, evals_per_epoch): eval_points = np.linspace(0, train_batches - 1, evals_per_epoch + 1)[1:] @@ -189,19 +222,15 @@ def inference_benchmark(validation_pipeline, dlrm, timer, FLAGS): if FLAGS.max_steps == -1: FLAGS.max_steps = 1000 - if FLAGS.saved_model_input_path: - cast_dtype = tf.float16 if FLAGS.amp else tf.float32 - else: - cast_dtype = None + evaluator = Evaluator(model=dlrm, timer=timer, auc_thresholds=FLAGS.auc_thresholds, + max_steps=FLAGS.max_steps, cast_dtype=None) - auc, test_loss, latencies = evaluate(validation_pipeline, dlrm, - timer, auc_thresholds=FLAGS.auc_thresholds, - max_steps=FLAGS.max_steps, cast_dtype=cast_dtype) + auc, test_loss, latencies = evaluator(validation_pipeline) # don't benchmark the first few warmup steps latencies = latencies[10:] result_data = { - 'mean_inference_throughput': FLAGS.batch_size / np.mean(latencies), + 'mean_inference_throughput': FLAGS.valid_batch_size / np.mean(latencies), 'mean_inference_latency': np.mean(latencies) } @@ -214,67 +243,83 @@ def inference_benchmark(validation_pipeline, dlrm, timer, FLAGS): def validate_cmd_line_flags(): - - if FLAGS.restore_checkpoint_path is not None and FLAGS.saved_model_input_path is not None: - raise ValueError('Incompatible cmd-line flags.' - 'You can only specify one of --restore_checkpoint_path' - 'and --saved_model_input_path at a time.') - - if FLAGS.saved_model_input_path is not None and FLAGS.mode == 'train': - raise ValueError('Training from a SavedModel is not supported.' - 'To train from a checkpoint please specify the ' - '--restore_checkpoint_path cmd-line flag.') - if FLAGS.cpu and hvd.size() > 1: raise ValueError('MultiGPU mode is not supported when training on CPU') - if FLAGS.cpu and FLAGS.dot_interaction == 'custom_cuda': + if FLAGS.cpu and FLAGS.interaction == 'custom_cuda': raise ValueError('"custom_cuda" dot interaction not supported for CPU. ' 'Please specify "--dot_interaction tensorflow" if you want to run on CPU') - if FLAGS.fp16 and FLAGS.amp: - raise ValueError('Only one of --amp and --fp16 can be specified at a time.') - + if FLAGS.concat_embedding and hvd.size() != 1: + raise ValueError('Concat embedding is currently unsupported in multiGPU mode.') -def main(argv): - hvd.init() - validate_cmd_line_flags() - init_logging(log_path=FLAGS.log_path, FLAGS=FLAGS) - init_tf(FLAGS) + if FLAGS.concat_embedding and FLAGS.dataset_type != 'tf_raw': + raise ValueError('Concat embedding is only supported for dataset_type="tf_raw",' + f'got dataset_type={FLAGS.dataset_type}') - dataset_metadata = get_dataset_metadata(FLAGS) - dlrm = Dlrm.load_model_if_path_exists(FLAGS.saved_model_input_path) - if dlrm is None: - if FLAGS.dummy_model: - dlrm = DummyDlrm(FLAGS=FLAGS, dataset_metadata=dataset_metadata) - else: - dlrm = Dlrm(FLAGS=FLAGS, dataset_metadata=dataset_metadata) - dlrm = dlrm.restore_checkpoint_if_path_exists(FLAGS.restore_checkpoint_path) + all_embedding_dims_equal = all(dim == FLAGS.embedding_dim[0] for dim in FLAGS.embedding_dim) + if FLAGS.concat_embedding and not all_embedding_dims_equal: + raise ValueError('Concat embedding is only supported when all embeddings have the same output dimension,' + f'got embedding_dim={FLAGS.embedding_dim}') - train_pipeline, validation_pipeline = create_input_pipelines(FLAGS, dlrm.local_table_ids) - if FLAGS.optimizer == 'sgd': - embedding_optimizer = tf.keras.optimizers.SGD(learning_rate=FLAGS.learning_rate, momentum=0) - if FLAGS.amp: +def create_optimizers(flags): + if flags.optimizer == 'sgd': + embedding_optimizer = tf.keras.optimizers.legacy.SGD(learning_rate=flags.learning_rate, momentum=0) + if flags.amp: embedding_optimizer = LossScaleOptimizer(embedding_optimizer, - initial_scale=FLAGS.loss_scale, + initial_scale=flags.loss_scale, dynamic=False) mlp_optimizer = embedding_optimizer - optimizers = [mlp_optimizer] - elif FLAGS.optimizer == 'adam': - embedding_optimizer = tfa.optimizers.LazyAdam(learning_rate=FLAGS.learning_rate) - mlp_optimizer = tf.keras.optimizers.Adam(learning_rate=FLAGS.learning_rate) - if FLAGS.amp: - embedding_optimizer = LossScaleOptimizer(embedding_optimizer, - initial_scale=FLAGS.loss_scale, - dynamic=False) - mlp_optimizer = LossScaleOptimizer(mlp_optimizer, - initial_scale=FLAGS.loss_scale, - dynamic=False) - optimizers = [mlp_optimizer, embedding_optimizer] + elif flags.optimizer == 'adam': + embedding_optimizer = tfa.optimizers.LazyAdam(learning_rate=flags.learning_rate, + beta_1=flags.beta1, beta_2=flags.beta2) + + mlp_optimizer = tf.keras.optimizers.legacy.Adam(learning_rate=flags.learning_rate, + beta_1=flags.beta1, beta_2=flags.beta2) + if flags.amp: + # only wrap the mlp optimizer and not the embedding optimizer because the embeddings are not run in FP16 + mlp_optimizer = LossScaleOptimizer(mlp_optimizer, initial_scale=flags.loss_scale, dynamic=False) - scheduler = LearningRateScheduler(optimizers, + return mlp_optimizer, embedding_optimizer + + +def main(): + hvd.init() + init_logging(log_path=FLAGS.log_path, params_dict=FLAGS.flag_values_dict(), enabled=hvd.rank()==0) + init_tf(FLAGS) + + dataset_metadata = get_dataset_metadata(FLAGS.dataset_path, FLAGS.feature_spec) + + FLAGS.embedding_dim = parse_embedding_dimension(FLAGS.embedding_dim, + num_embeddings=len(dataset_metadata.categorical_cardinalities)) + + validate_cmd_line_flags() + + if FLAGS.restore_checkpoint_path is not None: + model = Model.create_from_checkpoint(FLAGS.restore_checkpoint_path) + else: + model = Model(**FLAGS.flag_values_dict(), num_numerical_features=dataset_metadata.num_numerical_features, + categorical_cardinalities=dataset_metadata.categorical_cardinalities, + transpose=False) + + table_ids = model.sparse_model.get_local_table_ids(hvd.rank()) + print(f'local feature ids={table_ids}') + + train_pipeline, validation_pipeline = create_input_pipelines(dataset_type=FLAGS.dataset_type, + dataset_path=FLAGS.dataset_path, + train_batch_size=FLAGS.batch_size, + test_batch_size=FLAGS.valid_batch_size, + table_ids=table_ids, + feature_spec=FLAGS.feature_spec, + rank=hvd.rank(), world_size=hvd.size(), + concat_features=FLAGS.concat_embedding, + data_parallel_input=FLAGS.data_parallel_input) + + mlp_optimizer, embedding_optimizer = create_optimizers(FLAGS) + + scheduler = LearningRateScheduler([mlp_optimizer, embedding_optimizer], warmup_steps=FLAGS.warmup_steps, base_lr=FLAGS.learning_rate, decay_start_step=FLAGS.decay_start_step, @@ -283,19 +328,13 @@ def main(argv): timer = IterTimer(train_batch_size=FLAGS.batch_size, test_batch_size=FLAGS.batch_size, optimizer=embedding_optimizer, print_freq=FLAGS.print_freq, enabled=hvd.rank() == 0) - if FLAGS.mode == 'inference': - inference_benchmark(validation_pipeline, dlrm, timer, FLAGS) + inference_benchmark(validation_pipeline, model, timer, FLAGS) return - elif FLAGS.mode == 'deploy': - dlrm.save_model_if_path_exists(FLAGS.saved_model_output_path, - save_input_signature=FLAGS.save_input_signature) - print('deployed to: ', FLAGS.saved_model_output_path) - return - elif FLAGS.mode == 'eval': - test_auc, test_loss, _ = evaluate(validation_pipeline, dlrm, - timer, auc_thresholds=FLAGS.auc_thresholds) + evaluator = Evaluator(model=model, timer=timer, auc_thresholds=FLAGS.auc_thresholds, max_steps=FLAGS.max_steps) + test_auc, test_loss, _ = evaluator(validation_pipeline) + if hvd.rank() == 0: dllogger.log(data=dict(auc=test_auc, test_loss=test_loss), step=tuple()) return @@ -303,10 +342,10 @@ def main(argv): eval_points = compute_eval_points(train_batches=len(train_pipeline), evals_per_epoch=FLAGS.evals_per_epoch) - trainer = DlrmTrainer(dlrm, embedding_optimizer=embedding_optimizer, - mlp_optimizer=mlp_optimizer, amp=FLAGS.amp, - lr_scheduler=scheduler, - pipe=train_pipeline, cpu=FLAGS.cpu) + trainer = Trainer(model, embedding_optimizer=embedding_optimizer, mlp_optimizer=mlp_optimizer, amp=FLAGS.amp, + lr_scheduler=scheduler, tf_dataset_op=train_pipeline.op, cpu=FLAGS.cpu) + + evaluator = Evaluator(model=model, timer=timer, auc_thresholds=FLAGS.auc_thresholds, distributed=hvd.size() > 1) best_auc = 0 best_loss = 1e6 @@ -323,9 +362,9 @@ def main(argv): loss = trainer.train_step() if step == 0 and hvd.size() > 1: - dmp.broadcast_variables(trainer.dlrm.variables, root_rank=0) + dmp.broadcast_variables(model.variables, root_rank=0) - if step % 100 == 0: + if step % FLAGS.print_freq == 0: if tf.math.is_nan(loss): print('NaN loss encountered in training. Aborting.') break @@ -337,16 +376,16 @@ def main(argv): break if step in eval_points: - test_auc, test_loss, _ = evaluate(validation_pipeline, dlrm, timer, FLAGS.auc_thresholds) + test_auc, test_loss, _ = evaluator(validation_pipeline) dist_print(f'Evaluation completed, AUC: {test_auc:.6f}, test_loss: {test_loss:.6f}') timer.test_idx = 0 best_auc = max(best_auc, test_auc) best_loss = min(best_loss, test_loss) elapsed = time.time() - train_begin - dlrm.save_checkpoint_if_path_exists(FLAGS.save_checkpoint_path) - dlrm.save_model_if_path_exists(FLAGS.saved_model_output_path, - save_input_signature=FLAGS.save_input_signature) + + if FLAGS.save_checkpoint_path is not None: + model.save_checkpoint(FLAGS.save_checkpoint_path) if hvd.rank() == 0: dist_print(f'Training run completed, elapsed: {elapsed:.0f} [s]') @@ -354,11 +393,6 @@ def main(argv): 'throughput': FLAGS.batch_size / timer.mean_train_time(), 'mean_step_time_ms': timer.mean_train_time() * 1000, 'auc': best_auc, - 'validation_loss': best_loss, - 'train_loss': loss.numpy().item() + 'validation_loss': best_loss } dllogger.log(data=results, step=tuple()) - - -if __name__ == '__main__': - app.run(main) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/__init__.py new file mode 100644 index 000000000..4fda2b94d --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/dcn.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/dcn.py new file mode 100644 index 000000000..8c802214d --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/dcn.py @@ -0,0 +1,214 @@ +# Copyright 2021 The TensorFlow Recommenders Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +"""Implements `Cross` Layer, the cross layer in Deep & Cross Network (DCN).""" + +from typing import Union, Text, Optional + +import tensorflow as tf + + +@tf.keras.utils.register_keras_serializable() +class Cross(tf.keras.layers.Layer): + """Cross Layer in Deep & Cross Network to learn explicit feature interactions. + A layer that creates explicit and bounded-degree feature interactions + efficiently. The `call` method accepts `inputs` as a tuple of size 2 + tensors. The first input `x0` is the base layer that contains the original + features (usually the embedding layer); the second input `xi` is the output + of the previous `Cross` layer in the stack, i.e., the i-th `Cross` + layer. For the first `Cross` layer in the stack, x0 = xi. + The output is x_{i+1} = x0 .* (W * xi + bias + diag_scale * xi) + xi, + where .* designates elementwise multiplication, W could be a full-rank + matrix, or a low-rank matrix U*V to reduce the computational cost, and + diag_scale increases the diagonal of W to improve training stability ( + especially for the low-rank case). + References: + 1. [R. Wang et al.](https://arxiv.org/pdf/2008.13535.pdf) + See Eq. (1) for full-rank and Eq. (2) for low-rank version. + 2. [R. Wang et al.](https://arxiv.org/pdf/1708.05123.pdf) + Example: + ```python + # after embedding layer in a functional model: + input = tf.keras.Input(shape=(None,), name='index', dtype=tf.int64) + x0 = tf.keras.layers.Embedding(input_dim=32, output_dim=6) + x1 = Cross()(x0, x0) + x2 = Cross()(x0, x1) + logits = tf.keras.layers.Dense(units=10)(x2) + model = tf.keras.Model(input, logits) + ``` + Args: + projection_dim: project dimension to reduce the computational cost. + Default is `None` such that a full (`input_dim` by `input_dim`) matrix + W is used. If enabled, a low-rank matrix W = U*V will be used, where U + is of size `input_dim` by `projection_dim` and V is of size + `projection_dim` by `input_dim`. `projection_dim` need to be smaller + than `input_dim`/2 to improve the model efficiency. In practice, we've + observed that `projection_dim` = d/4 consistently preserved the + accuracy of a full-rank version. + diag_scale: a non-negative float used to increase the diagonal of the + kernel W by `diag_scale`, that is, W + diag_scale * I, where I is an + identity matrix. + use_bias: whether to add a bias term for this layer. If set to False, + no bias term will be used. + kernel_initializer: Initializer to use on the kernel matrix. + bias_initializer: Initializer to use on the bias vector. + kernel_regularizer: Regularizer to use on the kernel matrix. + bias_regularizer: Regularizer to use on bias vector. + Input shape: A tuple of 2 (batch_size, `input_dim`) dimensional inputs. + Output shape: A single (batch_size, `input_dim`) dimensional output. + """ + + def __init__( + self, + projection_dim: Optional[int] = None, + diag_scale: Optional[float] = 0.0, + use_bias: bool = True, + kernel_initializer: Union[ + Text, tf.keras.initializers.Initializer] = "truncated_normal", + bias_initializer: Union[Text, + tf.keras.initializers.Initializer] = "zeros", + kernel_regularizer: Union[Text, None, + tf.keras.regularizers.Regularizer] = None, + bias_regularizer: Union[Text, None, + tf.keras.regularizers.Regularizer] = None, + **kwargs): + + super(Cross, self).__init__(**kwargs) + + self._projection_dim = projection_dim + self._diag_scale = diag_scale + self._use_bias = use_bias + self._kernel_initializer = tf.keras.initializers.get(kernel_initializer) + self._bias_initializer = tf.keras.initializers.get(bias_initializer) + self._kernel_regularizer = tf.keras.regularizers.get(kernel_regularizer) + self._bias_regularizer = tf.keras.regularizers.get(bias_regularizer) + self._input_dim = None + + self._supports_masking = True + + if self._diag_scale < 0: + raise ValueError( + "`diag_scale` should be non-negative. Got `diag_scale` = {}".format( + self._diag_scale)) + + def build(self, input_shape): + last_dim = input_shape[-1] + + if self._projection_dim is None: + self._dense = tf.keras.layers.Dense( + last_dim, + kernel_initializer=self._kernel_initializer, + bias_initializer=self._bias_initializer, + kernel_regularizer=self._kernel_regularizer, + bias_regularizer=self._bias_regularizer, + use_bias=self._use_bias, + ) + else: + self._dense_u = tf.keras.layers.Dense( + self._projection_dim, + kernel_initializer=self._kernel_initializer, + kernel_regularizer=self._kernel_regularizer, + use_bias=False, + ) + self._dense_v = tf.keras.layers.Dense( + last_dim, + kernel_initializer=self._kernel_initializer, + bias_initializer=self._bias_initializer, + kernel_regularizer=self._kernel_regularizer, + bias_regularizer=self._bias_regularizer, + use_bias=self._use_bias, + ) + self.built = True + + def call(self, x0: tf.Tensor, x: Optional[tf.Tensor] = None) -> tf.Tensor: + """Computes the feature cross. + Args: + x0: The input tensor + x: Optional second input tensor. If provided, the layer will compute + crosses between x0 and x; if not provided, the layer will compute + crosses between x0 and itself. + Returns: + Tensor of crosses. + """ + + if not self.built: + self.build(x0.shape) + + if x is None: + x = x0 + + if x0.shape[-1] != x.shape[-1]: + raise ValueError( + "`x0` and `x` dimension mismatch! Got `x0` dimension {}, and x " + "dimension {}. This case is not supported yet.".format( + x0.shape[-1], x.shape[-1])) + + if self._projection_dim is None: + prod_output = self._dense(x) + else: + prod_output = self._dense_v(self._dense_u(x)) + + if self._diag_scale: + prod_output = prod_output + self._diag_scale * x + + return x0 * prod_output + x + + def get_config(self): + config = { + "projection_dim": + self._projection_dim, + "diag_scale": + self._diag_scale, + "use_bias": + self._use_bias, + "kernel_initializer": + tf.keras.initializers.serialize(self._kernel_initializer), + "bias_initializer": + tf.keras.initializers.serialize(self._bias_initializer), + "kernel_regularizer": + tf.keras.regularizers.serialize(self._kernel_regularizer), + "bias_regularizer": + tf.keras.regularizers.serialize(self._bias_regularizer), + } + base_config = super(Cross, self).get_config() + return dict(list(base_config.items()) + list(config.items())) + + +class CrossNetwork(tf.Module): + def __init__(self, num_layers, projection_dim=None): + self.cross_layers = [] + for _ in range(num_layers): + self.cross_layers.append(Cross(projection_dim=projection_dim)) + + def __call__(self, x0): + x = x0 + for cl in self.cross_layers: + x = cl(x0=x0, x=x) + return x diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/dense_model.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/dense_model.py new file mode 100644 index 000000000..9f4928342 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/dense_model.py @@ -0,0 +1,262 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import json + +import tensorflow.keras.initializers as initializers +import math +from tensorflow.python.keras.saving.saving_utils import model_input_signature +from .dcn import CrossNetwork +from . import interaction +import tensorflow as tf +import horovod.tensorflow as hvd + +try: + from tensorflow_dot_based_interact.python.ops import dot_based_interact_ops +except ImportError: + print('WARNING: Could not import the custom dot-interaction kernels') + + +dense_model_parameters = ['embedding_dim', 'interaction', 'bottom_mlp_dims', + 'top_mlp_dims', 'num_numerical_features', 'categorical_cardinalities', + 'transpose', 'num_cross_layers', 'cross_layer_projection_dim', + 'batch_size'] + +class DenseModel(tf.keras.Model): + def __init__(self, **kwargs): + super(DenseModel, self).__init__() + + for field in dense_model_parameters: + self.__dict__[field] = kwargs[field] + + self.num_all_categorical_features = len(self.categorical_cardinalities) + self.bottom_mlp_dims = [int(d) for d in self.bottom_mlp_dims] + self.top_mlp_dims = [int(d) for d in self.top_mlp_dims] + + if self.interaction != 'cross' and any(dim != self.embedding_dim[0] for dim in self.embedding_dim): + raise ValueError(f'For DLRM all embedding dimensions should be equal, ' + f'got interaction={interaction}, embedding_dim={self.embedding_dim}') + + if self.interaction != 'cross' and self.bottom_mlp_dims[-1] != self.embedding_dim[0]: + raise ValueError(f'Final dimension of the Bottom MLP should match embedding dimension. ' + f'Got: {self.bottom_mlp_dims[-1]} and {self.embedding_dim} respectively.') + + self._create_interaction_op() + self._create_bottom_mlp() + self._create_top_mlp() + + self.bottom_mlp_padding = self._compute_padding(num_features=self.num_numerical_features) + self.top_mlp_padding = self._compute_padding(num_features=self._get_top_mlp_input_features()) + + def _create_interaction_op(self): + if self.interaction == 'dot_custom_cuda': + self.interact_op = dot_based_interact_ops.dot_based_interact + elif self.interaction == 'dot_tensorflow': + # TODO: add support for datasets with no dense features + self.interact_op = interaction.DotInteractionGather(num_features=self.num_all_categorical_features + 1) + elif self.interaction == 'cross': + self.interact_op = CrossNetwork(num_layers=self.num_cross_layers, + projection_dim=self.cross_layer_projection_dim) + else: + raise ValueError(f'Unknown interaction {self.interaction}') + + @staticmethod + def _compute_padding(num_features, multiple=8): + pad_to = math.ceil(num_features / multiple) * multiple + return pad_to - num_features + + def _get_top_mlp_input_features(self): + if self.interaction == 'cross': + num_features = sum(self.embedding_dim) + if self.num_numerical_features != 0: + num_features += self.bottom_mlp_dims[-1] + return num_features + else: + num_features = self.num_all_categorical_features + if self.num_numerical_features != 0: + num_features += 1 + num_features = num_features * (num_features - 1) + num_features = num_features // 2 + num_features = num_features + self.bottom_mlp_dims[-1] + return num_features + + def _create_bottom_mlp(self): + self.bottom_mlp_layers = [] + for dim in self.bottom_mlp_dims: + kernel_initializer = initializers.GlorotNormal() + bias_initializer = initializers.RandomNormal(stddev=math.sqrt(1. / dim)) + + l = tf.keras.layers.Dense(dim, activation='relu', + kernel_initializer=kernel_initializer, + bias_initializer=bias_initializer) + self.bottom_mlp_layers.append(l) + + def _create_top_mlp(self): + self.top_mlp = [] + for i, dim in enumerate(self.top_mlp_dims): + if i == len(self.top_mlp_dims) - 1: + # final layer + activation = 'linear' + else: + activation = 'relu' + + kernel_initializer = initializers.GlorotNormal() + bias_initializer = initializers.RandomNormal(stddev=math.sqrt(1. / dim)) + + l = tf.keras.layers.Dense(dim, activation=activation, + kernel_initializer=kernel_initializer, + bias_initializer=bias_initializer) + self.top_mlp.append(l) + + def transpose_nonequal_embedding_dim(self, embedding_outputs, numerical_features): + # We get a table-major format here for inference, + # but the sizes of the tables are not the same. + # Therefore a simple transposition will not work, + # we need to perform multiple splits and concats instead. + + # TODO: test this. + embedding_outputs = tf.reshape(embedding_outputs, shape=[-1]) + batch_size = numerical_features.shape[0] + split_sizes = [batch_size * dim for dim in self.embedding_dim] + embedding_outputs = tf.split(embedding_outputs, num_or_size_splits=split_sizes) + embedding_outputs = [tf.split(eout, num_or_size_splits=dim) for eout, dim in zip(embedding_outputs, + self.emdedding_dim)] + transposed_outputs = [] * batch_size + for i, o in enumerate(transposed_outputs): + ith_sample = [out[i] for out in embedding_outputs] + ith_sample = tf.concat(ith_sample, axis=1) + transposed_outputs[i] = ith_sample + transposed_outputs = tf.concat(transposed_outputs, axis=0) + return tf.reshape(transposed_outputs, shape=[batch_size, sum(self.embedding_dim)]) + + def transpose_input(self, embedding_outputs, numerical_features): + if any(dim != self.embedding_dim[0] for dim in self.embedding_dim): + return self.transpose_nonequal_embedding_dim(embedding_outputs, numerical_features) + else: + embedding_outputs = tf.reshape(embedding_outputs, shape=[self.num_all_categorical_features, -1, self.embedding_dim[0]]) + return tf.transpose(embedding_outputs, perm=[1, 0, 2]) + + def reshape_input(self, embedding_outputs): + if self.interaction == 'cross': + return tf.reshape(embedding_outputs, shape=[-1, sum(self.embedding_dim)]) + else: + return tf.reshape(embedding_outputs, shape=[-1, self.num_all_categorical_features, self.embedding_dim[0]]) + + @tf.function + def call(self, numerical_features, embedding_outputs, sigmoid=False, training=False): + numerical_features = tf.reshape(numerical_features, shape=[-1, self.num_numerical_features]) + + bottom_mlp_out = self._call_bottom_mlp(numerical_features, training) + + if self.transpose: + embedding_outputs = self.transpose_input(embedding_outputs, numerical_features) + embedding_outputs = self.reshape_input(embedding_outputs) + + x = self._call_interaction(embedding_outputs, bottom_mlp_out) + x = self._call_top_mlp(x) + + if sigmoid: + x = tf.math.sigmoid(x) + + x = tf.cast(x, tf.float32) + return x + + def _pad_bottom_mlp_input(self, numerical_features, training): + if training: + # When training, padding with a statically fixed batch size so that XLA has better shape information. + # This yields a significant (~15%) speedup for singleGPU DLRM. + padding = tf.zeros(shape=[self.batch_size // hvd.size(), self.bottom_mlp_padding], + dtype=self.compute_dtype) + x = tf.concat([numerical_features, padding], axis=1) + else: + # For inference, use tf.pad. + # This way inference can be performed with any batch size on the deployed SavedModel. + x = tf.pad(numerical_features, [[0, 0], [0, self.bottom_mlp_padding]]) + return x + + def _call_bottom_mlp(self, numerical_features, training): + numerical_features = tf.cast(numerical_features, dtype=self.compute_dtype) + + x = self._pad_bottom_mlp_input(numerical_features, training) + + with tf.name_scope('bottom_mlp'): + for l in self.bottom_mlp_layers: + x = l(x) + x = tf.expand_dims(x, axis=1) + bottom_mlp_out = x + return bottom_mlp_out + + def _call_interaction(self, embedding_outputs, bottom_mlp_out): + if self.interaction == 'cross': + bottom_mlp_out = tf.reshape(bottom_mlp_out, [-1, self.bottom_mlp_dims[-1]]) + x = tf.concat([bottom_mlp_out, embedding_outputs], axis=1) + x = self.interact_op(x) + else: + bottom_part_output = tf.concat([bottom_mlp_out, embedding_outputs], axis=1) + x = tf.reshape(bottom_part_output, shape=[-1, self.num_all_categorical_features + 1, self.embedding_dim[0]]) + bottom_mlp_out = tf.reshape(bottom_mlp_out, shape=[-1, self.bottom_mlp_dims[-1]]) + x = self.interact_op(x, bottom_mlp_out) + return x + + def _call_top_mlp(self, x): + if self.interaction != 'dot_custom_cuda': + x = tf.reshape(x, [-1, self._get_top_mlp_input_features()]) + x = tf.pad(x, [[0, 0], [0, self.top_mlp_padding]]) + + with tf.name_scope('top_mlp'): + for i, l in enumerate(self.top_mlp): + x = l(x) + return x + + def save_model(self, path, save_input_signature=False): + if save_input_signature: + input_sig = model_input_signature(self, keep_original_batch_size=True) + call_graph = tf.function(self) + signatures = call_graph.get_concrete_function(input_sig[0]) + else: + signatures = None + + tf.keras.models.save_model(model=self, filepath=path, overwrite=True, signatures=signatures) + + def force_initialization(self, batch_size=64, training=False, flattened_input=True): + if flattened_input: + embeddings_output = tf.zeros([batch_size * sum(self.embedding_dim)]) + numerical_input = tf.zeros([batch_size * self.num_numerical_features]) + else: + embeddings_output = tf.zeros([batch_size, sum(self.embedding_dim)]) + numerical_input = tf.zeros([batch_size, self.num_numerical_features]) + + _ = self(numerical_input, embeddings_output, sigmoid=False, training=training) + + + @staticmethod + def load_model(path): + print('Loading a saved model from', path) + + loaded = tf.keras.models.load_model(path) + return loaded + + def save_config(self, path): + config = {k : self.__dict__[k] for k in dense_model_parameters} + with open(path, 'w') as f: + json.dump(obj=config, fp=f, indent=4) + + @staticmethod + def from_config(path): + with open(path) as f: + config = json.load(fp=f) + return DenseModel(**config) + diff --git a/TensorFlow2/Recommendation/DLRM/embedding.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/embedding.py similarity index 56% rename from TensorFlow2/Recommendation/DLRM/embedding.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/embedding.py index 8f6be02bc..93d497a36 100644 --- a/TensorFlow2/Recommendation/DLRM/embedding.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/embedding.py @@ -14,12 +14,13 @@ # # author: Tomasz Grel (tgrel@nvidia.com) +import math import tensorflow as tf import numpy as np -import math +from distributed_embeddings.python.layers import embedding -from utils import get_variable_path +from utils.checkpointing import get_variable_path # write embedding checkpoints of 1M rows at a time @@ -28,7 +29,10 @@ @tf.keras.utils.register_keras_serializable() class EmbeddingInitializer(tf.keras.initializers.Initializer): - def __call__(self, shape, dtype=tf.float32): + def __call__(self, shape, dtype=None): + if dtype is None: + dtype = tf.float32 + with tf.device('/CPU:0'): maxval = tf.sqrt(tf.constant(1.) / tf.cast(shape[0], tf.float32)) maxval = tf.cast(maxval, dtype=dtype) @@ -43,10 +47,11 @@ def get_config(self): class Embedding(tf.keras.layers.Layer): - def __init__(self, input_dim, output_dim, trainable=True, dtype=tf.float32, feature_name=None): + def __init__(self, input_dim, output_dim, trainable=True, dtype=tf.float32, feature_name=None, + embeddings_initializer=None): super(Embedding, self).__init__(dtype=dtype) - self.input_dim = input_dim - self.output_dim = output_dim + self.input_dim = int(input_dim) + self.output_dim = int(output_dim) self.embedding_table = None self.trainable = trainable @@ -54,11 +59,13 @@ def __init__(self, input_dim, output_dim, trainable=True, dtype=tf.float32, feat if not self.feature_name: self.feature_name = '' + self.initializer = embeddings_initializer if embeddings_initializer else EmbeddingInitializer() + def build(self, input_shape): self.embedding_table = self.add_weight("embedding_table", shape=[self.input_dim, self.output_dim], dtype=self.dtype, - initializer=EmbeddingInitializer(), + initializer=self.initializer, trainable=self.trainable) def call(self, indices): @@ -73,10 +80,20 @@ def save_checkpoint(self, checkpoint_path): def restore_checkpoint(self, checkpoint_path): filename = get_variable_path(checkpoint_path, self.feature_name) - numpy_arr = np.load(file=filename) - indices = tf.range(start=0, limit=numpy_arr.shape[0], dtype=tf.int32) - update = tf.IndexedSlices(values=numpy_arr, indices=indices, dense_shape=self.embedding_table.shape) - self.embedding_table.scatter_update(sparse_delta=update) + print('restoring embedding table from: ', filename) + numpy_arr = np.load(file=filename, mmap_mode='r') + + num_chunks = math.ceil(numpy_arr.shape[0] / _embedding_checkpoint_batch) + for i in range(num_chunks): + begin = i * _embedding_checkpoint_batch + end = (i+1) * _embedding_checkpoint_batch + end = min(end, numpy_arr.shape[0]) + + indices = tf.range(start=begin, limit=end, dtype=tf.int32) + update = tf.IndexedSlices(values=numpy_arr[begin:end, :], + indices=indices, + dense_shape=self.embedding_table.shape) + self.embedding_table.scatter_update(sparse_delta=update) class EmbeddingGroup(tf.keras.layers.Layer): @@ -86,7 +103,7 @@ def __init__(self, table_sizes, output_dim, dtype=tf.float32, feature_names=None self.output_dim = output_dim self.feature_names = feature_names if not self.feature_names: - self.feature_names = ['feature_{i}' for i in range(len(table_sizes))] + self.feature_names = [f'feature_{i}' for i in range(len(table_sizes))] self.embedding_layers = [] for fname, ts in zip(self.feature_names, self.table_sizes): @@ -111,7 +128,7 @@ def restore_checkpoint(self, checkpoint_path): e.restore_checkpoint(checkpoint_path) -class JointEmbeddingInitializer(tf.keras.initializers.Initializer): +class FusedEmbeddingInitializer(tf.keras.initializers.Initializer): def __init__(self, table_sizes, embedding_dim, wrapped): self.table_sizes = table_sizes self.wrapped = wrapped @@ -130,34 +147,39 @@ def get_config(self): return {} -class JointEmbedding(tf.keras.layers.Layer): - def __init__(self, table_sizes, output_dim, dtype, feature_names=None, trainable=True): - super(JointEmbedding, self).__init__(dtype=dtype) +class FusedEmbedding(tf.keras.layers.Layer): + def __init__(self, table_sizes, output_dim, dtype=tf.float32, feature_names=None, trainable=True, + use_mde_embeddings=True): + + super(FusedEmbedding, self).__init__(dtype=dtype) self.table_sizes = table_sizes self.output_dim = output_dim - self.embedding_table = None self.offsets = np.array([0] + table_sizes, dtype=np.int32).cumsum() self.offsets.reshape([1, -1]) self.offsets = tf.constant(self.offsets, dtype=tf.int32) + self.use_mde_embeddings = use_mde_embeddings self.feature_names = feature_names if not self.feature_names: - self.feature_names = ['feature_{i}' for i in range(len(table_sizes))] + self.feature_names = [f'feature_{i}' for i in range(len(table_sizes))] self.trainable = trainable - def build(self, input_shape): - initializer = JointEmbeddingInitializer(table_sizes=self.table_sizes, + initializer = FusedEmbeddingInitializer(table_sizes=self.table_sizes, embedding_dim=self.output_dim, wrapped=EmbeddingInitializer) - self.embedding_table = self.add_weight("embedding_table", - shape=[self.offsets[-1], self.output_dim], - dtype=self.dtype, - initializer=initializer, - trainable=self.trainable) + embedding_cls = embedding.Embedding if use_mde_embeddings else Embedding + self.wrapped = embedding_cls(input_dim=self.offsets[-1], output_dim=self.output_dim, + embeddings_initializer=initializer) + + def _get_embedding_table(self): + if self.use_mde_embeddings: + return self.wrapped.variables[0] + else: + return self.wrapped.variables[0] def call(self, indices): indices = indices + self.offsets[:-1] - return tf.nn.embedding_lookup(params=self.embedding_table, ids=indices) + return self.wrapped(indices) def save_checkpoint(self, checkpoint_path): for j in range(len(self.offsets) - 1): @@ -166,7 +188,7 @@ def save_checkpoint(self, checkpoint_path): filename = get_variable_path(checkpoint_path, name) indices = tf.range(start=self.offsets[j], limit=self.offsets[j] + nrows, dtype=tf.int32) - arr = tf.gather(params=self.embedding_table, indices=indices, axis=0) + arr = tf.gather(params=self._get_embedding_table(), indices=indices, axis=0) arr = arr.numpy() np.save(arr=arr, file=filename) @@ -175,11 +197,20 @@ def restore_checkpoint(self, checkpoint_path): name = self.feature_names[j] filename = get_variable_path(checkpoint_path, name) - numpy_arr = np.load(file=filename) + print('restoring embedding table from: ', filename) + numpy_arr = np.load(file=filename, mmap_mode='r') - indices = tf.range(start=self.offsets[j], limit=self.offsets[j] + numpy_arr.shape[0], dtype=tf.int32) - update = tf.IndexedSlices(values=numpy_arr, indices=indices, dense_shape=self.embedding_table.shape) - self.embedding_table.scatter_update(sparse_delta=update) + num_chunks = math.ceil(numpy_arr.shape[0] / _embedding_checkpoint_batch) + for i in range(num_chunks): + begin = i * _embedding_checkpoint_batch + end = (i+1) * _embedding_checkpoint_batch + end = min(end, numpy_arr.shape[0]) + + indices = tf.range(start=begin, limit=end, dtype=tf.int32) + self.offsets[j] + update = tf.IndexedSlices(values=numpy_arr[begin:end, :], + indices=indices, + dense_shape=self._get_embedding_table().shape) + self._get_embedding_table().scatter_update(sparse_delta=update) class DualEmbeddingGroup(tf.keras.layers.Layer): @@ -190,7 +221,7 @@ class DualEmbeddingGroup(tf.keras.layers.Layer): def __init__(self, cardinalities, output_dim, memory_threshold, cpu_embedding='multitable', gpu_embedding='fused', dtype=tf.float32, - feature_names=None, trainable=True): + feature_names=None, trainable=True, use_mde_embeddings=True): # TODO: throw an exception if the features are not sorted by cardinality in reversed order @@ -199,19 +230,18 @@ def __init__(self, cardinalities, output_dim, memory_threshold, if dtype not in [tf.float32, tf.float16]: raise ValueError(f'Only float32 and float16 embedding dtypes are currently supported. Got {dtype}.') - cpu_embedding_class = EmbeddingGroup if cpu_embedding == 'multitable' else JointEmbedding - gpu_embedding_class = EmbeddingGroup if gpu_embedding == 'multitable' else JointEmbedding + cpu_embedding_class = EmbeddingGroup if cpu_embedding == 'multitable' else FusedEmbedding + gpu_embedding_class = EmbeddingGroup if gpu_embedding == 'multitable' else FusedEmbedding - cardinalities = np.array(cardinalities) + print('Dual embedding cardinalities: ', cardinalities) + self.cardinalities = np.array(cardinalities) self.memory_threshold = memory_threshold self.bytes_per_element = 2 if self.dtype == tf.float16 else 4 - self.table_sizes = cardinalities * output_dim * self.bytes_per_element + self.table_sizes = self.cardinalities * output_dim * self.bytes_per_element self._find_first_gpu_index() - self.cpu_cardinalities = cardinalities[:self.first_gpu_index] - self.gpu_cardinalities = cardinalities[self.first_gpu_index:] if not feature_names: feature_names = [f'feature_{i}' for i in range(len(self.table_sizes))] @@ -220,57 +250,84 @@ def __init__(self, cardinalities, output_dim, memory_threshold, self.gpu_embedding = gpu_embedding_class(table_sizes=self.gpu_cardinalities.tolist(), output_dim=output_dim, dtype=self.dtype, - feature_names=feature_names[self.first_gpu_index:], - trainable=trainable) + feature_names=[feature_names[i] for i in self.gpu_inputs], + trainable=trainable, use_mde_embeddings=use_mde_embeddings) # Force using FP32 for CPU embeddings, FP16 performance is much worse - self.cpu_embeddings = cpu_embedding_class(table_sizes=self.cpu_cardinalities, - output_dim=output_dim, dtype=tf.float32, - feature_names=feature_names[:self.first_gpu_index], - trainable=trainable) + self.cpu_embedding = cpu_embedding_class(table_sizes=self.cpu_cardinalities, + output_dim=output_dim, dtype=tf.float32, + feature_names=[feature_names[i] for i in self.cpu_inputs], + trainable=trainable) def _find_first_gpu_index(self): # order from smallest to largest - reversed_sizes = np.flip(self.table_sizes) + idx_mapping = np.argsort(self.table_sizes) + reversed_sizes = self.table_sizes[idx_mapping] + cumulative_size = np.cumsum(reversed_sizes) - cumulative_indicators = (cumulative_size > self.memory_threshold * 2 ** 30).tolist() + cumulative_indicators = (cumulative_size > self.memory_threshold * (10 ** 9)).tolist() if True in cumulative_indicators: - reversed_index = cumulative_indicators.index(True) + index = cumulative_indicators.index(True) else: - reversed_index = len(cumulative_size) + index = len(cumulative_size) + + self.first_cpu_index = index + + self.gpu_inputs = sorted(idx_mapping[:self.first_cpu_index]) + self.cpu_inputs = sorted(idx_mapping[self.first_cpu_index:]) + + self.cpu_cardinalities = self.cardinalities[self.cpu_inputs] + self.gpu_cardinalities = self.cardinalities[self.gpu_inputs] + + self.cpu_sizes = self.table_sizes[self.cpu_inputs] + self.gpu_sizes = self.table_sizes[self.gpu_inputs] - # convert to index into the original unreversed order - index = len(reversed_sizes) - reversed_index - self.first_gpu_index = index + print(f'self.cpu_inputs: {self.cpu_inputs}') + print(f'self.gpu_inputs: {self.gpu_inputs}') + + print(f'Total size of GPU tables: {sum(self.gpu_sizes) / 10 ** 9:.3f}[GB]') + print(f'Total size of CPU tables: {sum(self.cpu_sizes) / 10 ** 9:.3f}[GB]') def call(self, indices): - indices = tf.stack(indices, axis=1) + cpu_indices, gpu_indices = [], [] - to_concat = [] - if self.first_gpu_index > 0: - # at least one cpu-based embedding - cpu_indices = indices[:, :self.first_gpu_index] + if not self.cpu_inputs: + return self.gpu_embedding(indices) + + if not self.gpu_inputs: with tf.device('/CPU:0'): - cpu_results = self.cpu_embeddings(cpu_indices) - cpu_results = tf.cast(cpu_results, dtype=self.dtype) - to_concat.append(cpu_results) + return self.cpu_embedding(indices) + + for i in self.cpu_inputs: + cpu_indices.append(indices[:, i]) + for i in self.gpu_inputs: + gpu_indices.append(indices[:, i]) - if self.first_gpu_index < len(self.table_sizes): - # at least one gpu-based embedding - gpu_indices = indices[:, self.first_gpu_index:] + to_concat = [] + # at least one cpu-based embedding + with tf.device('/CPU:0'): + cpu_indices = tf.stack(cpu_indices, axis=1) + cpu_results = self.cpu_embedding(cpu_indices) + cpu_results = tf.cast(cpu_results, dtype=self.dtype) + to_concat.append(cpu_results) + # at least one gpu-based embedding + with tf.device('/GPU:0'): + gpu_indices = tf.stack(gpu_indices, axis=1) gpu_results = self.gpu_embedding(gpu_indices) to_concat.append(gpu_results) - if len(to_concat) > 1: - result = tf.concat(to_concat, axis=1) - else: - result = to_concat[0] + result = tf.concat(to_concat, axis=1) + + reorder_indices = np.concatenate([self.cpu_inputs, self.gpu_inputs], axis=0).argsort().tolist() + split_result = tf.split(result, num_or_size_splits=indices.shape[1], axis=1) + result = [split_result[i] for i in reorder_indices] + result = tf.concat(result, axis=1) return result def save_checkpoint(self, checkpoint_path): self.gpu_embedding.save_checkpoint(checkpoint_path) - self.cpu_embeddings.save_checkpoint(checkpoint_path) + self.cpu_embedding.save_checkpoint(checkpoint_path) def restore_checkpoint(self, checkpoint_path): self.gpu_embedding.restore_checkpoint(checkpoint_path) - self.cpu_embeddings.restore_checkpoint(checkpoint_path) + self.cpu_embedding.restore_checkpoint(checkpoint_path) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/evaluator.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/evaluator.py new file mode 100644 index 000000000..eeb9354ef --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/evaluator.py @@ -0,0 +1,94 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import tensorflow as tf +import time + +from .nn_utils import create_inputs_dict + +class Evaluator: + def __init__(self, model, timer, auc_thresholds, max_steps=None, cast_dtype=None, distributed=False): + self.model = model + self.timer = timer + self.max_steps = max_steps + self.cast_dtype = cast_dtype + self.distributed = distributed + + if self.distributed: + import horovod.tensorflow as hvd + self.hvd = hvd + else: + self.hvd = None + + self.auc_metric = tf.keras.metrics.AUC(num_thresholds=auc_thresholds, curve='ROC', + summation_method='interpolation', from_logits=True) + self.bce_op = tf.keras.losses.BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE, from_logits=True) + + def _reset(self): + self.latencies, self.all_test_losses = [], [] + self.auc_metric.reset_state() + + @tf.function + def update_auc_metric(self, labels, y_pred): + self.auc_metric.update_state(labels, y_pred) + + @tf.function + def compute_bce_loss(self, labels, y_pred): + return self.bce_op(labels, y_pred) + + def _step(self, pipe): + begin = time.time() + + batch = pipe.get_next() + (numerical_features, categorical_features), labels = batch + + if self.cast_dtype is not None: + numerical_features = tf.cast(numerical_features, self.cast_dtype) + + inputs = create_inputs_dict(numerical_features, categorical_features) + y_pred = self.model(inputs, sigmoid=False, training=False) + + end = time.time() + self.latencies.append(end - begin) + + if self.distributed: + y_pred = self.hvd.allgather(y_pred) + labels = self.hvd.allgather(labels) + + self.timer.step_test() + if not self.distributed or self.hvd.rank() == 0: + self.update_auc_metric(labels, y_pred) + test_loss = self.compute_bce_loss(labels, y_pred) + self.all_test_losses.append(test_loss) + + def __call__(self, validation_pipeline): + self._reset() + auc, test_loss = 0, 0 + pipe = iter(validation_pipeline.op()) + + num_steps = len(validation_pipeline) + if self.max_steps is not None and self.max_steps >= 0: + num_steps = min(num_steps, self.max_steps) + + for _ in range(num_steps): + self._step(pipe) + + if not self.distributed or self.hvd.rank() == 0: + auc = self.auc_metric.result().numpy().item() + test_loss = tf.reduce_mean(self.all_test_losses).numpy().item() + + return auc, test_loss, self.latencies diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/interaction.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/interaction.py new file mode 100644 index 000000000..a9812ab38 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/interaction.py @@ -0,0 +1,52 @@ +# Copyright 2020 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +import tensorflow as tf + + +class DotInteractionGather(tf.keras.layers.Layer): + def __init__(self, num_features): + super(DotInteractionGather, self).__init__() + self.num_features = num_features + self.indices = [] + for i in range(self.num_features): + for j in range(i): + self.indices.append(i * num_features + j) + + def call(self, features, bottom_mlp_out=None): + interactions = tf.matmul(features, features, transpose_b=True) + interactions = tf.reshape(interactions, shape=[-1, self.num_features * self.num_features]) + + x = tf.gather(params=interactions, indices=self.indices, axis=1) + + if bottom_mlp_out is not None: + x = tf.concat([bottom_mlp_out, x], axis=1) + return x \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM/lr_scheduler.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/lr_scheduler.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/lr_scheduler.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/lr_scheduler.py diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/model.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/model.py new file mode 100644 index 000000000..47daa97e0 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/model.py @@ -0,0 +1,102 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import tensorflow as tf +import horovod.tensorflow as hvd +import time +import os + +from utils.distributed import dist_print +from .dense_model import DenseModel, dense_model_parameters +from .sparse_model import SparseModel, sparse_model_parameters +from .nn_utils import create_inputs_dict + + +class Model(tf.keras.Model): + def __init__(self, **kwargs): + super(Model, self).__init__() + + if kwargs: + dense_model_kwargs = {k:kwargs[k] for k in dense_model_parameters} + self.dense_model = DenseModel(**dense_model_kwargs) + + sparse_model_kwargs = {k:kwargs[k] for k in sparse_model_parameters} + self.sparse_model = SparseModel(**sparse_model_kwargs) + + @staticmethod + def create_from_checkpoint(checkpoint_path): + if checkpoint_path is None: + return None + + model = Model() + model.dense_model = DenseModel.from_config(os.path.join(checkpoint_path, 'dense', 'config.json')) + model.sparse_model = SparseModel.from_config(os.path.join(checkpoint_path, 'sparse', 'config.json')) + model.restore_checkpoint(checkpoint_path) + return model + + def force_initialization(self, global_batch_size): + numerical_features = tf.zeros(shape=[global_batch_size // hvd.size(), + self.dense_model.num_numerical_features]) + + categorical_features = [tf.zeros(shape=[global_batch_size, 1], dtype=tf.int32) + for _ in range(len(self.sparse_model.get_local_table_ids(hvd.rank())))] + inputs = create_inputs_dict(numerical_features, categorical_features) + self(inputs=inputs) + + @tf.function + def call(self, inputs, sigmoid=False, training=False): + numerical_features, cat_features = list(inputs.values()) + embedding_outputs = self.sparse_model(cat_features) + embedding_outputs = tf.reshape(embedding_outputs, shape=[-1]) + x = self.dense_model(numerical_features, embedding_outputs, sigmoid=sigmoid, training=training) + return x + + def save_checkpoint(self, checkpoint_path): + dist_print('Saving a checkpoint...') + begin_save = time.time() + os.makedirs(checkpoint_path, exist_ok=True) + + if hvd.rank() == 0: + dense_checkpoint_dir = os.path.join(checkpoint_path, 'dense') + os.makedirs(dense_checkpoint_dir, exist_ok=True) + self.dense_model.save_config(os.path.join(dense_checkpoint_dir, 'config.json')) + self.dense_model.save_weights(os.path.join(dense_checkpoint_dir, 'dense')) + + sparse_checkpoint_dir = os.path.join(checkpoint_path, 'sparse') + os.makedirs(sparse_checkpoint_dir, exist_ok=True) + self.sparse_model.save_config(os.path.join(sparse_checkpoint_dir, 'config.json')) + self.sparse_model.save_checkpoint(sparse_checkpoint_dir) + + end_save = time.time() + dist_print('Saved a checkpoint to ', checkpoint_path) + dist_print(f'Saving a checkpoint took {end_save - begin_save:.3f}') + + def restore_checkpoint(self, checkpoint_path): + begin = time.time() + dist_print('Restoring a checkpoint...') + + local_batch = 64 + self.force_initialization(global_batch_size=hvd.size()*local_batch) + + dense_checkpoint_path = os.path.join(checkpoint_path, 'dense', 'dense') + self.dense_model.load_weights(dense_checkpoint_path) + + sparse_checkpoint_dir = os.path.join(checkpoint_path, 'sparse') + self.sparse_model.load_checkpoint(sparse_checkpoint_dir) + + end = time.time() + dist_print(f'Restoring a checkpoint took: {end-begin:.3f} seconds') + return self diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/nn_utils.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/nn_utils.py new file mode 100644 index 000000000..73a5ab8fa --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/nn_utils.py @@ -0,0 +1,31 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +from collections import OrderedDict + + +def create_inputs_dict(numerical_features, categorical_features): + # Passing inputs as (numerical_features, categorical_features) changes the model + # input signature to (). + # This leads to errors while loading the saved model. + # TF flattens the inputs while loading the model, + # so the inputs are converted from () -> [list of tensors] + # see _set_inputs function in training_v1.py: + # https://github.com/tensorflow/tensorflow/blob/7628750678786f1b65e8905fb9406d8fbffef0db/tensorflow/python/keras/engine/training_v1.py#L2588) + inputs = OrderedDict() + inputs['numerical_features'] = numerical_features + inputs['categorical_features'] = categorical_features + return inputs diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/sparse_model.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/sparse_model.py new file mode 100644 index 000000000..d8475ce6d --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/sparse_model.py @@ -0,0 +1,147 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + +import tensorflow as tf +import horovod.tensorflow as hvd +import numpy as np +import json + +from distributed_embeddings.python.layers import dist_model_parallel as dmp + +from utils.checkpointing import get_variable_path + +from .embedding import EmbeddingInitializer, DualEmbeddingGroup + + +sparse_model_parameters = ['use_mde_embeddings', 'embedding_dim', 'column_slice_threshold', + 'embedding_zeros_initializer', 'embedding_trainable', 'categorical_cardinalities', + 'concat_embedding', 'cpu_offloading_threshold_gb', + 'data_parallel_input', 'row_slice_threshold', 'data_parallel_threshold'] + +def _gigabytes_to_elements(gb, dtype=tf.float32): + if gb is None: + return None + + if dtype == tf.float32: + bytes_per_element = 4 + else: + raise ValueError(f'Unsupported dtype: {dtype}') + + return gb * 10**9 / bytes_per_element + +class SparseModel(tf.keras.Model): + def __init__(self, **kwargs): + super(SparseModel, self).__init__() + + sparse_model_kwargs = {k:kwargs[k] for k in sparse_model_parameters} + for field in sparse_model_kwargs.keys(): + self.__dict__[field] = kwargs[field] + + self.num_all_categorical_features = len(self.categorical_cardinalities) + self.use_concat_embedding = self.concat_embedding and (hvd.size() == 1) and \ + all(dim == self.embedding_dim[0] for dim in self.embedding_dim) + self._create_embeddings() + + def _create_embeddings(self): + self.embedding_layers = [] + + initializer_cls = tf.keras.initializers.Zeros if self.embedding_zeros_initializer else EmbeddingInitializer + + # use a concatenated embedding for singleGPU when all embedding dimensions are equal + if self.use_concat_embedding: + self.embedding = DualEmbeddingGroup(cardinalities=self.categorical_cardinalities, + output_dim=self.embedding_dim[0], + memory_threshold=self.cpu_offloading_threshold_gb, + trainable=self.trainable, + use_mde_embeddings=self.use_mde_embeddings) + return + + for table_size, dim in zip(self.categorical_cardinalities, self.embedding_dim): + if hvd.rank() == 0: + print(f'Creating embedding with size: {table_size} {dim}') + e = tf.keras.layers.Embedding(input_dim=table_size, output_dim=dim, + embeddings_initializer=initializer_cls()) + self.embedding_layers.append(e) + + gpu_size = _gigabytes_to_elements(self.cpu_offloading_threshold_gb) + self.embedding = dmp.DistributedEmbedding(self.embedding_layers, + strategy='memory_balanced', + dp_input=self.data_parallel_input, + column_slice_threshold=self.column_slice_threshold, + row_slice_threshold=self.row_slice_threshold, + data_parallel_threshold=self.data_parallel_threshold, + gpu_embedding_size=gpu_size) + + def get_local_table_ids(self, rank): + if self.use_concat_embedding or self.data_parallel_input: + return list(range(self.num_all_categorical_features)) + else: + return self.embedding.strategy.input_ids_list[rank] + + @tf.function + def call(self, cat_features): + embedding_outputs = self._call_embeddings(cat_features) + return embedding_outputs + + def _call_embeddings(self, cat_features): + if self.use_concat_embedding: + x = self.embedding(cat_features) + else: + x = self.embedding(cat_features) + x = tf.concat(x, axis=1) + + x = tf.cast(x, dtype=self.compute_dtype) + return x + + def force_initialization(self, global_batch_size=64): + categorical_features = [tf.zeros(shape=[global_batch_size, 1], dtype=tf.int32) + for _ in range(len(self.get_local_table_ids(hvd.rank())))] + _ = self(categorical_features) + + def save_checkpoint(self, checkpoint_path): + print('Gathering the embedding weights...') + full_embedding_weights = self.embedding.get_weights() + print('Saving the embedding weights...') + for i, weight in enumerate(full_embedding_weights): + filename = get_variable_path(checkpoint_path, f'feature_{i}') + np.save(file=filename, arr=weight) + print('Embedding checkpoint saved.') + + def load_checkpoint(self, checkpoint_path): + self.force_initialization() + paths = [] + for i in range(self.num_all_categorical_features): + path = get_variable_path(checkpoint_path, f'feature_{i}') + paths.append(path) + + self.embedding.set_weights(weights=paths) + + def save_config(self, path): + config = {k : self.__dict__[k] for k in sparse_model_parameters} + with open(path, 'w') as f: + json.dump(obj=config, fp=f, indent=4) + + @staticmethod + def from_config(path): + with open(path) as f: + config = json.load(fp=f) + if 'data_parallel_input' not in config: + config['data_parallel_input'] = False + if 'row_slice_threshold' not in config: + config['row_slice_threshold'] = None + if 'data_parallel_threshold' not in config: + config['data_parallel_threshold'] = None + return SparseModel(**config) diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/trainer.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/trainer.py new file mode 100644 index 000000000..f76bc9818 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/nn/trainer.py @@ -0,0 +1,85 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import tensorflow as tf +import horovod.tensorflow as hvd + +from distributed_embeddings.python.layers import dist_model_parallel as dmp + +from .nn_utils import create_inputs_dict + + +class Trainer: + def __init__(self, model, embedding_optimizer, mlp_optimizer, amp, lr_scheduler, tf_dataset_op, cpu): + self.model = model + self.embedding_optimizer = embedding_optimizer + self.mlp_optimizer = mlp_optimizer + self.amp = amp + self.lr_scheduler = lr_scheduler + self.bce = tf.keras.losses.BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE, from_logits=True) + self.cpu = cpu + self.tf_dataset_op = tf_dataset_op + self.dataset_iter = iter(self.tf_dataset_op()) + + def _weight_update(self, gradients): + if self.amp: + gradients = self.mlp_optimizer.get_unscaled_gradients(gradients) + + dense_gradients, dense_variables = [], [] + embedding_gradients, embedding_variables = [], [] + embedding_refs = set(v.ref() for v in self.model.sparse_model.trainable_variables) + + for var, grad in zip(self.model.trainable_variables, gradients): + if var.ref() in embedding_refs: + embedding_variables.append(var) + embedding_gradients.append(grad) + else: + dense_variables.append(var) + dense_gradients.append(grad) + + self.mlp_optimizer.apply_gradients(zip(dense_gradients, dense_variables)) + self.embedding_optimizer.apply_gradients(zip(embedding_gradients, embedding_variables)) + + @tf.function + def train_step(self): + device = '/CPU:0' if self.cpu else '/GPU:0' + with tf.device(device): + self.lr_scheduler() + with tf.name_scope("dataloading"): + (numerical_features, categorical_features), labels = self.dataset_iter.get_next() + + inputs = create_inputs_dict(numerical_features, categorical_features) + with tf.GradientTape() as tape: + predictions = self.model(inputs=inputs, training=True) + unscaled_loss = self.bce(labels, predictions) + # tf keras doesn't reduce the loss when using a Custom Training Loop + unscaled_loss = tf.math.reduce_mean(unscaled_loss) + scaled_loss = self.mlp_optimizer.get_scaled_loss(unscaled_loss) if self.amp else unscaled_loss + + if hvd.size() > 1: + tape = dmp.DistributedGradientTape(tape) + gradients = tape.gradient(scaled_loss, self.model.trainable_variables) + + self._weight_update(gradients) + + if hvd.size() > 1: + # compute mean loss for all workers for reporting + mean_loss = hvd.allreduce(unscaled_loss, name="mean_loss", op=hvd.Average) + else: + mean_loss = unscaled_loss + + return mean_loss diff --git a/TensorFlow2/Recommendation/DLRM/preproc/dgx2_config.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/dgx2_config.sh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/dgx2_config.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/dgx2_config.sh diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/gpu/get_gpu_resources.sh similarity index 69% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/__init__.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/gpu/get_gpu_resources.sh index 4d3bf2cf6..212f015b1 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/__init__.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/gpu/get_gpu_resources.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,5 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from .model_analyzer import ModelAnalyzer, ModelAnalyzerMode, ModelAnalyzerReportMode # noqa: F401 -from .model_analyzer_config import ModelAnalyzerConfig # noqa: F401 +# + + +#! /bin/bash + +ADDRS=`nvidia-smi --query-gpu=index --format=csv,noheader | sed -e ':a' -e 'N' -e'$!ba' -e 's/\n/","/g'` +echo {\"name\": \"gpu\", \"addresses\":[\"$ADDRS\"]} diff --git a/TensorFlow2/Recommendation/DLRM/preproc/gpu/spark-defaults.conf b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/gpu/spark-defaults.conf similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/gpu/spark-defaults.conf rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/gpu/spark-defaults.conf diff --git a/TensorFlow2/Recommendation/DLRM/preproc/parquet_to_binary.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/parquet_to_binary.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/parquet_to_binary.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/parquet_to_binary.py diff --git a/TensorFlow2/Recommendation/DLRM/preproc/prepare_dataset.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/prepare_dataset.sh similarity index 92% rename from TensorFlow2/Recommendation/DLRM/preproc/prepare_dataset.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/prepare_dataset.sh index cc85009f0..2be5344d0 100755 --- a/TensorFlow2/Recommendation/DLRM/preproc/prepare_dataset.sh +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/prepare_dataset.sh @@ -31,10 +31,10 @@ set -x ls -ltrash -download_dir=${download_dir:-'/data/dlrm/criteo'} +download_dir=${download_dir:-'/data/criteo_orig'} ./verify_criteo_downloaded.sh ${download_dir} -spark_output_path=${spark_output_path:-'/data/dlrm/spark/output'} +spark_output_path=${spark_output_path:-'/data/spark/output'} if [ -f ${spark_output_path}/train/_SUCCESS ] \ @@ -47,8 +47,8 @@ else ./run_spark.sh $1 ${download_dir} ${spark_output_path} $2 fi -conversion_intermediate_dir=${conversion_intermediate_dir:-'/data/dlrm/intermediate_binary'} -final_output_dir=${final_output_dir:-'/data/dlrm/binary_dataset'} +conversion_intermediate_dir=${conversion_intermediate_dir:-'/data/intermediate_binary'} +final_output_dir=${final_output_dir:-'/data/preprocessed'} if [ -d ${final_output_dir}/train ] \ diff --git a/TensorFlow2/Recommendation/DLRM/preproc/run_spark.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/run_spark.sh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/run_spark.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/run_spark.sh diff --git a/TensorFlow2/Recommendation/DLRM/preproc/run_spark_cpu.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/run_spark_cpu.sh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/run_spark_cpu.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/run_spark_cpu.sh diff --git a/TensorFlow2/Recommendation/DLRM/preproc/run_spark_gpu.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/run_spark_gpu.sh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/run_spark_gpu.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/run_spark_gpu.sh diff --git a/TensorFlow2/Recommendation/DLRM/preproc/spark_data_utils.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/spark_data_utils.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/spark_data_utils.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/spark_data_utils.py diff --git a/TensorFlow2/Recommendation/DLRM/preproc/split_dataset.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/split_dataset.py similarity index 98% rename from TensorFlow2/Recommendation/DLRM/preproc/split_dataset.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/split_dataset.py index 23667e450..3667867db 100644 --- a/TensorFlow2/Recommendation/DLRM/preproc/split_dataset.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/split_dataset.py @@ -69,7 +69,7 @@ def split_binary_file( numerical_f.write(numerical_features.astype(np.float16).tobytes()) label = batch_data[:, 0] - label_f.write(label.astype(np.bool).tobytes()) + label_f.write(label.astype(bool).tobytes()) cat_offset = num_numerical_features + 1 for cat_idx, cat_feature_type in enumerate(cat_feature_types): diff --git a/TensorFlow2/Recommendation/DLRM/preproc/verify_criteo_downloaded.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/verify_criteo_downloaded.sh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/preproc/verify_criteo_downloaded.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/preproc/verify_criteo_downloaded.sh diff --git a/TensorFlow2/Recommendation/DLRM/requirements.txt b/TensorFlow2/Recommendation/DLRM_and_DCNv2/requirements.txt similarity index 51% rename from TensorFlow2/Recommendation/DLRM/requirements.txt rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/requirements.txt index 7b6437869..0cae8cfe5 100644 --- a/TensorFlow2/Recommendation/DLRM/requirements.txt +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/requirements.txt @@ -1,8 +1,12 @@ git+https://github.com/NVIDIA/dllogger#egg=dllogger absl-py>=0.7.0 -numpy pyarrow pandas joblib tqdm pyyaml +onnxruntime +git+https://github.com/onnx/tensorflow-onnx +numpy<1.24 +tabulate>=0.8.7 +natsort>=7.0.0 \ No newline at end of file diff --git a/TensorFlow2/Recommendation/DLRM/slurm_multinode.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/slurm_multinode.sh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/slurm_multinode.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/slurm_multinode.sh diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/LICENSE b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/LICENSE similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/LICENSE rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/LICENSE diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/MANIFEST.in b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/MANIFEST.in similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/MANIFEST.in rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/MANIFEST.in diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/Makefile b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/Makefile similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/Makefile rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/Makefile diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/build_pip_pkg.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/build_pip_pkg.sh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/build_pip_pkg.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/build_pip_pkg.sh diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/setup.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/setup.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/setup.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/setup.py diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/__init__.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/__init__.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/__init__.py diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.cu similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.cu diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.h b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.h similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.h rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/ampere/dot_based_interact_ampere.h diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp16.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp16.cu similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp16.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp16.cu diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp32.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp32.cu similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp32.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_fp32.cu diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_shared_utils.cuh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_shared_utils.cuh similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_shared_utils.cuh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_shared_utils.cuh diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_tf32.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_tf32.cu similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_tf32.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/cuda_kernels/dot_based_interact_tf32.cu diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_grad_kernels.cc b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_grad_kernels.cc similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_grad_kernels.cc rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_grad_kernels.cc diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_kernels.cc b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_kernels.cc similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_kernels.cc rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/dot_based_interact_kernels.cc diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp16_launcher.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp16_launcher.cu similarity index 95% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp16_launcher.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp16_launcher.cu index eb9b59bbe..5d2e02c48 100644 --- a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp16_launcher.cu +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp16_launcher.cu @@ -1,3 +1,19 @@ +// Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + #ifndef FP16_LAUNCHER_CU #define FP16_LAUNCHER_CU @@ -237,4 +253,4 @@ inline void dotBasedInteractFP16Bwd(const void *input, } } -#endif /* FP16_LAUNCHER_CU */ \ No newline at end of file +#endif /* FP16_LAUNCHER_CU */ diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp32_launcher.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp32_launcher.cu similarity index 89% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp32_launcher.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp32_launcher.cu index 7e0288db7..12e4c4c36 100644 --- a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp32_launcher.cu +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_fp32_launcher.cu @@ -1,3 +1,19 @@ +// Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + #ifndef FP32_LAUNCHER_CU #define FP32_LAUNCHER_CU @@ -105,4 +121,4 @@ inline void dotBasedInteractFP32Bwd(const void *input, } } -#endif /* FP32_LAUNCHER_CU */ \ No newline at end of file +#endif /* FP32_LAUNCHER_CU */ diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_tf32_launcher.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_tf32_launcher.cu similarity index 93% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_tf32_launcher.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_tf32_launcher.cu index bf57a695d..7d72a4ae7 100644 --- a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_tf32_launcher.cu +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/launchers/dot_based_interact_tf32_launcher.cu @@ -1,3 +1,19 @@ +// Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + #ifndef TF32_LAUNCHER_CU #define TF32_LAUNCHER_CU @@ -193,4 +209,4 @@ inline void dotBasedInteractTF32Bwd(const void *input, stream); } } -#endif /* TF32_LAUNCHER_CU */ \ No newline at end of file +#endif /* TF32_LAUNCHER_CU */ diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.cu b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.cu similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.cu rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.cu diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.h b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.h similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.h rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/kernels/volta/dot_based_interact_volta.h diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/ops/dot_based_interact_ops.cc b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/ops/dot_based_interact_ops.cc similarity index 97% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/ops/dot_based_interact_ops.cc rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/ops/dot_based_interact_ops.cc index 232f97332..8c6aab850 100644 --- a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/ops/dot_based_interact_ops.cc +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/cc/ops/dot_based_interact_ops.cc @@ -32,7 +32,7 @@ REGISTER_OP("DotBasedInteract") int64 output_size = ((raw_output_size-1)/8 + 1)*8; //round up to multiple of 8 auto output_size_dim = c->MakeDim(output_size); c->set_output(0, c->MakeShape({batch_size_dim, output_size_dim})); - return Status::OK(); + return Status(); }); REGISTER_OP("DotBasedInteractGrad") @@ -47,5 +47,5 @@ REGISTER_OP("DotBasedInteractGrad") auto num_cols_dim = c->Dim(input, 2); c->set_output(0, input); //gradient w.r.t categoricals c->set_output(1, c->MakeShape({batch_size_dim, num_cols_dim})); //gradient w.r.t bottom mlp - return Status::OK(); + return Status(); }); diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/__init__.py new file mode 100644 index 000000000..d13f30782 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/__init__.py new file mode 100644 index 000000000..188294669 --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops.py diff --git a/TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops_test.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops_test.py similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops_test.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tensorflow-dot-based-interact/tensorflow_dot_based_interact/python/ops/dot_based_interact_ops_test.py diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/10_num.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/10_num.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/10_num.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/10_num.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/13_num_10_cat.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/13_num_10_cat.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/13_num_10_cat.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/13_num_10_cat.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/13_num_26_cat.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/13_num_26_cat.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/13_num_26_cat.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/13_num_26_cat.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/13_num_30_cat.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/13_num_30_cat.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/13_num_30_cat.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/13_num_30_cat.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/20_num.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/20_num.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/20_num.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/20_num.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/criteo_f15.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/criteo_f15.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/criteo_f15.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/criteo_f15.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/default.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/default.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/default.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/default.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/different_feature_names.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/different_feature_names.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/different_feature_names.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/different_feature_names.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/different_paths.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/different_paths.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/different_paths.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/different_paths.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/feature_specs/wider_dtypes.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/wider_dtypes.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/feature_specs/wider_dtypes.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/feature_specs/wider_dtypes.yaml diff --git a/TensorFlow2/Recommendation/DLRM/tests/test_all_configs.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_all_configs.sh similarity index 76% rename from TensorFlow2/Recommendation/DLRM/tests/test_all_configs.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_all_configs.sh index a5142db7f..b0480fbcb 100644 --- a/TensorFlow2/Recommendation/DLRM/tests/test_all_configs.sh +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_all_configs.sh @@ -1,3 +1,18 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + #!/bin/bash set -e set -x @@ -47,4 +62,4 @@ done # docker build . -t nvidia_dlrm_tf # docker run --security-opt seccomp=unconfined --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data nvidia_dlrm_tf bash # cd tests -# bash test_all_configs.sh \ No newline at end of file +# bash test_all_configs.sh diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_fspecs.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_fspecs.sh new file mode 100644 index 000000000..821d6262b --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_fspecs.sh @@ -0,0 +1,28 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +#!/bin/bash + +NAMES=${1:-'*.yaml'} +COMMON_OPTS="--xla --amp" + +bash test_with_opts.sh "${NAMES}" "${COMMON_OPTS}" + +# +# usage: +# docker build . -t nvidia_dlrm_tf +# docker run --security-opt seccomp=unconfined --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data nvidia_dlrm_tf bash +# cd tests +# bash test_fspecs.sh diff --git a/TensorFlow2/Recommendation/DLRM/tests/test_with_opts.sh b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_with_opts.sh similarity index 60% rename from TensorFlow2/Recommendation/DLRM/tests/test_with_opts.sh rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_with_opts.sh index 49b17b9ff..21faf86f7 100644 --- a/TensorFlow2/Recommendation/DLRM/tests/test_with_opts.sh +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/test_with_opts.sh @@ -1,3 +1,18 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + #!/bin/bash set -e set -x @@ -28,4 +43,4 @@ done # docker build . -t nvidia_dlrm_tf # docker run --security-opt seccomp=unconfined --runtime=nvidia -it --rm --ipc=host -v ${PWD}/data:/data nvidia_dlrm_tf bash # cd tests -# bash test_with_opts.sh \ No newline at end of file +# bash test_with_opts.sh diff --git a/TensorFlow2/Recommendation/DLRM/tests/transcoding/small_csv.yaml b/TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/transcoding/small_csv.yaml similarity index 100% rename from TensorFlow2/Recommendation/DLRM/tests/transcoding/small_csv.yaml rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/tests/transcoding/small_csv.yaml diff --git a/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/__init__.py new file mode 100644 index 000000000..4fda2b94d --- /dev/null +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# author: Tomasz Grel (tgrel@nvidia.com) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/maintainer_factory.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/checkpointing.py similarity index 62% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/maintainer_factory.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/checkpointing.py index 617968ac3..330376e84 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/maintainer_factory.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/checkpointing.py @@ -11,15 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import pathlib +# +# author: Tomasz Grel (tgrel@nvidia.com) -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name -from .docker.maintainer import DockerMaintainer +import os -class MaintainerFactory: - @staticmethod - def create_docker_maintainer(): - return DockerMaintainer() +def get_variable_path(checkpoint_path, name): + tokens = name.split('/') + tokens = [t for t in tokens if 'model_parallel' not in t and 'data_parallel' not in t] + name = '_'.join(tokens) + name = name.replace(':', '_') + filename = name + '.npy' + return os.path.join(checkpoint_path, filename) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/__init__.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/distributed.py similarity index 76% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/__init__.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/distributed.py index bd3cc4dd0..2b67eff66 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/__init__.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/distributed.py @@ -11,6 +11,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from .container import Container -from .docker.maintainer import DockerMaintainer -from .maintainer import Maintainer +# +# author: Tomasz Grel (tgrel@nvidia.com) + + +import horovod.tensorflow as hvd + + +def dist_print(*args, force=False, **kwargs): + if hvd.rank() == 0 or force: + print(*args, **kwargs) + diff --git a/TensorFlow2/Recommendation/DLRM/utils.py b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/logging.py similarity index 69% rename from TensorFlow2/Recommendation/DLRM/utils.py rename to TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/logging.py index 609632bf4..b922a2595 100644 --- a/TensorFlow2/Recommendation/DLRM/utils.py +++ b/TensorFlow2/Recommendation/DLRM_and_DCNv2/utils/logging.py @@ -17,56 +17,31 @@ import time import dllogger -import horovod.tensorflow as hvd import json -import os -def get_variable_path(checkpoint_path, name, i=0): - tokens = name.split('/') - tokens = [t for t in tokens if 'model_parallel' not in t and 'data_parallel' not in t] - name = '_'.join(tokens) - name = name.replace(':', '_') - filename = name + f'_part{i}' + '.npy' - return os.path.join(checkpoint_path, filename) - - -def print_model_summary(model): - variables_placement = { - v.name: (v.device, v.shape.as_list(), - str(v.is_initialized()), str(v.dtype), str(v.trainable), str(v.synchronization)) for v in model.trainable_variables - } - print('============ VARIABLES PLACEMENT =====================') - print(json.dumps(variables_placement, indent=4)) - print('============ VARIABLES PLACEMENT END =================') - - -def dist_print(*args, force=False, **kwargs): - if hvd.rank() == 0 or force: - print(*args, **kwargs) - - -def init_logging(log_path, FLAGS): - if hvd.rank() != 0: +def init_logging(log_path, params_dict, enabled=True): + if not enabled: return + json_backend = dllogger.JSONStreamBackend(verbosity=dllogger.Verbosity.VERBOSE, filename=log_path) stdout_backend = dllogger.StdOutBackend(verbosity=dllogger.Verbosity.VERBOSE) - dllogger.init(backends=[json_backend, stdout_backend]) - dllogger.metadata('auc', {'unit': None, 'format': '0:.5f'}) - dllogger.metadata('throughput', {'unit': 'samples/s', 'format': ':.2e'}) - dllogger.metadata('validation_loss', {'unit': None, 'format': '0:.5f'}) - dllogger.metadata('train_loss', {'unit': None, 'format': '0:.5f'}) - dllogger.metadata('mean_step_time_ms', {'unit': 'ms', 'format': '0:.3f'}) - dllogger.metadata('mean_inference_throughput', {'unit': 'samples/s', 'format': ':.2e'}) - dllogger.metadata('mean_inference_latency', {'unit': 's', 'format': '0:.5f'}) + stdout_backend._metadata['auc'].update({'format': '0:.6f'}) + stdout_backend._metadata['validation_loss'].update({'format': '0:.6f'}) + stdout_backend._metadata['throughput'].update({'format': ':.3e'}) + stdout_backend._metadata['mean_step_time_ms'].update({'format': '0:.3f'}) + stdout_backend._metadata['mean_inference_throughput'].update({'format': ':.3e'}) + stdout_backend._metadata['mean_inference_latency'].update({'format': '0:.5f'}) for percentile in [90, 95, 99]: - dllogger.metadata(f'p{percentile}_inference_latency', {'unit': 's', 'format': '0:.5f'}) + stdout_backend._metadata[f'p{percentile}_inference_latency'].update({'format': '0:.5f'}) + + dllogger.init(backends=[json_backend, stdout_backend]) - dllogger.log(data=FLAGS.flag_values_dict(), step='PARAMETER') + dllogger.log(data=params_dict, step='PARAMETER') print("Command line flags:") - print(json.dumps(FLAGS.flag_values_dict(), indent=4)) + print(json.dumps(params_dict, indent=4)) class IterTimer: diff --git a/TensorFlow2/Recommendation/SIM/main.py b/TensorFlow2/Recommendation/SIM/main.py index f29cfe463..77c68639a 100644 --- a/TensorFlow2/Recommendation/SIM/main.py +++ b/TensorFlow2/Recommendation/SIM/main.py @@ -253,7 +253,10 @@ def eval(model_fn, data_iterator, num_thresholds=8000, prefix=""): local = tf.constant(local) # concat all local variables into a single tensor - local = tf.concat(local, 0) + if local is local_total_losses: + local = tf.stack(local, 0) + else: + local = tf.concat(local, 0) # for single element lists, tf.concat will produce shape=() instead of shape=(1,). # reshape it for hvd.allgather to work diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/.gitignore b/TensorFlow2/Segmentation/Contrib/UNet3P/.gitignore new file mode 100644 index 000000000..60d8f9716 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/.gitignore @@ -0,0 +1,18 @@ +.idea +__pycache__ + +checkpoint/tb_logs/* +checkpoint/*.hdf5 +checkpoint/*.csv +!checkpoint/tb_logs/.gitkeep + +#data/* +/data/**/*.png +/data/**/*.jpg +/data/**/*.nii +!data/**/.gitkeep + +data_preparation/verify_preprocess_data.ipynb +old_data_preperation/ +others/ +**/outputs \ No newline at end of file diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/Dockerfile b/TensorFlow2/Segmentation/Contrib/UNet3P/Dockerfile new file mode 100644 index 000000000..498695855 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/Dockerfile @@ -0,0 +1,15 @@ +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/tensorflow:22.12-tf2-py3 +FROM ${FROM_IMAGE_NAME} + +ADD . /workspace/unet3p +WORKDIR /workspace/unet3p + +RUN pip install -r requirements.txt + +#For opencv, inside docker run these commands +RUN apt-get update +RUN apt-get install ffmpeg libsm6 libxext6 -y + +# reinstall jupyterlab +RUN pip uninstall jupyterlab -y +RUN pip install jupyterlab diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/LICENSE b/TensorFlow2/Segmentation/Contrib/UNet3P/LICENSE new file mode 100644 index 000000000..a1deb94c2 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 Hamid Ali + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/README.md b/TensorFlow2/Segmentation/Contrib/UNet3P/README.md new file mode 100644 index 000000000..183f816bb --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/README.md @@ -0,0 +1,319 @@ +# UNet 3+: A Full-Scale Connected UNet for Medical Image Segmentation + +[![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/unet-3-a-full-scale-connected-unet-for/medical-image-segmentation-on-lits2017)](https://paperswithcode.com/sota/medical-image-segmentation-on-lits2017?p=unet-3-a-full-scale-connected-unet-for) + +This repository provides a script and recipe to train UNet3+ to achieve state of the art accuracy. + +**The code and associated performance metrics were contributed by the community and are not maintained by NVIDIA.** + +## Table of Contents + +- [UNet 3+](https://arxiv.org/abs/2004.08790) for Image Segmentation in Tensorflow 2.0. + - [Table of Contents](#table-of-contents) + - [Feature Support Matrix](#feature-support-matrix) + - [Installation](#installation) + - [Code Structure](#code-structure) + - [Config](#config) + - [Data Preparation](#data-preparation) + - [Models](#models) + - [Performance](#performance) + - [Inference Demo](#inference-demo) + - [Known issues](#known-issues) + - [Release notes](#release-notes) + +## Feature Support Matrix + +The following features are supported by our code base: + +| Feature | UNet3+ Supports | +|:------------------------------------------:|:---------------:| +| DALI | ✓ | +| TensorFlow Multi-GPU Training | ✓ | +| TensorFlow Automatic Mixed Precision(AMP) | ✓ | +| TensorFlow Accelerated Linear Algebra(XLA) | ✓ | + +#### [NVIDIA DALI](https://docs.nvidia.com/deeplearning/dali/user-guide/docs/index.html) + +The NVIDIA Data Loading Library (DALI) is a library for data loading and +pre-processing to accelerate deep learning applications. It provides a +collection of highly optimized building blocks for loading and processing +image, video and audio data. It can be used as a portable drop-in +replacement for built in data loaders and data iterators in popular deep +learning frameworks. + +#### [TensorFlow Multi-GPU Training](https://www.tensorflow.org/guide/distributed_training) + +Distribute training across multiple GPUs, multiple machines, or TPUs. + +#### [TensorFlow Automatic Mixed Precision(AMP)](https://www.tensorflow.org/guide/mixed_precision) + +Mixed precision is the use of both 16-bit and 32-bit floating-point types in a model during training to make it run +faster and use less memory. By keeping certain parts of the model in the 32-bit types for numeric stability, the model +will have a lower step time and train equally as well in terms of the evaluation metrics such as accuracy. + +#### [TensorFlow Accelerated Linear Algebra(XLA)](https://www.tensorflow.org/xla) + +In a TensorFlow program, all of the operations are executed individually by the TensorFlow executor. Each TensorFlow +operation has a precompiled GPU kernel implementation that the executor dispatches to. +XLA provides an alternative mode of running models: it compiles the TensorFlow graph into a sequence of computation +kernels generated specifically for the given model. Because these kernels are unique to the model, they can exploit +model-specific information for optimization. + +For details on how to enable these features while training and evaluation see [Benchmarking](#benchmarking) section. + +## Installation + +* Clone code + +``` +git clone https://github.com/hamidriasat/NVIDIA-DeepLearningExamples.git +cd NVIDIA-DeepLearningExamples/TensorFlow2/Segmentation/UNet3P/ +``` + +* Build the UNet3P TensorFlow NGC container + From `Dockerfile` this will create a docker image with name `unet3p`. This image will contain all the components + required to successfully run the UNet3+ code. + +``` +docker build -t unet3p . +``` + +The NGC container contains all the components optimized for usage on NVIDIA hardware. + +* Start an interactive session in the NGC container + +To run preprocessing/training/inference, following command will launch the container and mount the current directory +to `/workspace/unet3p` as a volume in the container + +``` +docker run --rm -it --shm-size=1g --ulimit memlock=-1 --pids-limit=8192 --gpus all -p 5012:8888 -v $PWD/:/workspace/unet3p --name unet3p unet3p:latest /bin/bash +``` + +Here we are mapping external port `5012` to `8888` inside docker. This will be used for visualization purpose. + +## Code Structure + +- **callbacks**: Custom callbacks to monitor training time, latency and throughput +- **checkpoint**: Model checkpoint and logs directory +- **configs**: Configuration file (see [Config](#config) for more details) +- **data**: Dataset files (see [Data Preparation](#data-preparation) for more details) +- **data_generators**: Data loaders for UNet3+ (see [Data Generators](#data-generators) for more details) +- **data_preparation**: For LiTS data preparation and data verification +- **figures**: Model architecture image +- **losses**: Implementations of UNet3+ hybrid loss function and dice coefficient +- **models**: Unet3+ model files (see [Models](#models) for more details) +- **utils**: Generic utility functions +- **benchmark_inference.py**: Benchmark script to output model throughput and latency while inference +- **evaluate.py**: Evaluation script to validate accuracy on trained model +- **predict.ipynb**: Prediction file used to visualize model output inside notebook(helpful for remote server + visualization) +- **predict.py**: Prediction script used to visualize model output +- **train.py**: Training script + +## Data Preparation + +- This code can be used to reproduce UNet3+ paper results + on [LiTS - Liver Tumor Segmentation Challenge](https://competitions.codalab.org/competitions/15595). +- You can also use it to train UNet3+ on custom dataset. + +For dataset preparation read [here](data_preparation/README.md). + +## Config + +Configurations are passed through `yaml` file. For more details on config file read [here](configs/). + +## Data Generators + +We support two types of data loaders. `NVIDIA DALI` and `TensorFlow Sequence` +generators. For more details on supported generator types read [here](data_generators/). + +## Models + +UNet 3+ is latest from Unet family, proposed for semantic image segmentation. it takes advantage of full-scale skip +connections and deep supervisions.The full-scale skip connections incorporate low-level details with high-level +semantics from feature maps in different scales; while the deep supervision learns hierarchical representations from the +full-scale aggregated feature maps. + +![alt text](figures/unet3p_architecture.png) + +Figure 1. UNet3+ architecture diagram from [original paper](https://arxiv.org/abs/2004.08790). + +This repo contains all three versions of UNet3+. + +| # | Description | Model Name | Training Supported | +|:----|:-------------------------------------------------------------:|:-----------------------------------------------------------------:|:------------------:| +| 1 | UNet3+ Base model | [unet3plus](models/unet3plus.py) | ✓ | +| 2 | UNet3+ with Deep Supervision | [unet3plus_deepsup](models/unet3plus_deep_supervision.py) | ✓ | +| 3 | UNet3+ with Deep Supervision and Classification Guided Module | [unet3plus_deepsup_cgm](models/unet3plus_deep_supervision_cgm.py) | ✗ | + +Available backbones are `unet3plus`, `vgg16` and `vgg19`. All backbones are untrained networks. + +In our case all results are reported using `vgg19` backbone and `unet3plus` variant. + +[Here](losses/unet_loss.py) you can find UNet3+ hybrid loss. + +## Performance + +### Benchmarking + +The following section shows how to run benchmarks to measure the model performance in training and inference modes. + +#### Training performance benchmark + +Run the `python train.py` script with the required model configurations to print training benchmark results for each +model +configuration. At the end of the training, a line reporting the training throughput and latency will be printed. + +To calculate dice score on trained model call `python evaluate.py` with required parameters. + +##### Example 1 + +To train base model `unet3plus` with `vgg19` backbone on `single GPU` +using `TensorFlow Sequence Generator` without `Automatic Mixed Precision(AMP)` and `Accelerated Linear Algebra(XLA)` run + +``` +python train.py MODEL.TYPE=unet3plus MODEL.BACKBONE.TYPE=vgg19 \ +USE_MULTI_GPUS.VALUE=False \ +DATA_GENERATOR_TYPE=TF_GENERATOR \ +OPTIMIZATION.AMP=False OPTIMIZATION.XLA=False +``` + +##### Example 2 + +To train base model `unet3plus` with `vgg19` backbone on `multiple GPUs` +using `TensorFlow Sequence Generator` without `Automatic Mixed Precision(AMP)` and `Accelerated Linear Algebra(XLA)` run + +``` +python train.py MODEL.TYPE=unet3plus MODEL.BACKBONE.TYPE=vgg19 \ +USE_MULTI_GPUS.VALUE=True USE_MULTI_GPUS.GPU_IDS=-1 \ +DATA_GENERATOR_TYPE=TF_GENERATOR \ +OPTIMIZATION.AMP=False OPTIMIZATION.XLA=False +``` + +##### Example 3 + +To train base model `unet3plus` with `vgg19` backbone on `multiple GPUs` +using `NVIDIA DALI Generator` with `Automatic Mixed Precision(AMP)` and `Accelerated Linear Algebra(XLA)` run + +``` +python train.py MODEL.TYPE=unet3plus MODEL.BACKBONE.TYPE=vgg19 \ +USE_MULTI_GPUS.VALUE=True USE_MULTI_GPUS.GPU_IDS=-1 \ +DATA_GENERATOR_TYPE=DALI_GENERATOR \ +OPTIMIZATION.AMP=True OPTIMIZATION.XLA=True +``` + +To evaluate/calculate dice accuracy of model pass same parameters to `evaluate.py` file. + +Please check [Config](configs/config.yaml) file for more details about default training parameters. + +#### Inference performance benchmark + +To benchmark inference time, run the `python benchmark_inference.py` script with the required model configurations to +print +inference benchmark results for each model configuration. At the end, a line reporting the inference throughput and +latency will be printed. + +For inference run without `data generator` and `GPUs` details but with `batch size`, `warmup_steps` +and `bench_steps` +parameters. + +``` +python benchmark_inference.py MODEL.TYPE=unet3plus MODEL.BACKBONE.TYPE=vgg19 \ +HYPER_PARAMETERS.BATCH_SIZE=16 \ +OPTIMIZATION.AMP=False OPTIMIZATION.XLA=False \ ++warmup_steps=50 +bench_steps=100 +``` + +Each of these scripts will by default run a warm-up for 50 iterations and then start benchmarking for another 100 +steps. +You can adjust these settings with `+warmup_steps` and `+bench_steps` parameters. + +### Results + +The following section provide details of results that are achieved in different settings of model training and +inference. + +**These results were contributed by the community and are not maintained by NVIDIA.** + +#### Training accuracy results + +###### Training accuracy: NVIDIA DGX A100 (8xA100 80G) + +| #GPU | Generator | XLA | AMP | Training Time
HH:MM:SS ↓ | Latency Avg [ms] ↓ | Throughput Avg [img/s] ↑ | Speed Up | Dice Score | +|:----:|:---------:|:-------:|:-------:|:---------------------------------:|:-----------------------:|:-----------------------------:|:---------:|:----------:| +| 1 | TF | ✗ | ✗ | 51:38:24.24 | 616.14 | 25.97 | --- | 0.96032 | +| 8 | TF | ✗ | ✗ | 11:30:45 | 999.39 | 128.08 | 1x (base) | 0.95224 | +| 8 | DALI | ✗ | ✗ | 6:23:43 | 614.26 | 208.38 | 1.8x | 0.94566 | +| 8 | DALI | ✓ | ✗ | 7:33:15 | 692.71 | 184.78 | 1.5x | 0.94806 | +| 8 | DALI | ✗ | ✓ | 3:49:55 | 357.34 | 358.2 | 3x | 0.94786 | +| 8 | DALI | ✓ | ✓ | 3:14:24 | 302.83 | 422.68 | 3.5x | 0.9474 | + +Latency is reported in milliseconds per batch whereas throughput is reported in images per second. +Speed Up comparison is efficiency achieved in terms of training time between different runs. + +Note: Training time includes time to load cuDNN in first iteration and the first epoch which take little longer as +compared to later epochs because in first epoch tensorflow optimizes the training graph. In terms of latency and +throughput it does not matter much because we have trained networks for 100 epochs which normalizes this during +averaging. + +#### Inference performance results + +###### Inference performance: NVIDIA DGX A100 (1xA100 80G) + +| Batch Size | XLA | AMP | Latency Avg [ms] ↓ | Throughput Avg [img/s] ↑ | +|:----------:|:-------:|:-------:|:-----------------------:|:-----------------------------:| +| 1 | ✗ | ✗ | 59.54 | 16.79 | +| 1 | ✓ | ✗ | 70.59 | 14.17 | +| 1 | ✗ | ✓ | 56.17 | 17.80 | +| 1 | ✓ | ✓ | 55.54 | 18.16 | +| 16 | ✗ | ✗ | 225.59 | 70.93 | +| 16 | ✓ | ✗ | 379.93 | 43.15 | +| 16 | ✗ | ✓ | 184.98 | 87.02 | +| 16 | ✓ | ✓ | 153.65 | 103.6 | + +Inference results are tested on single gpu. Here data generator type does not matter because only prediction time +is calculated and averaged between 5 runs. + +## Inference Demo + +Model output can be visualized from Jupyter Notebook. Use below command to start Jupyter Lab on port `8888`. + +``` +jupyter lab --no-browser --allow-root --ip=0.0.0.0 --port=8888 +``` + +While starting container we mapped system port `5012` to `8888` inside docker. +> Note: Make sure you have server network ip and port access in case you are working with remote sever. + +Now in browser go to link `http://:5012/` to access Jupyter Lab. +Open [predict.ipynb](predict.ipynb) notebook and rerun the whole notebook to visualize model output. + +There are two options for visualization, you can + +1. Visualize from directory + +It's going to make prediction and show all images from given directory. Useful for detailed evaluation. + +2. Visualize from list + +It's going to make prediction on elements of given list. Use for testing on specific cases. + +For custom data visualization set `SHOW_CENTER_CHANNEL_IMAGE=False`. This should set True for only UNet3+ LiTS data. + +For further details on visualization options see [predict.ipynb](predict.ipynb) notebook. + +## Known issues + +There are no known issues in this release. + +## Release notes + +### Changelog + +Feb 2023 + +- Initial release + +We appreciate any feedback so reporting problems, and asking questions are welcomed here. + +Licensed under [Apache-2.0 License](LICENSE) diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/benchmark_inference.py b/TensorFlow2/Segmentation/Contrib/UNet3P/benchmark_inference.py new file mode 100644 index 000000000..468607674 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/benchmark_inference.py @@ -0,0 +1,101 @@ +""" +Script to benchmark model throughput and latency +""" +import os +import numpy as np +from tqdm import tqdm +from timeit import default_timer as timer +import hydra +from omegaconf import DictConfig +import tensorflow as tf +from tensorflow.keras import mixed_precision + +from data_generators import tf_data_generator +from utils.general_utils import join_paths, suppress_warnings +from utils.images_utils import postprocess_mask +from models.model import prepare_model + + +def benchmark_time(cfg: DictConfig): + """ + Output throughput and latency + """ + + # suppress TensorFlow and DALI warnings + suppress_warnings() + + if cfg.OPTIMIZATION.AMP: + print("Enabling Automatic Mixed Precision(AMP)") + policy = mixed_precision.Policy('mixed_float16') + mixed_precision.set_global_policy(policy) + + if cfg.OPTIMIZATION.XLA: + print("Enabling Accelerated Linear Algebra(XLA)") + tf.config.optimizer.set_jit(True) + + # data generator + val_generator = tf_data_generator.DataGenerator(cfg, mode="VAL") + validation_steps = val_generator.__len__() + + warmup_steps, bench_steps = 50, 100 + if "warmup_steps" in cfg.keys(): + warmup_steps = cfg.warmup_steps + if "bench_steps" in cfg.keys(): + bench_steps = cfg.bench_steps + validation_steps = min(validation_steps, (warmup_steps + bench_steps)) + + progress_bar = tqdm(total=validation_steps) + + # create model + model = prepare_model(cfg) + + # weights model path + checkpoint_path = join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.MODEL_CHECKPOINT.PATH, + f"{cfg.MODEL.WEIGHTS_FILE_NAME}.hdf5" + ) + + assert os.path.exists(checkpoint_path), \ + f"Model weight's file does not exist at \n{checkpoint_path}" + + # load model weights + model.load_weights(checkpoint_path, by_name=True, skip_mismatch=True) + # model.summary() + + time_taken = [] + # for each batch + for i, (batch_images, batch_mask) in enumerate(val_generator): + + start_time = timer() + # make prediction on batch + batch_predictions = model.predict_on_batch(batch_images) + if len(model.outputs) > 1: + batch_predictions = batch_predictions[0] + + # do postprocessing on predicted mask + batch_predictions = postprocess_mask(batch_predictions, cfg.OUTPUT.CLASSES) + + time_taken.append(timer() - start_time) + + progress_bar.update(1) + if i >= validation_steps: + break + progress_bar.close() + + mean_time = np.mean(time_taken[warmup_steps:]) # skipping warmup_steps + throughput = (cfg.HYPER_PARAMETERS.BATCH_SIZE / mean_time) + print(f"Latency: {round(mean_time * 1e3, 2)} msec") + print(f"Throughput/FPS: {round(throughput, 2)} samples/sec") + + +@hydra.main(version_base=None, config_path="configs", config_name="config") +def main(cfg: DictConfig): + """ + Read config file and pass to benchmark_time method + """ + benchmark_time(cfg) + + +if __name__ == "__main__": + main() diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/callbacks/timing_callback.py b/TensorFlow2/Segmentation/Contrib/UNet3P/callbacks/timing_callback.py new file mode 100644 index 000000000..093fabce0 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/callbacks/timing_callback.py @@ -0,0 +1,30 @@ +import sys +from timeit import default_timer as timer +import tensorflow as tf + + +class TimingCallback(tf.keras.callbacks.Callback): + """ + Custom callback to note training time, latency and throughput + """ + + def __init__(self, ): + super(TimingCallback, self).__init__() + self.train_start_time = None + self.train_end_time = None + self.batch_time = [] + self.batch_start_time = None + + def on_train_begin(self, logs: dict): + tf.print("Training starting time noted.", output_stream=sys.stdout) + self.train_start_time = timer() + + def on_train_end(self, logs: dict): + tf.print("Training ending time noted.", output_stream=sys.stdout) + self.train_end_time = timer() + + def on_train_batch_begin(self, batch: int, logs: dict): + self.batch_start_time = timer() + + def on_train_batch_end(self, batch: int, logs: dict): + self.batch_time.append(timer() - self.batch_start_time) diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/checkpoint/tb_logs/.gitkeep b/TensorFlow2/Segmentation/Contrib/UNet3P/checkpoint/tb_logs/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/configs/README.md b/TensorFlow2/Segmentation/Contrib/UNet3P/configs/README.md new file mode 100644 index 000000000..80d091d3d --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/configs/README.md @@ -0,0 +1,86 @@ +Here we provide **overview** of our config file and how you can use your own custom settings's for training and +evaluation. + +We are using [Hydra](https://hydra.cc/) for passing configurations. Hydra is a framework for elegantly configuring +complex applications. In Hydra you can easily [extend](https://hydra.cc/docs/patterns/extending_configs/) +and [interpolate](https://hydra.cc/docs/advanced/override_grammar/basic/#primitives) `yaml` config files. + +#### Override Hydra config from command line + +[Here](https://hydra.cc/docs/1.0/advanced/override_grammar/basic/) you can read how to pass or override configurations +through command line. Overall to + +###### Override higher level attribute + +Directly access the key and override its value + +- For instance to override Data generator pass `DATA_GENERATOR_TYPE=DALI_GENERATOR` + +###### Override nested attribute + +Use `.` to access nested keys + +- For instance to override model type `MODEL.TYPE=unet3plus` +- To override model backbone `MODEL.BACKBONE.TYPE=vgg19` + +To add new element from command line add `+` before attribute name. E.g. `+warmup_steps=50` because warm steps is not +added in config file. + +> Note: Don't add space between list elements, it will create problem with Hydra. + +Most of the configurations attributes in our [config](./../configs/config.yaml) are self-explanatory. However, for some +attributes additional comments are added. + +You can override configurations from command line too, but it's **advisable to override them from config file** because +it's +easy. + +By default, hydra stores a log file of each run in a separate directory. We have disabled it in our case, +if you want to enable them to keep record of each run configuration's then comment out the settings at the end of config +file. + +```yaml +# project root working directory, automatically read by hydra (.../UNet3P) +WORK_DIR: ${hydra:runtime.cwd} +DATA_PREPARATION: + # unprocessed LiTS scan data paths, for custom data training skip this section details + SCANS_TRAIN_DATA_PATH: "/data/Training Batch 2/" + ... +DATASET: + # training data paths, should be relative from project root path + TRAIN: + IMAGES_PATH: "/data/train/images" + ... +MODEL: + # available variants are unet3plus, unet3plus_deepsup, unet3plus_deepsup_cgm + TYPE: "unet3plus" + BACKBONE: + ... +... +DATA_GENERATOR_TYPE: "DALI_GENERATOR" # options are TF_GENERATOR or DALI_GENERATOR +SHOW_CENTER_CHANNEL_IMAGE: True # only true for UNet3+. for custom dataset it should be False +# Model input shape +INPUT: + HEIGHT: 320 + ... +# Model output classes +OUTPUT: + CLASSES: 2 +HYPER_PARAMETERS: + EPOCHS: 5 + BATCH_SIZE: 2 # specify per gpu batch size + ... +CALLBACKS: + TENSORBOARD: + ... +PREPROCESS_DATA: + RESIZE: + VALUE: False # if True, resize to input height and width + ... +USE_MULTI_GPUS: + ... +# to stop hydra from storing logs files +defaults: + ... + +``` diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/configs/config.yaml b/TensorFlow2/Segmentation/Contrib/UNet3P/configs/config.yaml new file mode 100644 index 000000000..6496ac019 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/configs/config.yaml @@ -0,0 +1,118 @@ +# project root working directory, automatically read by hydra (.../UNet3P) +WORK_DIR: ${hydra:runtime.cwd} + +DATA_PREPARATION: + # unprocessed LiTS scan data paths, for custom data training skip this section details + SCANS_TRAIN_DATA_PATH: "/data/Training Batch 2/" + SCANS_VAL_DATA_PATH: "/data/Training Batch 1/" + + # Resize scans to model input size + RESIZED_HEIGHT: ${INPUT.HEIGHT} + RESIZED_WIDTH: ${INPUT.WIDTH} + + # Clip scans value in given range + SCAN_MIN_VALUE: -200 + SCAN_MAX_VALUE: 250 + +DATASET: + # paths should be relative from project root path + TRAIN: + IMAGES_PATH: "/data/train/images" + MASK_PATH: "/data/train/mask" + VAL: + IMAGES_PATH: "/data/val/images" + MASK_PATH: "/data/val/mask" + + +MODEL: + # available variants are unet3plus, unet3plus_deepsup, unet3plus_deepsup_cgm + TYPE: "unet3plus" + WEIGHTS_FILE_NAME: model_${MODEL.TYPE} + BACKBONE: + # available variants are unet3plus, vgg16, vgg19 + TYPE: "vgg19" + +DATA_GENERATOR_TYPE: "DALI_GENERATOR" # options are TF_GENERATOR or DALI_GENERATOR +SEED: 5 # for result's reproducibility +VERBOSE: 1 # For logs printing details, available options are 0, 1, 2 +DATALOADER_WORKERS: 3 # number of workers used for data loading +SHOW_CENTER_CHANNEL_IMAGE: True # only true for UNet3+ for custom dataset it should be False + +# Model input shape +INPUT: + HEIGHT: 320 + WIDTH: 320 + CHANNELS: 3 + +# Model output classes +OUTPUT: + CLASSES: 2 + + +HYPER_PARAMETERS: + EPOCHS: 100 + BATCH_SIZE: 16 # specify per gpu batch size + LEARNING_RATE: 5e-5 # 0.1, 1e-3, 3e-4, 5e-5 + + +CALLBACKS: + # paths should be relative from project root path + TENSORBOARD: + PATH: "/checkpoint/tb_logs" + + EARLY_STOPPING: + PATIENCE: 100 + + MODEL_CHECKPOINT: + PATH: "/checkpoint" + SAVE_WEIGHTS_ONLY: True + SAVE_BEST_ONLY: True + + CSV_LOGGER: + PATH: "/checkpoint" + APPEND_LOGS: False + + +PREPROCESS_DATA: + RESIZE: + VALUE: False # if True, resize to input height and width + HEIGHT: ${INPUT.HEIGHT} + WIDTH: ${INPUT.WIDTH} + + IMAGE_PREPROCESSING_TYPE: "normalize" + + NORMALIZE_MASK: + VALUE: False # if True, divide mask by given value + NORMALIZE_VALUE: 255 + + SHUFFLE: + TRAIN: + VALUE: True + VAL: + VALUE: False + + +USE_MULTI_GPUS: + VALUE: True # If True use multiple gpus for training + # GPU_IDS: Could be integer or list of integers. + # In case Integer: if integer value is -1 then it uses all available gpus. + # otherwise if positive number, then use given number of gpus. + # In case list of Integers: each integer will be considered as gpu id + # e.g. [4, 5, 7] means use gpu 5,6 and 8 for training/evaluation + GPU_IDS: -1 + + +OPTIMIZATION: + AMP: True # Automatic Mixed Precision(AMP) + XLA: True # Accelerated Linear Algebra(XLA) + + +# to stop hydra from storing logs files +# logs will be stored in outputs directory +defaults: + - _self_ + - override hydra/hydra_logging: disabled + - override hydra/job_logging: disabled + +hydra: + output_subdir: null diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data/Training Batch 1/.gitkeep b/TensorFlow2/Segmentation/Contrib/UNet3P/data/Training Batch 1/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data/Training Batch 2/.gitkeep b/TensorFlow2/Segmentation/Contrib/UNet3P/data/Training Batch 2/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data/train/.gitkeep b/TensorFlow2/Segmentation/Contrib/UNet3P/data/train/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data/val/.gitkeep b/TensorFlow2/Segmentation/Contrib/UNet3P/data/val/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/README.md b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/README.md new file mode 100644 index 000000000..d65de3a72 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/README.md @@ -0,0 +1,44 @@ +Our code base support two types of data loaders. + +- [Tensorflow Sequence Generator](#tensorflow-sequence-generator) +- [NVIDIA DALI Generator](#nvidia-dali-generator) + +## [Tensorflow Sequence Generator](https://www.tensorflow.org/api_docs/python/tf/keras/utils/Sequence) + +Sequence data generator is best suited for situations where we need +advanced control over sample generation or when simple data does not +fit into memory and must be loaded dynamically. + +Our [sequence generator](./../data_generators/tf_data_generator.py) generates +dataset on multiple cores in real time and feed it right away to deep +learning model. + +## [NVIDIA DALI Generator](https://docs.nvidia.com/deeplearning/dali/user-guide/docs/index.html) + +The NVIDIA Data Loading Library (DALI) is a library for data loading and +pre-processing to accelerate deep learning applications. It provides a +collection of highly optimized building blocks for loading and processing +image, video and audio data. It can be used as a portable drop-in +replacement for built in data loaders and data iterators in popular deep +learning frameworks. + +We've used [DALI Pipeline](./../data_generators/dali_data_generator.py) to directly load +data on `GPU`, which resulted in reduced latency and training time, +mitigating bottlenecks, by overlapping training and pre-processing. Our code +base also support's multi GPU data loading for DALI. + +## Use Cases + +For training and evaluation you can use both `TF Sequence` and `DALI` generator with multiple gpus, but for prediction +and inference benchmark we only support `TF Sequence` generator with single gpu support. + +> Reminder: DALI is only supported on Linux platforms. For Windows, you can +> train using Sequence Generator. The code base will work without DALI +> installation too. + +It's advised to use DALI only when you have large gpu memory to load both model +and training data at the same time. + +Override `DATA_GENERATOR_TYPE` in config to change default generator type. Possible +options are `TF_GENERATOR` for Sequence generator and `DALI_GENERATOR` for DALI generator. + diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/dali_data_generator.py b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/dali_data_generator.py new file mode 100644 index 000000000..085c321de --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/dali_data_generator.py @@ -0,0 +1,264 @@ +""" +NVIDIA DALI data generator object. +""" +import nvidia.dali.fn as fn +from nvidia.dali import pipeline_def +import nvidia.dali.types as types +import nvidia.dali.plugin.tf as dali_tf +import tensorflow as tf +from omegaconf import DictConfig + +from utils.general_utils import get_data_paths, get_gpus_count + + +def data_generator_pipeline(cfg: DictConfig, mode: str, mask_available: bool): + """ + Returns DALI data pipeline object. + """ + data_paths = get_data_paths(cfg, mode, mask_available) # get data paths + images_paths = data_paths[0] + if mask_available: + mask_paths = data_paths[1] + + @pipeline_def(batch_size=cfg.HYPER_PARAMETERS.BATCH_SIZE) + def single_gpu_pipeline(device): + """ + Returns DALI data pipeline object for single GPU training. + """ + device = 'mixed' if 'gpu' in device.lower() else 'cpu' + + pngs, _ = fn.readers.file( + files=images_paths, + random_shuffle=cfg.PREPROCESS_DATA.SHUFFLE[mode].VALUE, + seed=cfg.SEED + ) + images = fn.decoders.image(pngs, device=device, output_type=types.RGB) + if cfg.PREPROCESS_DATA.RESIZE.VALUE: + # TODO verify image resizing method + images = fn.resize( + images, + size=[ + cfg.PREPROCESS_DATA.RESIZE.HEIGHT, + cfg.PREPROCESS_DATA.RESIZE.WIDTH + ] + ) + if cfg.PREPROCESS_DATA.IMAGE_PREPROCESSING_TYPE == "normalize": + images = fn.normalize(images, mean=0, stddev=255, ) # axes=(2,) + + if mask_available: + labels, _ = fn.readers.file( + files=mask_paths, + random_shuffle=cfg.PREPROCESS_DATA.SHUFFLE[mode].VALUE, + seed=cfg.SEED + ) + labels = fn.decoders.image( + labels, + device=device, + output_type=types.GRAY + ) + if cfg.PREPROCESS_DATA.RESIZE.VALUE: + # TODO verify image resizing method + labels = fn.resize( + labels, + size=[ + cfg.PREPROCESS_DATA.RESIZE.HEIGHT, + cfg.PREPROCESS_DATA.RESIZE.WIDTH + ] + ) + if cfg.PREPROCESS_DATA.NORMALIZE_MASK.VALUE: + labels = fn.normalize( + labels, + mean=0, + stddev=cfg.PREPROCESS_DATA.NORMALIZE_MASK.NORMALIZE_VALUE, + ) + if cfg.OUTPUT.CLASSES == 1: + labels = fn.cast(labels, dtype=types.FLOAT) + else: + labels = fn.squeeze(labels, axes=[2]) + labels = fn.one_hot(labels, num_classes=cfg.OUTPUT.CLASSES) + + if mask_available: + return images, labels + else: + return images, + + @pipeline_def(batch_size=cfg.HYPER_PARAMETERS.BATCH_SIZE) + def multi_gpu_pipeline(device, shard_id): + """ + Returns DALI data pipeline object for multi GPU'S training. + """ + device = 'mixed' if 'gpu' in device.lower() else 'cpu' + shard_id = 1 if 'cpu' in device else shard_id + num_shards = get_gpus_count() + # num_shards should be <= #images + num_shards = len(images_paths) if num_shards > len(images_paths) else num_shards + + pngs, _ = fn.readers.file( + files=images_paths, + random_shuffle=cfg.PREPROCESS_DATA.SHUFFLE[mode].VALUE, + shard_id=shard_id, + num_shards=num_shards, + seed=cfg.SEED + ) + images = fn.decoders.image(pngs, device=device, output_type=types.RGB) + if cfg.PREPROCESS_DATA.RESIZE.VALUE: + # TODO verify image resizing method + images = fn.resize( + images, + size=[ + cfg.PREPROCESS_DATA.RESIZE.HEIGHT, + cfg.PREPROCESS_DATA.RESIZE.WIDTH + ] + ) + if cfg.PREPROCESS_DATA.IMAGE_PREPROCESSING_TYPE == "normalize": + images = fn.normalize(images, mean=0, stddev=255, ) # axes=(2,) + + if mask_available: + labels, _ = fn.readers.file( + files=mask_paths, + random_shuffle=cfg.PREPROCESS_DATA.SHUFFLE[mode].VALUE, + shard_id=shard_id, + num_shards=num_shards, + seed=cfg.SEED + ) + labels = fn.decoders.image( + labels, + device=device, + output_type=types.GRAY + ) + if cfg.PREPROCESS_DATA.RESIZE.VALUE: + # TODO verify image resizing method + labels = fn.resize( + labels, + size=[ + cfg.PREPROCESS_DATA.RESIZE.HEIGHT, + cfg.PREPROCESS_DATA.RESIZE.WIDTH + ] + ) + if cfg.PREPROCESS_DATA.NORMALIZE_MASK.VALUE: + labels = fn.normalize( + labels, + mean=0, + stddev=cfg.PREPROCESS_DATA.NORMALIZE_MASK.NORMALIZE_VALUE, + ) + if cfg.OUTPUT.CLASSES == 1: + labels = fn.cast(labels, dtype=types.FLOAT) + else: + labels = fn.squeeze(labels, axes=[2]) + labels = fn.one_hot(labels, num_classes=cfg.OUTPUT.CLASSES) + + if mask_available: + return images, labels + else: + return images, + + if cfg.USE_MULTI_GPUS.VALUE: + return multi_gpu_pipeline + else: + return single_gpu_pipeline + + +def get_data_shapes(cfg: DictConfig, mask_available: bool): + """ + Returns shapes and dtypes of the outputs. + """ + if mask_available: + shapes = ( + (cfg.HYPER_PARAMETERS.BATCH_SIZE, + cfg.INPUT.HEIGHT, + cfg.INPUT.WIDTH, + cfg.INPUT.CHANNELS), + (cfg.HYPER_PARAMETERS.BATCH_SIZE, + cfg.INPUT.HEIGHT, + cfg.INPUT.WIDTH, + cfg.OUTPUT.CLASSES) + ) + dtypes = ( + tf.float32, + tf.float32) + else: + shapes = ( + (cfg.HYPER_PARAMETERS.BATCH_SIZE, + cfg.INPUT.HEIGHT, + cfg.INPUT.WIDTH, + cfg.INPUT.CHANNELS), + ) + dtypes = ( + tf.float32, + ) + return shapes, dtypes + + +def data_generator(cfg: DictConfig, + mode: str, + strategy: tf.distribute.Strategy = None): + """ + Generate batches of data for model by reading images and their + corresponding masks using NVIDIA DALI. + Works for both single and mult GPU's. In case of multi gpu pass + the strategy object too. + There are two options you can either pass directory path or list. + In case of directory, it should contain relative path of images/mask + folder from project root path. + In case of list of images, every element should contain absolute path + for each image and mask. + """ + + # check mask are available or not + mask_available = False if cfg.DATASET[mode].MASK_PATH is None or str( + cfg.DATASET[mode].MASK_PATH).lower() == "none" else True + + # create dali data pipeline + data_pipeline = data_generator_pipeline(cfg, mode, mask_available) + + shapes, dtypes = get_data_shapes(cfg, mask_available) + + if cfg.USE_MULTI_GPUS.VALUE: + def bound_dataset(input_context): + """ + In case of multi gpu training bound dataset to a device for distributed training. + """ + with tf.device("/gpu:{}".format(input_context.input_pipeline_id)): + device_id = input_context.input_pipeline_id + return dali_tf.DALIDataset( + pipeline=data_pipeline( + device="gpu", + device_id=device_id, + shard_id=device_id, + num_threads=cfg.DATALOADER_WORKERS + ), + batch_size=cfg.HYPER_PARAMETERS.BATCH_SIZE, + output_shapes=shapes, + output_dtypes=dtypes, + device_id=device_id, + ) + + # distribute dataset + input_options = tf.distribute.InputOptions( + experimental_place_dataset_on_device=True, + # for older dali versions use experimental_prefetch_to_device + # for new dali versions use experimental_fetch_to_device + experimental_fetch_to_device=False, # experimental_fetch_to_device + experimental_replication_mode=tf.distribute.InputReplicationMode.PER_REPLICA) + + # map dataset to given strategy and return it + return strategy.distribute_datasets_from_function(bound_dataset, input_options) + else: + # single gpu pipeline + pipeline = data_pipeline( + batch_size=cfg.HYPER_PARAMETERS.BATCH_SIZE, + num_threads=cfg.DATALOADER_WORKERS, + device="gpu", + device_id=0 + ) + + # create dataset + with tf.device('/gpu:0'): + data_generator = dali_tf.DALIDataset( + pipeline=pipeline, + batch_size=cfg.HYPER_PARAMETERS.BATCH_SIZE, + output_shapes=shapes, + output_dtypes=dtypes, + device_id=0) + + return data_generator diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/data_generator.py b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/data_generator.py new file mode 100644 index 000000000..ab19123e2 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/data_generator.py @@ -0,0 +1,88 @@ +""" +Data generator +""" +import os +import tensorflow as tf +from omegaconf import DictConfig + +from utils.general_utils import join_paths, get_gpus_count +from .tf_data_generator import DataGenerator as tf_data_generator + +try: + from .dali_data_generator import data_generator as dali_data_generator +except ModuleNotFoundError: + print("NVIDIA DALI not installed, please install it." + "\nNote: DALI is only available on Linux platform. For Window " + "you can use TensorFlow generator for training.") + + +def get_data_generator(cfg: DictConfig, + mode: str, + strategy: tf.distribute.Strategy = None): + """ + Creates and return data generator object based on given type. + """ + if cfg.DATA_GENERATOR_TYPE == "TF_GENERATOR": + print(f"Using TensorFlow generator for {mode} data") + generator = tf_data_generator(cfg, mode) + elif cfg.DATA_GENERATOR_TYPE == "DALI_GENERATOR": + print(f"Using NVIDIA DALI generator for {mode} data") + if cfg.USE_MULTI_GPUS.VALUE: + generator = dali_data_generator(cfg, mode, strategy) + else: + generator = dali_data_generator(cfg, mode) + else: + raise ValueError( + "Wrong generator type passed." + "\nPossible options are TF_GENERATOR and DALI_GENERATOR" + ) + return generator + + +def update_batch_size(cfg: DictConfig): + """ + Scale up batch size to multi gpus in case of TensorFlow generator. + """ + if cfg.DATA_GENERATOR_TYPE == "TF_GENERATOR" and cfg.USE_MULTI_GPUS.VALUE: + # change batch size according to available gpus + cfg.HYPER_PARAMETERS.BATCH_SIZE = \ + cfg.HYPER_PARAMETERS.BATCH_SIZE * get_gpus_count() + + +def get_batch_size(cfg: DictConfig): + """ + Return batch size. + In case of DALI generator scale up batch size to multi gpus. + """ + if cfg.DATA_GENERATOR_TYPE == "DALI_GENERATOR" and cfg.USE_MULTI_GPUS.VALUE: + # change batch size according to available gpus + return cfg.HYPER_PARAMETERS.BATCH_SIZE * get_gpus_count() + else: + return cfg.HYPER_PARAMETERS.BATCH_SIZE + + +def get_iterations(cfg: DictConfig, mode: str): + """ + Return steps per epoch + """ + images_length = len( + os.listdir( + join_paths( + cfg.WORK_DIR, + cfg.DATASET[mode].IMAGES_PATH + ) + ) + ) + + if cfg.DATA_GENERATOR_TYPE == "TF_GENERATOR": + training_steps = images_length // cfg.HYPER_PARAMETERS.BATCH_SIZE + elif cfg.DATA_GENERATOR_TYPE == "DALI_GENERATOR": + if cfg.USE_MULTI_GPUS.VALUE: + training_steps = images_length // ( + cfg.HYPER_PARAMETERS.BATCH_SIZE * get_gpus_count()) + else: + training_steps = images_length // cfg.HYPER_PARAMETERS.BATCH_SIZE + else: + raise ValueError("Wrong generator type passed.") + + return training_steps diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/tf_data_generator.py b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/tf_data_generator.py new file mode 100644 index 000000000..8f35a1b84 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_generators/tf_data_generator.py @@ -0,0 +1,179 @@ +""" +Tensorflow data generator class. +""" +import tensorflow as tf +import numpy as np +from omegaconf import DictConfig + +from utils.general_utils import get_data_paths +from utils.images_utils import prepare_image, prepare_mask + + +class DataGenerator(tf.keras.utils.Sequence): + """ + Generate batches of data for model by reading images and their + corresponding masks using TensorFlow Sequence Generator. + There are two options you can either pass directory path or list. + In case of directory, it should contain relative path of images/mask + folder from project root path. + In case of list of images, every element should contain absolute path + for each image and mask. + Because this generator is also used for prediction, so during testing you can + set mask path to None if mask are not available for visualization. + """ + + def __init__(self, cfg: DictConfig, mode: str): + """ + Initialization + """ + self.cfg = cfg + self.mode = mode + self.batch_size = self.cfg.HYPER_PARAMETERS.BATCH_SIZE + # set seed for reproducibility + np.random.seed(cfg.SEED) + + # check mask are available or not + self.mask_available = False if cfg.DATASET[mode].MASK_PATH is None or str( + cfg.DATASET[mode].MASK_PATH).lower() == "none" else True + + data_paths = get_data_paths(cfg, mode, self.mask_available) + + self.images_paths = data_paths[0] + if self.mask_available: + self.mask_paths = data_paths[1] + + # self.images_paths.sort() # no need for sorting + + self.on_epoch_end() + + def __len__(self): + """ + Denotes the number of batches per epoch + """ + # Tensorflow problem: on_epoch_end is not being called at the end + # of each epoch, so forcing on_epoch_end call + self.on_epoch_end() + return int( + np.floor( + len(self.images_paths) / self.batch_size + ) + ) + + def on_epoch_end(self): + """ + Updates indexes after each epoch + """ + self.indexes = np.arange(len(self.images_paths)) + if self.cfg.PREPROCESS_DATA.SHUFFLE[self.mode].VALUE: + np.random.shuffle(self.indexes) + + def __getitem__(self, index): + """ + Generate one batch of data + """ + # Generate indexes of the batch + indexes = self.indexes[ + index * self.batch_size:(index + 1) * self.batch_size + ] + + # Generate data + return self.__data_generation(indexes) + + def __data_generation(self, indexes): + """ + Generates batch data + """ + + # create empty array to store batch data + batch_images = np.zeros( + ( + self.cfg.HYPER_PARAMETERS.BATCH_SIZE, + self.cfg.INPUT.HEIGHT, + self.cfg.INPUT.WIDTH, + self.cfg.INPUT.CHANNELS + ) + ).astype(np.float32) + + if self.mask_available: + batch_masks = np.zeros( + ( + self.cfg.HYPER_PARAMETERS.BATCH_SIZE, + self.cfg.INPUT.HEIGHT, + self.cfg.INPUT.WIDTH, + self.cfg.OUTPUT.CLASSES + ) + ).astype(np.float32) + + for i, index in enumerate(indexes): + # extract path from list + img_path = self.images_paths[int(index)] + if self.mask_available: + mask_path = self.mask_paths[int(index)] + + # prepare image for model by resizing and preprocessing it + image = prepare_image( + img_path, + self.cfg.PREPROCESS_DATA.RESIZE, + self.cfg.PREPROCESS_DATA.IMAGE_PREPROCESSING_TYPE, + ) + + if self.mask_available: + # prepare image for model by resizing and preprocessing it + mask = prepare_mask( + mask_path, + self.cfg.PREPROCESS_DATA.RESIZE, + self.cfg.PREPROCESS_DATA.NORMALIZE_MASK, + ) + + # numpy to tensorflow conversion + if self.mask_available: + image, mask = tf.numpy_function( + self.tf_func, + [image, mask], + [tf.float32, tf.int32] + ) + else: + image = tf.numpy_function( + self.tf_func, + [image, ], + [tf.float32, ] + ) + + # set shape attributes which was lost during Tf conversion + image.set_shape( + [ + self.cfg.INPUT.HEIGHT, + self.cfg.INPUT.WIDTH, + self.cfg.INPUT.CHANNELS + ] + ) + batch_images[i] = image + + if self.mask_available: + # height x width --> height x width x output classes + if self.cfg.OUTPUT.CLASSES == 1: + mask = tf.expand_dims(mask, axis=-1) + else: + # convert mask into one hot vectors + mask = tf.one_hot( + mask, + self.cfg.OUTPUT.CLASSES, + dtype=tf.int32 + ) + mask.set_shape( + [ + self.cfg.INPUT.HEIGHT, + self.cfg.INPUT.WIDTH, + self.cfg.OUTPUT.CLASSES + ] + ) + batch_masks[i] = mask + + if self.mask_available: + return batch_images, batch_masks + else: + return batch_images, + + @staticmethod + def tf_func(*args): + return args diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/README.md b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/README.md new file mode 100644 index 000000000..9acd5b172 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/README.md @@ -0,0 +1,102 @@ +For data two options are available + +- [Train on LiTS Data](#lits-liver-tumor-segmentation-challenge) +- [Train on custom data](#train-on-custom-data) + +## LiTS Liver Tumor Segmentation challenge + +This dataset consist of 131 Liver CT Scans. + +Register [here](https://competitions.codalab.org/competitions/17094) to get dataset access. +Go to participate → Training Data to get dataset link. +Download Training Batch 1 and Training Batch 2 zip files and past them under data folder. + +`Training Batch 1` size is 3.97GB and `Training Batch 2` zip file size is 11.5GB. + +Inside main directory `/workspace/unet3p` run below command to extract zip files + +```shell +bash data_preparation/extract_data.sh +``` + +After extraction `Training Batch 1` folder size will be 11.4GB and `Training Batch 2` folder size will be 38.5GB. + +- `Training Batch 1` consist of 28 scans which are used for testing +- `Training Batch 2` consist of 103 scans which are used for training + +Default directory structure looks like this + + ├── data/ + │ ├── Training Batch 1/ + ├── segmentation-0.nii + ├── volume-0.nii + ├── ... + ├── volume-27.nii + │ ├── Training Batch 2/ + ├── segmentation-28.nii + ├── volume-28.nii + ├── ... + ├── volume-130.nii + +For testing, you can have any number of files in Training Batch 1 and Training Batch 2. But make sure the naming +convention is similar. + +To prepare LiTS dataset for training run + +``` +python data_preparation/preprocess_data.py +``` + +> Note: Because of the extensive preprocessing, it will take some time, so relax and wait. + +#### Final directory + +After completion, you will have a directories like this + + ├── data/ + │ ├── train/ + ├── images + ├── image_28_0.png + ├── ... + ├── mask + ├── mask_28_0.png + ├── ... + │ ├── val/ + ├── images + ├── image_0_0.png + ├── ... + ├── mask + ├── mask_0_0.png + ├── ... + +After processing the `train` folder size will be 5GB and `val` folder size will be 1.7GB. + +#### Free space (Optional) + +At this stage you can delete the intermediate scans files to free space, run below command + +```shell +bash data_preparation/delete_extracted_scans_data.sh +``` + +You can also delete the data zip files using below command, but remember you cannot retrieve them back + +```shell +bash data_preparation/delete_zip_data.sh +``` + +> Note: It is recommended to delete scan files but not zip data because you may need it again. + +## Train on custom data + +To train on custom dateset it's advised that you follow the same train and val directory structure like +mentioned [above](#final-directory). + +In our case image file name can be mapped to it's corresponding mask file name by replacing `image` text with `mask`. If +your data has different mapping then you need to update [image_to_mask_name](./../utils/images_utils.py#L63) function which +is responsible for converting image name to it's corresponding file name. + +Each image should be a color image with 3 channels and `RGB` color format. Each mask is considered as a gray scale +image, where each pixel value is the class on which each pixel belongs. + +Congratulations, now you can start training and testing on your new dataset! \ No newline at end of file diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/delete_extracted_scans_data.sh b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/delete_extracted_scans_data.sh new file mode 100644 index 000000000..72683297b --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/delete_extracted_scans_data.sh @@ -0,0 +1,2 @@ +rm -r 'data/Training Batch 1/' +rm -r 'data/Training Batch 2/' \ No newline at end of file diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/delete_zip_data.sh b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/delete_zip_data.sh new file mode 100644 index 000000000..14437b63f --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/delete_zip_data.sh @@ -0,0 +1,2 @@ +rm data/Training_Batch1.zip +rm data/Training_Batch2.zip \ No newline at end of file diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/extract_data.sh b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/extract_data.sh new file mode 100644 index 000000000..b284a3e7f --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/extract_data.sh @@ -0,0 +1,9 @@ +# extract testing data +unzip data/Training_Batch1.zip -d data/ +mv "data/media/nas/01_Datasets/CT/LITS/Training Batch 1/" "data/Training Batch 1/" +rm -r data/media + +# extract training data +unzip data/Training_Batch2.zip -d data/ +mv "data/media/nas/01_Datasets/CT/LITS/Training Batch 2/" "data/Training Batch 2/" +rm -r data/media diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/preprocess_data.py b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/preprocess_data.py new file mode 100644 index 000000000..9fb475015 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/preprocess_data.py @@ -0,0 +1,242 @@ +""" +Convert LiTS 2017 (Liver Tumor Segmentation) data into UNet3+ data format +LiTS: https://competitions.codalab.org/competitions/17094 +""" +import os +import sys +from glob import glob +from pathlib import Path +from tqdm import tqdm +import numpy as np +import multiprocessing as mp +import cv2 +import nibabel as nib +import hydra +from omegaconf import DictConfig + +sys.path.append(os.path.abspath("./")) +from utils.general_utils import create_directory, join_paths +from utils.images_utils import resize_image + + +def read_nii(filepath): + """ + Reads .nii file and returns pixel array + """ + ct_scan = nib.load(filepath).get_fdata() + # TODO: Verify images orientation + # in both train and test set, especially on train scan 130 + ct_scan = np.rot90(np.array(ct_scan)) + return ct_scan + + +def crop_center(img, croph, cropw): + """ + Center crop on given height and width + """ + height, width = img.shape[:2] + starth = height // 2 - (croph // 2) + startw = width // 2 - (cropw // 2) + return img[starth:starth + croph, startw:startw + cropw, :] + + +def linear_scale(img): + """ + First convert image to range of 0-1 and them scale to 255 + """ + img = (img - img.min(axis=(0, 1))) / (img.max(axis=(0, 1)) - img.min(axis=(0, 1))) + return img * 255 + + +def clip_scan(img, min_value, max_value): + """ + Clip scan to given range + """ + return np.clip(img, min_value, max_value) + + +def resize_scan(scan, new_height, new_width, scan_type): + """ + Resize CT scan to given size + """ + scan_shape = scan.shape + resized_scan = np.zeros((new_height, new_width, scan_shape[2]), dtype=scan.dtype) + resize_method = cv2.INTER_CUBIC if scan_type == "image" else cv2.INTER_NEAREST + for start in range(0, scan_shape[2], scan_shape[1]): + end = start + scan_shape[1] + if end >= scan_shape[2]: end = scan_shape[2] + resized_scan[:, :, start:end] = resize_image( + scan[:, :, start:end], + new_height, new_width, + resize_method + ) + + return resized_scan + + +def save_images(scan, save_path, img_index): + """ + Based on UNet3+ requirement "input image had three channels, including + the slice to be segmented and the upper and lower slices, which was + cropped to 320×320" save each scan as separate image with previous and + next scan concatenated. + """ + scan_shape = scan.shape + for index in range(scan_shape[-1]): + before_index = index - 1 if (index - 1) > 0 else 0 + after_index = index + 1 if (index + 1) < scan_shape[-1] else scan_shape[-1] - 1 + + new_img_path = join_paths(save_path, f"image_{img_index}_{index}.png") + new_image = np.stack( + ( + scan[:, :, before_index], + scan[:, :, index], + scan[:, :, after_index] + ) + , axis=-1) + new_image = cv2.cvtColor(new_image, cv2.COLOR_RGB2BGR) # RGB to BGR + cv2.imwrite(new_img_path, new_image) # save the images as .png + + +def save_mask(scan, save_path, mask_index): + """ + Save each scan as separate mask + """ + for index in range(scan.shape[-1]): + new_mask_path = join_paths(save_path, f"mask_{mask_index}_{index}.png") + cv2.imwrite(new_mask_path, scan[:, :, index]) # save grey scale image + + +def extract_image(cfg, image_path, save_path, scan_type="image", ): + """ + Extract image from given scan path + """ + _, index = str(Path(image_path).stem).split("-") + + scan = read_nii(image_path) + scan = resize_scan( + scan, + cfg.DATA_PREPARATION.RESIZED_HEIGHT, + cfg.DATA_PREPARATION.RESIZED_WIDTH, + scan_type + ) + if scan_type == "image": + scan = clip_scan( + scan, + cfg.DATA_PREPARATION.SCAN_MIN_VALUE, + cfg.DATA_PREPARATION.SCAN_MAX_VALUE + ) + scan = linear_scale(scan) + scan = np.uint8(scan) + save_images(scan, save_path, index) + else: + # 0 for background/non-lesion, 1 for liver, 2 for lesion/tumor + # merging label 2 into label 1, because lesion/tumor is part of liver + scan = np.where(scan != 0, 1, scan) + # scan = np.where(scan==2, 1, scan) + scan = np.uint8(scan) + save_mask(scan, save_path, index) + + +def extract_images(cfg, images_path, save_path, scan_type="image", ): + """ + Extract images paths using multiprocessing and pass to + extract_image function for further processing . + """ + # create pool + process_count = np.clip(mp.cpu_count() - 2, 1, 20) # less than 20 workers + pool = mp.Pool(process_count) + for image_path in tqdm(images_path): + pool.apply_async(extract_image, + args=(cfg, image_path, save_path, scan_type), + ) + + # close pool + pool.close() + pool.join() + + +@hydra.main(version_base=None, config_path="../configs", config_name="config") +def preprocess_lits_data(cfg: DictConfig): + """ + Preprocess LiTS 2017 (Liver Tumor Segmentation) data by extractions + images and mask into UNet3+ data format + """ + train_images_names = glob( + join_paths( + cfg.WORK_DIR, + cfg.DATA_PREPARATION.SCANS_TRAIN_DATA_PATH, + "volume-*.nii" + ) + ) + train_mask_names = glob( + join_paths( + cfg.WORK_DIR, + cfg.DATA_PREPARATION.SCANS_TRAIN_DATA_PATH, + "segmentation-*.nii" + ) + ) + + assert len(train_images_names) == len(train_mask_names), \ + "Train volumes and segmentations are not same in length" + + val_images_names = glob( + join_paths( + cfg.WORK_DIR, + cfg.DATA_PREPARATION.SCANS_VAL_DATA_PATH, + "volume-*.nii" + ) + ) + val_mask_names = glob( + join_paths( + cfg.WORK_DIR, + cfg.DATA_PREPARATION.SCANS_VAL_DATA_PATH, + "segmentation-*.nii" + ) + ) + assert len(val_images_names) == len(val_mask_names), \ + "Validation volumes and segmentations are not same in length" + + train_images_names = sorted(train_images_names) + train_mask_names = sorted(train_mask_names) + val_images_names = sorted(val_images_names) + val_mask_names = sorted(val_mask_names) + + train_images_path = join_paths( + cfg.WORK_DIR, cfg.DATASET.TRAIN.IMAGES_PATH + ) + train_mask_path = join_paths( + cfg.WORK_DIR, cfg.DATASET.TRAIN.MASK_PATH + ) + val_images_path = join_paths( + cfg.WORK_DIR, cfg.DATASET.VAL.IMAGES_PATH + ) + val_mask_path = join_paths( + cfg.WORK_DIR, cfg.DATASET.VAL.MASK_PATH + ) + + create_directory(train_images_path) + create_directory(train_mask_path) + create_directory(val_images_path) + create_directory(val_mask_path) + + print("\nExtracting train images") + extract_images( + cfg, train_images_names, train_images_path, scan_type="image" + ) + print("\nExtracting train mask") + extract_images( + cfg, train_mask_names, train_mask_path, scan_type="mask" + ) + print("\nExtracting val images") + extract_images( + cfg, val_images_names, val_images_path, scan_type="image" + ) + print("\nExtracting val mask") + extract_images( + cfg, val_mask_names, val_mask_path, scan_type="mask" + ) + + +if __name__ == '__main__': + preprocess_lits_data() diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/verify_data.py b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/verify_data.py new file mode 100644 index 000000000..0eb0d77bf --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/data_preparation/verify_data.py @@ -0,0 +1,56 @@ +""" +Verify for each image corresponding mask exist or not. +Check against both train and val data +""" +import os +import sys +from omegaconf import DictConfig +from tqdm import tqdm + +sys.path.append(os.path.abspath("./")) +from utils.general_utils import join_paths +from utils.images_utils import image_to_mask_name + + +def check_image_and_mask(cfg, mode): + """ + Check and print names of those images whose mask are not found. + """ + images_path = join_paths( + cfg.WORK_DIR, + cfg.DATASET[mode].IMAGES_PATH + ) + mask_path = join_paths( + cfg.WORK_DIR, + cfg.DATASET[mode].MASK_PATH + ) + + all_images = os.listdir(images_path) + + both_found = True + for image in tqdm(all_images): + mask_name = image_to_mask_name(image) + if not ( + os.path.exists( + join_paths(images_path, image) + ) and + os.path.exists( + join_paths(mask_path, mask_name) + ) + ): + print(f"{mask_name} did not found against {image}") + both_found = False + + return both_found + + +def verify_data(cfg: DictConfig): + """ + For both train and val data, check for each image its + corresponding mask exist or not. If not then stop the program. + """ + assert check_image_and_mask(cfg, "TRAIN"), \ + "Train images and mask should be same in length" + + assert check_image_and_mask(cfg, "VAL"), \ + "Validation images and mask should be same in length" diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/evaluate.py b/TensorFlow2/Segmentation/Contrib/UNet3P/evaluate.py new file mode 100644 index 000000000..555381e6b --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/evaluate.py @@ -0,0 +1,125 @@ +""" +Evaluation script used to calculate accuracy of trained model +""" +import os +import hydra +from omegaconf import DictConfig +import tensorflow as tf +from tensorflow.keras import mixed_precision + +from data_generators import data_generator +from utils.general_utils import join_paths, set_gpus, suppress_warnings +from models.model import prepare_model +from losses.loss import DiceCoefficient +from losses.unet_loss import unet3p_hybrid_loss + + +def evaluate(cfg: DictConfig): + """ + Evaluate or calculate accuracy of given model + """ + + # suppress TensorFlow and DALI warnings + suppress_warnings() + + if cfg.USE_MULTI_GPUS.VALUE: + # change number of visible gpus for evaluation + set_gpus(cfg.USE_MULTI_GPUS.GPU_IDS) + # update batch size according to available gpus + data_generator.update_batch_size(cfg) + + if cfg.OPTIMIZATION.AMP: + print("Enabling Automatic Mixed Precision(AMP) training") + policy = mixed_precision.Policy('mixed_float16') + mixed_precision.set_global_policy(policy) + + if cfg.OPTIMIZATION.XLA: + print("Enabling Automatic Mixed Precision(XLA) training") + tf.config.optimizer.set_jit(True) + + # create model + strategy = None + if cfg.USE_MULTI_GPUS.VALUE: + # multi gpu training using tensorflow mirrored strategy + strategy = tf.distribute.MirroredStrategy( + cross_device_ops=tf.distribute.HierarchicalCopyAllReduce() + ) + print('Number of visible gpu devices: {}'.format(strategy.num_replicas_in_sync)) + with strategy.scope(): + optimizer = tf.keras.optimizers.Adam( + learning_rate=cfg.HYPER_PARAMETERS.LEARNING_RATE + ) # optimizer + if cfg.OPTIMIZATION.AMP: + optimizer = mixed_precision.LossScaleOptimizer( + optimizer, + dynamic=True + ) + dice_coef = DiceCoefficient(post_processed=True, classes=cfg.OUTPUT.CLASSES) + dice_coef = tf.keras.metrics.MeanMetricWrapper(name="dice_coef", fn=dice_coef) + model = prepare_model(cfg, training=True) + else: + optimizer = tf.keras.optimizers.Adam( + learning_rate=cfg.HYPER_PARAMETERS.LEARNING_RATE + ) # optimizer + if cfg.OPTIMIZATION.AMP: + optimizer = mixed_precision.LossScaleOptimizer( + optimizer, + dynamic=True + ) + dice_coef = DiceCoefficient(post_processed=True, classes=cfg.OUTPUT.CLASSES) + dice_coef = tf.keras.metrics.MeanMetricWrapper(name="dice_coef", fn=dice_coef) + model = prepare_model(cfg, training=True) + + model.compile( + optimizer=optimizer, + loss=unet3p_hybrid_loss, + metrics=[dice_coef], + ) + + # weights model path + checkpoint_path = join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.MODEL_CHECKPOINT.PATH, + f"{cfg.MODEL.WEIGHTS_FILE_NAME}.hdf5" + ) + + assert os.path.exists(checkpoint_path), \ + f"Model weight's file does not exist at \n{checkpoint_path}" + + # TODO: verify without augment it produces same results + # load model weights + model.load_weights(checkpoint_path, by_name=True, skip_mismatch=True) + model.summary() + + # data generators + val_generator = data_generator.get_data_generator(cfg, "VAL", strategy) + validation_steps = data_generator.get_iterations(cfg, mode="VAL") + + # evaluation metric + evaluation_metric = "dice_coef" + if len(model.outputs) > 1: + evaluation_metric = f"{model.output_names[0]}_dice_coef" + + result = model.evaluate( + x=val_generator, + steps=validation_steps, + workers=cfg.DATALOADER_WORKERS, + return_dict=True, + ) + + # return computed loss, validation accuracy, and it's metric name + return result, evaluation_metric + + +@hydra.main(version_base=None, config_path="configs", config_name="config") +def main(cfg: DictConfig): + """ + Read config file and pass to evaluate method + """ + result, evaluation_metric = evaluate(cfg) + print(result) + print(f"Validation dice coefficient: {result[evaluation_metric]}") + + +if __name__ == "__main__": + main() diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/figures/unet3p_architecture.png b/TensorFlow2/Segmentation/Contrib/UNet3P/figures/unet3p_architecture.png new file mode 100644 index 000000000..77a892f11 Binary files /dev/null and b/TensorFlow2/Segmentation/Contrib/UNet3P/figures/unet3p_architecture.png differ diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/losses/loss.py b/TensorFlow2/Segmentation/Contrib/UNet3P/losses/loss.py new file mode 100644 index 000000000..652c7434e --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/losses/loss.py @@ -0,0 +1,114 @@ +""" +Implementation of different loss functions +""" +import tensorflow as tf +import tensorflow.keras.backend as K + + +def iou(y_true, y_pred, smooth=1.e-9): + """ + Calculate intersection over union (IoU) between images. + Input shape should be Batch x Height x Width x #Classes (BxHxWxN). + Using Mean as reduction type for batch values. + """ + intersection = K.sum(K.abs(y_true * y_pred), axis=[1, 2, 3]) + union = K.sum(y_true, [1, 2, 3]) + K.sum(y_pred, [1, 2, 3]) + union = union - intersection + iou = K.mean((intersection + smooth) / (union + smooth), axis=0) + return iou + + +def iou_loss(y_true, y_pred): + """ + Jaccard / IoU loss + """ + return 1 - iou(y_true, y_pred) + + +def focal_loss(y_true, y_pred): + """ + Focal loss + """ + gamma = 2. + alpha = 4. + epsilon = 1.e-9 + + y_true_c = tf.convert_to_tensor(y_true, tf.float32) + y_pred_c = tf.convert_to_tensor(y_pred, tf.float32) + + model_out = tf.add(y_pred_c, epsilon) + ce = tf.multiply(y_true_c, -tf.math.log(model_out)) + weight = tf.multiply(y_true_c, tf.pow( + tf.subtract(1., model_out), gamma) + ) + fl = tf.multiply(alpha, tf.multiply(weight, ce)) + reduced_fl = tf.reduce_max(fl, axis=-1) + return tf.reduce_mean(reduced_fl) + + +def ssim_loss(y_true, y_pred, smooth=1.e-9): + """ + Structural Similarity Index loss. + Input shape should be Batch x Height x Width x #Classes (BxHxWxN). + Using Mean as reduction type for batch values. + """ + ssim_value = tf.image.ssim(y_true, y_pred, max_val=1) + return K.mean(1 - ssim_value + smooth, axis=0) + + +class DiceCoefficient(tf.keras.metrics.Metric): + """ + Dice coefficient metric. Can be used to calculate dice on probabilities + or on their respective classes + """ + + def __init__(self, post_processed: bool, + classes: int, + name='dice_coef', + **kwargs): + """ + Set post_processed=False if dice coefficient needs to be calculated + on probabilities. Set post_processed=True if probabilities needs to + be first converted/mapped into their respective class. + """ + super(DiceCoefficient, self).__init__(name=name, **kwargs) + self.dice_value = self.add_weight(name='dice_value', initializer='zeros', + aggregation=tf.VariableAggregation.MEAN) # SUM + self.post_processed = post_processed + self.classes = classes + if self.classes == 1: + self.axis = [1, 2, 3] + else: + self.axis = [1, 2, ] + + def update_state(self, y_true, y_pred, sample_weight=None): + if self.post_processed: + if self.classes == 1: + y_true_ = y_true + y_pred_ = tf.where(y_pred > .5, 1.0, 0.0) + else: + y_true_ = tf.math.argmax(y_true, axis=-1, output_type=tf.int32) + y_pred_ = tf.math.argmax(y_pred, axis=-1, output_type=tf.int32) + y_true_ = tf.cast(y_true_, dtype=tf.float32) + y_pred_ = tf.cast(y_pred_, dtype=tf.float32) + else: + y_true_, y_pred_ = y_true, y_pred + + self.dice_value.assign(self.dice_coef(y_true_, y_pred_)) + + def result(self): + return self.dice_value + + def reset_state(self): + self.dice_value.assign(0.0) # reset metric state + + def dice_coef(self, y_true, y_pred, smooth=1.e-9): + """ + Calculate dice coefficient. + Input shape could be either Batch x Height x Width x #Classes (BxHxWxN) + or Batch x Height x Width (BxHxW). + Using Mean as reduction type for batch values. + """ + intersection = K.sum(y_true * y_pred, axis=self.axis) + union = K.sum(y_true, axis=self.axis) + K.sum(y_pred, axis=self.axis) + return K.mean((2. * intersection + smooth) / (union + smooth), axis=0) diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/losses/unet_loss.py b/TensorFlow2/Segmentation/Contrib/UNet3P/losses/unet_loss.py new file mode 100644 index 000000000..24f3c1063 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/losses/unet_loss.py @@ -0,0 +1,19 @@ +""" +UNet 3+ Loss +""" +from .loss import focal_loss, ssim_loss, iou_loss + + +def unet3p_hybrid_loss(y_true, y_pred): + """ + Hybrid loss proposed in + UNET 3+ (https://arxiv.org/ftp/arxiv/papers/2004/2004.08790.pdf) + Hybrid loss for segmentation in three-level hierarchy – pixel, + patch and map-level, which is able to capture both large-scale + and fine structures with clear boundaries. + """ + f_loss = focal_loss(y_true, y_pred) + ms_ssim_loss = ssim_loss(y_true, y_pred) + jacard_loss = iou_loss(y_true, y_pred) + + return f_loss + ms_ssim_loss + jacard_loss diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/models/backbones.py b/TensorFlow2/Segmentation/Contrib/UNet3P/models/backbones.py new file mode 100644 index 000000000..22fd65e84 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/models/backbones.py @@ -0,0 +1,73 @@ +""" +Unet3+ backbones +""" +import tensorflow as tf +import tensorflow.keras as k +from .unet3plus_utils import conv_block + + +def vgg16_backbone(input_layer, ): + """ VGG-16 backbone as encoder for UNet3P """ + + base_model = tf.keras.applications.VGG16( + input_tensor=input_layer, + weights=None, + include_top=False + ) + + # block 1 + e1 = base_model.get_layer("block1_conv2").output # 320, 320, 64 + # block 2 + e2 = base_model.get_layer("block2_conv2").output # 160, 160, 128 + # block 3 + e3 = base_model.get_layer("block3_conv3").output # 80, 80, 256 + # block 4 + e4 = base_model.get_layer("block4_conv3").output # 40, 40, 512 + # block 5 + e5 = base_model.get_layer("block5_conv3").output # 20, 20, 512 + + return [e1, e2, e3, e4, e5] + + +def vgg19_backbone(input_layer, ): + """ VGG-19 backbone as encoder for UNet3P """ + + base_model = tf.keras.applications.VGG19( + input_tensor=input_layer, + weights=None, + include_top=False + ) + + # block 1 + e1 = base_model.get_layer("block1_conv2").output # 320, 320, 64 + # block 2 + e2 = base_model.get_layer("block2_conv2").output # 160, 160, 128 + # block 3 + e3 = base_model.get_layer("block3_conv4").output # 80, 80, 256 + # block 4 + e4 = base_model.get_layer("block4_conv4").output # 40, 40, 512 + # block 5 + e5 = base_model.get_layer("block5_conv4").output # 20, 20, 512 + + return [e1, e2, e3, e4, e5] + + +def unet3plus_backbone(input_layer, filters): + """ UNet3+ own backbone """ + """ Encoder""" + # block 1 + e1 = conv_block(input_layer, filters[0]) # 320*320*64 + # block 2 + e2 = k.layers.MaxPool2D(pool_size=(2, 2))(e1) # 160*160*64 + e2 = conv_block(e2, filters[1]) # 160*160*128 + # block 3 + e3 = k.layers.MaxPool2D(pool_size=(2, 2))(e2) # 80*80*128 + e3 = conv_block(e3, filters[2]) # 80*80*256 + # block 4 + e4 = k.layers.MaxPool2D(pool_size=(2, 2))(e3) # 40*40*256 + e4 = conv_block(e4, filters[3]) # 40*40*512 + # block 5, bottleneck layer + e5 = k.layers.MaxPool2D(pool_size=(2, 2))(e4) # 20*20*512 + e5 = conv_block(e5, filters[4]) # 20*20*1024 + + return [e1, e2, e3, e4, e5] diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/models/model.py b/TensorFlow2/Segmentation/Contrib/UNet3P/models/model.py new file mode 100644 index 000000000..1b2e5a6bd --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/models/model.py @@ -0,0 +1,100 @@ +""" +Returns Unet3+ model +""" +import tensorflow as tf +from omegaconf import DictConfig + +from .backbones import vgg16_backbone, vgg19_backbone, unet3plus_backbone +from .unet3plus import unet3plus +from .unet3plus_deep_supervision import unet3plus_deepsup +from .unet3plus_deep_supervision_cgm import unet3plus_deepsup_cgm + + +def prepare_model(cfg: DictConfig, training=False): + """ + Creates and return model object based on given model type. + """ + + input_shape = [cfg.INPUT.HEIGHT, cfg.INPUT.WIDTH, cfg.INPUT.CHANNELS] + input_layer = tf.keras.layers.Input( + shape=input_shape, + name="input_layer" + ) # 320*320*3 + filters = [64, 128, 256, 512, 1024] + + # create backbone + if cfg.MODEL.BACKBONE.TYPE == "unet3plus": + backbone_layers = unet3plus_backbone( + input_layer, + filters + ) + elif cfg.MODEL.BACKBONE.TYPE == "vgg16": + backbone_layers = vgg16_backbone(input_layer, ) + elif cfg.MODEL.BACKBONE.TYPE == "vgg19": + backbone_layers = vgg19_backbone(input_layer, ) + else: + raise ValueError( + "Wrong backbone type passed." + "\nPlease check config file for possible options." + ) + print(f"Using {cfg.MODEL.BACKBONE.TYPE} as a backbone.") + + if cfg.MODEL.TYPE == "unet3plus": + # training parameter does not matter in this case + outputs, model_name = unet3plus( + backbone_layers, + cfg.OUTPUT.CLASSES, + filters + ) + elif cfg.MODEL.TYPE == "unet3plus_deepsup": + outputs, model_name = unet3plus_deepsup( + backbone_layers, + cfg.OUTPUT.CLASSES, + filters, + training + ) + elif cfg.MODEL.TYPE == "unet3plus_deepsup_cgm": + if cfg.OUTPUT.CLASSES != 1: + raise ValueError( + "UNet3+ with Deep Supervision and Classification Guided Module" + "\nOnly works when model output classes are equal to 1" + ) + outputs, model_name = unet3plus_deepsup_cgm( + backbone_layers, + cfg.OUTPUT.CLASSES, + filters, + training + ) + else: + raise ValueError( + "Wrong model type passed." + "\nPlease check config file for possible options." + ) + + return tf.keras.Model( + inputs=input_layer, + outputs=outputs, + name=model_name + ) + + +if __name__ == "__main__": + """## Test model Compilation,""" + from omegaconf import OmegaConf + + cfg = { + "WORK_DIR": "H:\\Projects\\UNet3P", + "INPUT": {"HEIGHT": 320, "WIDTH": 320, "CHANNELS": 3}, + "OUTPUT": {"CLASSES": 1}, + # available variants are unet3plus, unet3plus_deepsup, unet3plus_deepsup_cgm + "MODEL": {"TYPE": "unet3plus", + # available variants are unet3plus, vgg16, vgg19 + "BACKBONE": {"TYPE": "vgg19", } + } + } + unet_3P = prepare_model(OmegaConf.create(cfg), True) + unet_3P.summary() + + # tf.keras.utils.plot_model(unet_3P, show_layer_names=True, show_shapes=True) + + # unet_3P.save("unet_3P.hdf5") diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus.py b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus.py new file mode 100644 index 000000000..a1036196e --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus.py @@ -0,0 +1,104 @@ +""" +UNet3+ base model +""" +import tensorflow as tf +import tensorflow.keras as k +from .unet3plus_utils import conv_block + + +def unet3plus(encoder_layer, output_channels, filters): + """ UNet3+ base model """ + + """ Encoder """ + e1 = encoder_layer[0] + e2 = encoder_layer[1] + e3 = encoder_layer[2] + e4 = encoder_layer[3] + e5 = encoder_layer[4] + + """ Decoder """ + cat_channels = filters[0] + cat_blocks = len(filters) + upsample_channels = cat_blocks * cat_channels + + """ d4 """ + e1_d4 = k.layers.MaxPool2D(pool_size=(8, 8))(e1) # 320*320*64 --> 40*40*64 + e1_d4 = conv_block(e1_d4, cat_channels, n=1) # 320*320*64 --> 40*40*64 + + e2_d4 = k.layers.MaxPool2D(pool_size=(4, 4))(e2) # 160*160*128 --> 40*40*128 + e2_d4 = conv_block(e2_d4, cat_channels, n=1) # 160*160*128 --> 40*40*64 + + e3_d4 = k.layers.MaxPool2D(pool_size=(2, 2))(e3) # 80*80*256 --> 40*40*256 + e3_d4 = conv_block(e3_d4, cat_channels, n=1) # 80*80*256 --> 40*40*64 + + e4_d4 = conv_block(e4, cat_channels, n=1) # 40*40*512 --> 40*40*64 + + e5_d4 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(e5) # 80*80*256 --> 40*40*256 + e5_d4 = conv_block(e5_d4, cat_channels, n=1) # 20*20*1024 --> 20*20*64 + + d4 = k.layers.concatenate([e1_d4, e2_d4, e3_d4, e4_d4, e5_d4]) + d4 = conv_block(d4, upsample_channels, n=1) # 40*40*320 --> 40*40*320 + + """ d3 """ + e1_d3 = k.layers.MaxPool2D(pool_size=(4, 4))(e1) # 320*320*64 --> 80*80*64 + e1_d3 = conv_block(e1_d3, cat_channels, n=1) # 80*80*64 --> 80*80*64 + + e2_d3 = k.layers.MaxPool2D(pool_size=(2, 2))(e2) # 160*160*256 --> 80*80*256 + e2_d3 = conv_block(e2_d3, cat_channels, n=1) # 80*80*256 --> 80*80*64 + + e3_d3 = conv_block(e3, cat_channels, n=1) # 80*80*512 --> 80*80*64 + + e4_d3 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d4) # 40*40*320 --> 80*80*320 + e4_d3 = conv_block(e4_d3, cat_channels, n=1) # 80*80*320 --> 80*80*64 + + e5_d3 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(e5) # 20*20*320 --> 80*80*320 + e5_d3 = conv_block(e5_d3, cat_channels, n=1) # 80*80*320 --> 80*80*64 + + d3 = k.layers.concatenate([e1_d3, e2_d3, e3_d3, e4_d3, e5_d3]) + d3 = conv_block(d3, upsample_channels, n=1) # 80*80*320 --> 80*80*320 + + """ d2 """ + e1_d2 = k.layers.MaxPool2D(pool_size=(2, 2))(e1) # 320*320*64 --> 160*160*64 + e1_d2 = conv_block(e1_d2, cat_channels, n=1) # 160*160*64 --> 160*160*64 + + e2_d2 = conv_block(e2, cat_channels, n=1) # 160*160*256 --> 160*160*64 + + d3_d2 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d3) # 80*80*320 --> 160*160*320 + d3_d2 = conv_block(d3_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d4_d2 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d4) # 40*40*320 --> 160*160*320 + d4_d2 = conv_block(d4_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + e5_d2 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(e5) # 20*20*320 --> 160*160*320 + e5_d2 = conv_block(e5_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d2 = k.layers.concatenate([e1_d2, e2_d2, d3_d2, d4_d2, e5_d2]) + d2 = conv_block(d2, upsample_channels, n=1) # 160*160*320 --> 160*160*320 + + """ d1 """ + e1_d1 = conv_block(e1, cat_channels, n=1) # 320*320*64 --> 320*320*64 + + d2_d1 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d2) # 160*160*320 --> 320*320*320 + d2_d1 = conv_block(d2_d1, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d3_d1 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d3) # 80*80*320 --> 320*320*320 + d3_d1 = conv_block(d3_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + d4_d1 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(d4) # 40*40*320 --> 320*320*320 + d4_d1 = conv_block(d4_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + e5_d1 = k.layers.UpSampling2D(size=(16, 16), interpolation='bilinear')(e5) # 20*20*320 --> 320*320*320 + e5_d1 = conv_block(e5_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + d1 = k.layers.concatenate([e1_d1, d2_d1, d3_d1, d4_d1, e5_d1, ]) + d1 = conv_block(d1, upsample_channels, n=1) # 320*320*320 --> 320*320*320 + + # last layer does not have batchnorm and relu + d = conv_block(d1, output_channels, n=1, is_bn=False, is_relu=False) + + if output_channels == 1: + output = k.layers.Activation('sigmoid', dtype='float32')(d) + else: + output = k.layers.Activation('softmax', dtype='float32')(d) + + return output, 'UNet_3Plus' diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_deep_supervision.py b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_deep_supervision.py new file mode 100644 index 000000000..0766ed820 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_deep_supervision.py @@ -0,0 +1,132 @@ +""" +UNet3+ with Deep Supervision +""" +import tensorflow as tf +import tensorflow.keras as k +from .unet3plus_utils import conv_block + + +def unet3plus_deepsup(encoder_layer, output_channels, filters, training=False): + """ UNet_3Plus with Deep Supervision """ + + """ Encoder """ + e1 = encoder_layer[0] + e2 = encoder_layer[1] + e3 = encoder_layer[2] + e4 = encoder_layer[3] + e5 = encoder_layer[4] + + """ Decoder """ + cat_channels = filters[0] + cat_blocks = len(filters) + upsample_channels = cat_blocks * cat_channels + + """ d4 """ + e1_d4 = k.layers.MaxPool2D(pool_size=(8, 8))(e1) # 320*320*64 --> 40*40*64 + e1_d4 = conv_block(e1_d4, cat_channels, n=1) # 320*320*64 --> 40*40*64 + + e2_d4 = k.layers.MaxPool2D(pool_size=(4, 4))(e2) # 160*160*128 --> 40*40*128 + e2_d4 = conv_block(e2_d4, cat_channels, n=1) # 160*160*128 --> 40*40*64 + + e3_d4 = k.layers.MaxPool2D(pool_size=(2, 2))(e3) # 80*80*256 --> 40*40*256 + e3_d4 = conv_block(e3_d4, cat_channels, n=1) # 80*80*256 --> 40*40*64 + + e4_d4 = conv_block(e4, cat_channels, n=1) # 40*40*512 --> 40*40*64 + + e5_d4 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(e5) # 80*80*256 --> 40*40*256 + e5_d4 = conv_block(e5_d4, cat_channels, n=1) # 20*20*1024 --> 20*20*64 + + d4 = k.layers.concatenate([e1_d4, e2_d4, e3_d4, e4_d4, e5_d4]) + d4 = conv_block(d4, upsample_channels, n=1) # 40*40*320 --> 40*40*320 + + """ d3 """ + e1_d3 = k.layers.MaxPool2D(pool_size=(4, 4))(e1) # 320*320*64 --> 80*80*64 + e1_d3 = conv_block(e1_d3, cat_channels, n=1) # 80*80*64 --> 80*80*64 + + e2_d3 = k.layers.MaxPool2D(pool_size=(2, 2))(e2) # 160*160*256 --> 80*80*256 + e2_d3 = conv_block(e2_d3, cat_channels, n=1) # 80*80*256 --> 80*80*64 + + e3_d3 = conv_block(e3, cat_channels, n=1) # 80*80*512 --> 80*80*64 + + e4_d3 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d4) # 40*40*320 --> 80*80*320 + e4_d3 = conv_block(e4_d3, cat_channels, n=1) # 80*80*320 --> 80*80*64 + + e5_d3 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(e5) # 20*20*320 --> 80*80*320 + e5_d3 = conv_block(e5_d3, cat_channels, n=1) # 80*80*320 --> 80*80*64 + + d3 = k.layers.concatenate([e1_d3, e2_d3, e3_d3, e4_d3, e5_d3]) + d3 = conv_block(d3, upsample_channels, n=1) # 80*80*320 --> 80*80*320 + + """ d2 """ + e1_d2 = k.layers.MaxPool2D(pool_size=(2, 2))(e1) # 320*320*64 --> 160*160*64 + e1_d2 = conv_block(e1_d2, cat_channels, n=1) # 160*160*64 --> 160*160*64 + + e2_d2 = conv_block(e2, cat_channels, n=1) # 160*160*256 --> 160*160*64 + + d3_d2 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d3) # 80*80*320 --> 160*160*320 + d3_d2 = conv_block(d3_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d4_d2 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d4) # 40*40*320 --> 160*160*320 + d4_d2 = conv_block(d4_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + e5_d2 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(e5) # 20*20*320 --> 160*160*320 + e5_d2 = conv_block(e5_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d2 = k.layers.concatenate([e1_d2, e2_d2, d3_d2, d4_d2, e5_d2]) + d2 = conv_block(d2, upsample_channels, n=1) # 160*160*320 --> 160*160*320 + + """ d1 """ + e1_d1 = conv_block(e1, cat_channels, n=1) # 320*320*64 --> 320*320*64 + + d2_d1 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d2) # 160*160*320 --> 320*320*320 + d2_d1 = conv_block(d2_d1, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d3_d1 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d3) # 80*80*320 --> 320*320*320 + d3_d1 = conv_block(d3_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + d4_d1 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(d4) # 40*40*320 --> 320*320*320 + d4_d1 = conv_block(d4_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + e5_d1 = k.layers.UpSampling2D(size=(16, 16), interpolation='bilinear')(e5) # 20*20*320 --> 320*320*320 + e5_d1 = conv_block(e5_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + d1 = k.layers.concatenate([e1_d1, d2_d1, d3_d1, d4_d1, e5_d1, ]) + d1 = conv_block(d1, upsample_channels, n=1) # 320*320*320 --> 320*320*320 + + # last layer does not have batch norm and relu + d1 = conv_block(d1, output_channels, n=1, is_bn=False, is_relu=False) + + if output_channels == 1: + d1 = k.layers.Activation('sigmoid', dtype='float32')(d1) + else: + # d1 = k.activations.softmax(d1) + d1 = k.layers.Activation('softmax', dtype='float32')(d1) + + """ Deep Supervision Part""" + if training: + d2 = conv_block(d2, output_channels, n=1, is_bn=False, is_relu=False) + d3 = conv_block(d3, output_channels, n=1, is_bn=False, is_relu=False) + d4 = conv_block(d4, output_channels, n=1, is_bn=False, is_relu=False) + e5 = conv_block(e5, output_channels, n=1, is_bn=False, is_relu=False) + + # d1 = no need for up sampling + d2 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d2) + d3 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d3) + d4 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(d4) + e5 = k.layers.UpSampling2D(size=(16, 16), interpolation='bilinear')(e5) + + if output_channels == 1: + d2 = k.layers.Activation('sigmoid', dtype='float32')(d2) + d3 = k.layers.Activation('sigmoid', dtype='float32')(d3) + d4 = k.layers.Activation('sigmoid', dtype='float32')(d4) + e5 = k.layers.Activation('sigmoid', dtype='float32')(e5) + else: + d2 = k.layers.Activation('softmax', dtype='float32')(d2) + d3 = k.layers.Activation('softmax', dtype='float32')(d3) + d4 = k.layers.Activation('softmax', dtype='float32')(d4) + e5 = k.layers.Activation('softmax', dtype='float32')(e5) + + if training: + return [d1, d2, d3, d4, e5], 'UNet3Plus_DeepSup' + else: + return [d1, ], 'UNet3Plus_DeepSup' diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_deep_supervision_cgm.py b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_deep_supervision_cgm.py new file mode 100644 index 000000000..110dd81d8 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_deep_supervision_cgm.py @@ -0,0 +1,138 @@ +""" +UNet_3Plus with Deep Supervision and Classification Guided Module +""" +import tensorflow as tf +import tensorflow.keras as k +from .unet3plus_utils import conv_block, dot_product + + +def unet3plus_deepsup_cgm(encoder_layer, output_channels, filters, training=False): + """ UNet_3Plus with Deep Supervision and Classification Guided Module """ + + """ Encoder """ + e1 = encoder_layer[0] + e2 = encoder_layer[1] + e3 = encoder_layer[2] + e4 = encoder_layer[3] + e5 = encoder_layer[4] + + """ Classification Guided Module. Part 1""" + cls = k.layers.Dropout(rate=0.5)(e5) + cls = k.layers.Conv2D(2, kernel_size=(1, 1), padding="same", strides=(1, 1))(cls) + cls = k.layers.GlobalMaxPooling2D()(cls) + cls = k.layers.Activation('sigmoid', dtype='float32')(cls) + cls = tf.argmax(cls, axis=-1) + cls = cls[..., tf.newaxis] + cls = tf.cast(cls, dtype=tf.float32, ) + + """ Decoder """ + cat_channels = filters[0] + cat_blocks = len(filters) + upsample_channels = cat_blocks * cat_channels + + """ d4 """ + e1_d4 = k.layers.MaxPool2D(pool_size=(8, 8))(e1) # 320*320*64 --> 40*40*64 + e1_d4 = conv_block(e1_d4, cat_channels, n=1) # 320*320*64 --> 40*40*64 + + e2_d4 = k.layers.MaxPool2D(pool_size=(4, 4))(e2) # 160*160*128 --> 40*40*128 + e2_d4 = conv_block(e2_d4, cat_channels, n=1) # 160*160*128 --> 40*40*64 + + e3_d4 = k.layers.MaxPool2D(pool_size=(2, 2))(e3) # 80*80*256 --> 40*40*256 + e3_d4 = conv_block(e3_d4, cat_channels, n=1) # 80*80*256 --> 40*40*64 + + e4_d4 = conv_block(e4, cat_channels, n=1) # 40*40*512 --> 40*40*64 + + e5_d4 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(e5) # 80*80*256 --> 40*40*256 + e5_d4 = conv_block(e5_d4, cat_channels, n=1) # 20*20*1024 --> 20*20*64 + + d4 = k.layers.concatenate([e1_d4, e2_d4, e3_d4, e4_d4, e5_d4]) + d4 = conv_block(d4, upsample_channels, n=1) # 40*40*320 --> 40*40*320 + + """ d3 """ + e1_d3 = k.layers.MaxPool2D(pool_size=(4, 4))(e1) # 320*320*64 --> 80*80*64 + e1_d3 = conv_block(e1_d3, cat_channels, n=1) # 80*80*64 --> 80*80*64 + + e2_d3 = k.layers.MaxPool2D(pool_size=(2, 2))(e2) # 160*160*256 --> 80*80*256 + e2_d3 = conv_block(e2_d3, cat_channels, n=1) # 80*80*256 --> 80*80*64 + + e3_d3 = conv_block(e3, cat_channels, n=1) # 80*80*512 --> 80*80*64 + + e4_d3 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d4) # 40*40*320 --> 80*80*320 + e4_d3 = conv_block(e4_d3, cat_channels, n=1) # 80*80*320 --> 80*80*64 + + e5_d3 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(e5) # 20*20*320 --> 80*80*320 + e5_d3 = conv_block(e5_d3, cat_channels, n=1) # 80*80*320 --> 80*80*64 + + d3 = k.layers.concatenate([e1_d3, e2_d3, e3_d3, e4_d3, e5_d3]) + d3 = conv_block(d3, upsample_channels, n=1) # 80*80*320 --> 80*80*320 + + """ d2 """ + e1_d2 = k.layers.MaxPool2D(pool_size=(2, 2))(e1) # 320*320*64 --> 160*160*64 + e1_d2 = conv_block(e1_d2, cat_channels, n=1) # 160*160*64 --> 160*160*64 + + e2_d2 = conv_block(e2, cat_channels, n=1) # 160*160*256 --> 160*160*64 + + d3_d2 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d3) # 80*80*320 --> 160*160*320 + d3_d2 = conv_block(d3_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d4_d2 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d4) # 40*40*320 --> 160*160*320 + d4_d2 = conv_block(d4_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + e5_d2 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(e5) # 20*20*320 --> 160*160*320 + e5_d2 = conv_block(e5_d2, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d2 = k.layers.concatenate([e1_d2, e2_d2, d3_d2, d4_d2, e5_d2]) + d2 = conv_block(d2, upsample_channels, n=1) # 160*160*320 --> 160*160*320 + + """ d1 """ + e1_d1 = conv_block(e1, cat_channels, n=1) # 320*320*64 --> 320*320*64 + + d2_d1 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d2) # 160*160*320 --> 320*320*320 + d2_d1 = conv_block(d2_d1, cat_channels, n=1) # 160*160*320 --> 160*160*64 + + d3_d1 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d3) # 80*80*320 --> 320*320*320 + d3_d1 = conv_block(d3_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + d4_d1 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(d4) # 40*40*320 --> 320*320*320 + d4_d1 = conv_block(d4_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + e5_d1 = k.layers.UpSampling2D(size=(16, 16), interpolation='bilinear')(e5) # 20*20*320 --> 320*320*320 + e5_d1 = conv_block(e5_d1, cat_channels, n=1) # 320*320*320 --> 320*320*64 + + d1 = k.layers.concatenate([e1_d1, d2_d1, d3_d1, d4_d1, e5_d1, ]) + d1 = conv_block(d1, upsample_channels, n=1) # 320*320*320 --> 320*320*320 + + """ Deep Supervision Part""" + # last layer does not have batch norm and relu + d1 = conv_block(d1, output_channels, n=1, is_bn=False, is_relu=False) + if training: + d2 = conv_block(d2, output_channels, n=1, is_bn=False, is_relu=False) + d3 = conv_block(d3, output_channels, n=1, is_bn=False, is_relu=False) + d4 = conv_block(d4, output_channels, n=1, is_bn=False, is_relu=False) + e5 = conv_block(e5, output_channels, n=1, is_bn=False, is_relu=False) + + # d1 = no need for up sampling + d2 = k.layers.UpSampling2D(size=(2, 2), interpolation='bilinear')(d2) + d3 = k.layers.UpSampling2D(size=(4, 4), interpolation='bilinear')(d3) + d4 = k.layers.UpSampling2D(size=(8, 8), interpolation='bilinear')(d4) + e5 = k.layers.UpSampling2D(size=(16, 16), interpolation='bilinear')(e5) + + """ Classification Guided Module. Part 2""" + d1 = dot_product(d1, cls) + d1 = k.layers.Activation('sigmoid', dtype='float32')(d1) + + if training: + d2 = dot_product(d2, cls) + d3 = dot_product(d3, cls) + d4 = dot_product(d4, cls) + e5 = dot_product(e5, cls) + + d2 = k.layers.Activation('sigmoid', dtype='float32')(d2) + d3 = k.layers.Activation('sigmoid', dtype='float32')(d3) + d4 = k.layers.Activation('sigmoid', dtype='float32')(d4) + e5 = k.layers.Activation('sigmoid', dtype='float32')(e5) + + if training: + return [d1, d2, d3, d4, e5, cls], 'UNet3Plus_DeepSup_CGM' + else: + return [d1, ], 'UNet3Plus_DeepSup_CGM' diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_utils.py b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_utils.py new file mode 100644 index 000000000..e002a3c89 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/models/unet3plus_utils.py @@ -0,0 +1,31 @@ +""" +Utility functions for Unet3+ models +""" +import tensorflow as tf +import tensorflow.keras as k + + +def conv_block(x, kernels, kernel_size=(3, 3), strides=(1, 1), padding='same', + is_bn=True, is_relu=True, n=2): + """ Custom function for conv2d: + Apply 3*3 convolutions with BN and relu. + """ + for i in range(1, n + 1): + x = k.layers.Conv2D(filters=kernels, kernel_size=kernel_size, + padding=padding, strides=strides, + kernel_regularizer=tf.keras.regularizers.l2(1e-4), + kernel_initializer=k.initializers.he_normal(seed=5))(x) + if is_bn: + x = k.layers.BatchNormalization()(x) + if is_relu: + x = k.activations.relu(x) + + return x + + +def dot_product(seg, cls): + b, h, w, n = k.backend.int_shape(seg) + seg = tf.reshape(seg, [-1, h * w, n]) + final = tf.einsum("ijk,ik->ijk", seg, cls) + final = tf.reshape(final, [-1, h, w, n]) + return final diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/predict.ipynb b/TensorFlow2/Segmentation/Contrib/UNet3P/predict.ipynb new file mode 100644 index 000000000..599ff0f89 --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/predict.ipynb @@ -0,0 +1,247 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "570c0575", + "metadata": {}, + "source": [ + "# Visualization Script" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "fc14ebac", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-02-20 07:22:21.247783: I tensorflow/core/platform/cpu_feature_guard.cc:194] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: SSE3 SSE4.1 SSE4.2 AVX\n", + "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n" + ] + } + ], + "source": [ + "# Imports\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "%matplotlib inline\n", + "\n", + "import hydra\n", + "from hydra import initialize, compose\n", + "from hydra.core.hydra_config import HydraConfig\n", + "\n", + "from predict import predict" + ] + }, + { + "cell_type": "markdown", + "id": "2115b6b7", + "metadata": {}, + "source": [ + "## Read Config File" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "065dc666-417f-4cd9-b70c-52d8907696b8", + "metadata": {}, + "outputs": [], + "source": [ + "# clear previous hydra instances\n", + "hydra.core.global_hydra.GlobalHydra.instance().clear()\n", + "\n", + "# configs/config.yaml\n", + "initialize(version_base=None, config_path=\"configs\")\n", + "cfg = compose(config_name=\"config\", return_hydra_config=True)\n", + "HydraConfig().cfg = cfg" + ] + }, + { + "cell_type": "markdown", + "id": "3f51818e", + "metadata": {}, + "source": [ + "For visualization two options are available\n", + "1: Visualize from directory\n", + "2: Visualize from list\n", + "In both cases mask is optional\n", + "You can also override these settings through command line and call predict.py" + ] + }, + { + "cell_type": "markdown", + "id": "ce64141b", + "metadata": {}, + "source": [ + "## 1: Visualize from directory\n", + "In case of visualization from directory, it's going to make prediction and show all images from given directory.\n", + "Override the validation data paths and make sure the directory paths are relative to the project base/root path" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "210cdc87", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + } + }, + "outputs": [], + "source": [ + "# e.g. to visualize validation data\n", + "# images_paths = \"/data/val/images\"\n", + "# mask_paths = \"/data/val/mask\"" + ] + }, + { + "cell_type": "markdown", + "id": "5f846db6", + "metadata": {}, + "source": [ + "## 2: Visualize from list\n", + "In case of visualization from list, each list element should contain absolute path of image/mask." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "b88515e2-620e-4269-9e4c-4b1ddb9b48df", + "metadata": {}, + "outputs": [], + "source": [ + "# e.g. to visualize two images with their corresponding mask\n", + "images_paths = [\n", + " \"/workspace/unet3p/data/val/images/image_0_48.png\",\n", + " \"/workspace/unet3p/data/val/images/image_0_21.png\",\n", + "]\n", + "mask_paths = [\n", + " \"/workspace/unet3p/data/val/mask/mask_0_48.png\",\n", + " \"/workspace/unet3p/data/val/mask/mask_0_21.png\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ad2e8191-c1d1-4994-bef8-cc8a36062150", + "metadata": {}, + "outputs": [], + "source": [ + "# override given settings\n", + "cfg.DATASET.VAL.IMAGES_PATH = images_paths\n", + "cfg.DATASET.VAL.MASK_PATH = mask_paths" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6a77869e", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + } + }, + "outputs": [], + "source": [ + "# In both cases if mask is not available just set the mask path to None\n", + "# cfg.DATASET.VAL.MASK_PATH = None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28e38f6d-6eee-4c7c-b209-f700598723fa", + "metadata": {}, + "outputs": [], + "source": [ + "# For custom data visualization set SHOW_CENTER_CHANNEL_IMAGE=False. This should set True for only UNet3+ LiTS data.\n", + "cfg.SHOW_CENTER_CHANNEL_IMAGE=True" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ffb762af-e67b-41e5-92ff-0983a1396762", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using vgg19 as a backbone.\n" + ] + }, + { + "data": { + "image/png": "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rxRFUZT/+7//UzQajdLb28vfVaPRKH9usnn3lltuUTQajdLX16coyq65G4Dyr//6r+86ho6ODp6bf/zjHysajUb5/ve//55jF94fkjou7DNf+tKXGn4/5ZRTsGPHjgnbXXjhhWhpaeHfTzjhBJx44on4wx/+sN/H+G6o3R51Oh0WL14MRVHw+c9/nl93u92YPXt2w3npdDo2rqjX64jH46hWq1i8eDHWrl3L261evRoGgwFXXnklv6bVanH11Vc3jCMej+Ppp5/Gxz/+cWQyGcRiMcRiMYyPj2PFihXYunUrhoaGpvz8BUGYfkwmEy6//PL3/fn7778fp5xyCjweD88dsVgMy5cvR61Ww/PPP7/X+7rkkkvw0EMPoVwu44EHHoBOp9tjNo06ylypVDA+Po6enh643e6GedDtdmPDhg3YunXrex7/mWeewYoVK7Bs2TI89NBDMJlMez12QRD2P8uXL0cgEEBbWxtWrVoFu92Ohx9+uOE7HoAJmY33338/XC4XzjzzzIZ5atGiRbDb7Vx69+STT6JcLuPLX/5yQ0r3V7/61fcc2+uvv46dO3fiq1/9Ktxud8N76n3tiQMxxt3xeDw4++yz8Zvf/AbAriyik046CR0dHZNur553c7kcYrEYTjrpJCiKgtdff523MRqNePbZZyekvE/Gv/zLv+ArX/kKbr31VvzDP/zDPp+DsHdI6riwT5jNZq6XJjwez6R/1JO1jZk1axZ++9vf7rfx7Q3t7e0Nv7tcLpjNZvj9/gmvj4+PN7x2991347bbbsOmTZtQqVT49a6uLv53X18fQqHQBGOjnp6eht+3bdsGRVHwne98B9/5zncmHWskEpnwPzJBEA59Wlpa9tk1V83WrVvx5ptvTpiPiUgkstf7WrVqFa677jr88Y9/xL333ouVK1fC4XBMum2hUMAtt9yCO++8E0NDQ1AUhd9LpVL87+9973u44IILMGvWLCxYsABnn302PvOZz0wo+SkWizjvvPOwaNEi/Pa3v4VeL19LBOFg42c/+xlmzZoFvV6PpqYmzJ49G1ptY6xOr9ejtbW14bWtW7cilUpNWoYCvDNP9fX1AZj4vTEQCMDj8bzr2CiNfbLa5r3hQIxxMi655BJ85jOfQX9/Px555BH8y7/8yx637e/vx3e/+108+uijE75v07xrMplw66234utf/zqamprw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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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xjfwqle96rfaR0VRjm+y2SwuuugiXHbZZXjDG95wRNdEYH8F/Oyzz8bc3Bze+ta3YtWqVbjzzjvxgQ98AAsLC/jUpz71tJ7nda97neRf8Mvz1772NZx33nno6+s75P6/+MUvcOedd+Kyyy7DyMgIpqen8bnPfQ7nnHMOfv3rX0tV/iMf+QiuvvpqvPnNb8Zpp50GwzBw77334v7778cFF1xw2G35xS9+gV27duHUU0/Fd77zHfh8viM6JoqiPDPs2bMHAJBIJOS2druNXbt24cwzz8QnP/lJuRa89a1vxXXXXYcrr7wSf/qnf4qpqSn88z//M375y1/ijjvugMvlAgB86EMfwsc//nFcfPHFuPjii3H//ffjpS99KZrN5m/cnptvvhmXXHIJBgcH8e53vxsDAwN49NFH8b3vfQ/vfve78da3vhXz8/OHbeN5prbRyute9zq8+93vRrlcRjAYRLvdxg033ID3vve9h7WN33DDDahWq3j729+ORCKBe+65B9deey1mZ2dxww03yP0uvfRSPPLII3jXu96FsbExpNNp3HzzzZiZmZHi1cF84QtfwNve9jb81V/9FT7+8Y8f0X4oTwNTUQ7DF7/4RROA+Ytf/EJuu/zyy00A5l//9V/33Pd5z3ueuWPHDvl9amrKBGD6fD5zdnZWbr/77rtNAOaf/dmfyW1nn322efbZZx/y+pdffrm5evVq+X15edkEYH74wx9+Wtt/2223mQDMG264QW778Ic/bAIw/+RP/kRua7fb5sjIiGmz2cy//du/ldvz+bzp8/nMyy+/vOe+jUaj53Xy+bzZ399vvvGNb5TbvvGNb5gAzE996lNyW6fTMc8991wTgPnFL35Rbj/vvPPMrVu3mvV6XW7rdrvmGWecYa5fv/5p7auiKMcv73jHO8yD/1d79tlnmwDMz3/+84fc/8muc6tXr+65Hn3sYx8zA4GA+fjjj/fc7/3vf7/pcDjMmZmZp9yus88+29y8ebNpmqZ56qmnmm9605tM09x/TXO73eaXvvSlw15Hq9XqIc911113mQDML3/5y3Lb9u3bzZe97GVPuQ2XX365GQgETNM0zZ/97GdmOBw2X/ayl/VcDxVFOXbwu+Att9xiLi8vm/v27TP/4z/+w0wkEj3f8fj98P3vf3/P43/605+aAMzrr7++5/abbrqp5/Z0Om263W7zZS97mdntduV+f/VXf2UC6Ln28bp02223maa5/7vZ+Pi4uXr1ajOfz/e8jvW5DnctPlrb+GQAMN/xjneYuVzOdLvd5le+8hXTNE3z+9//vmmz2czp6Wn5rrq8vCyPO9x19+qrrzZtNpu5d+9e0zT3X7sBmH//93//lNuwevVquTZ/+tOfNm02m/mxj33sN2678tuh1nHliHnb297W8/uLX/xiPPHEE4fc75WvfCWGh4fl99NOOw07d+7ED37wg6O+jU+FNe3R4XDg1FNPhWmaeNOb3iS3R6NRnHTSST375XA4JLii2+0il8uh3W7j1FNPxf333y/3u+mmm+ByufCWt7xFbrPb7XjHO97Rsx25XA633norXvOa16BUKiGTySCTySCbzWLXrl2YmJjA3Nzciu+/oijHHo/HgyuvvPK3fvwNN9yAF7/4xYjFYnLtyGQyOP/889HpdPA///M/T/u5Xve61+Gb3/wmms0mbrzxRjgcjid101irzK1WC9lsFuvWrUM0Gu25DkajUTzyyCOYmJj4ja9/2223YdeuXTjvvPPwzW9+Ex6P52lvu6IoR5/zzz8fqVQKo6OjuOyyyxAMBvGtb32r5zsegEOcjTfccAMikQguuOCCnuvUjh07EAwGpfXulltuQbPZxLve9a4eS/d73vOe37htv/zlLzE1NYX3vOc9iEajPX+zPteT8Uxs48HEYjFceOGF+Pd//3cA+11EZ5xxBlavXn3Y+1uvu5VKBZlMBmeccQZM08Qvf/lLuY/b7cbtt99+iOX9cPzd3/0d3v3ud+MTn/gE/s//+T9HvA/K00Ot48oR4fV6pV+axGKxw36oDzc2ZsOGDfj6179+1Lbv6bBq1aqe3yORCLxeL5LJ5CG3Z7PZntu+9KUv4ZprrsHu3bvRarXk9vHxcfn33r17MTg4eEiw0bp163p+n5ychGma+OAHP4gPfvCDh93WdDp9yP/IFEU58RkeHj7i1FwrExMTePDBBw+5HpN0Ov20n+uyyy7DVVddhR/+8Ie4/vrrcckllyAUCh32vrVaDVdffTW++MUvYm5uDqZpyt+KxaL8+6//+q/xile8Ahs2bMCWLVtw4YUX4o/+6I8Oafmp1+t42ctehh07duDrX/86nE79WqIoxxuf+cxnsGHDBjidTvT39+Okk06C3d5bq3M6nRgZGem5bWJiAsVi8bBtKMCB69TevXsBHPq9MZVKIRaLPeW20cZ+uN7mp8MzsY2H43Wvex3+6I/+CDMzM/j2t7+Nv/u7v3vS+87MzOBDH/oQvvvd7x7yfZvXXY/Hg0984hN43/veh/7+frzwhS/EJZdcgj/+4z/GwMBAz2N+8pOf4Pvf/z7+8i//UvuyjzL6fzTliHA4HCv6fDabreeLGrGGq600h9uHJ9sv67Z99atfxRVXXIFXvvKV+PM//3P09fXB4XDg6quvlgv9kcDwoauuugq7du067H0OFueKojw7ONL+44Ovid1uFxdccAH+4i/+4rD337Bhw9N+7sHBQZxzzjm45pprcMcddzxl4u273vUufPGLX8R73vMenH766YhEIrDZbLjssst6AtXOOuss7NmzB9/5znfw3//93/jXf/1X/OM//iM+//nP97iKPB4PLr74YnznO9/BTTfdhEsuueRpb7eiKM8Mp512mqSOPxkej+cQ8d3tdtHX14frr7/+sI95soXCZ5JjtY2/93u/B4/Hg8svvxyNRuOw4ZPA/mv/BRdcgFwuh7/8y7/Exo0bEQgEMDc3hyuuuKLnuvue97wHL3/5y/Htb38bP/rRj/DBD34QV199NW699VY873nPk/tt3rwZhUIBX/nKV/DWt761p1ikrCwqtJWjxuEsg48//nhPIEMsFjus7Zwrh+Tp2H+ONjfeeCPWrFmDb37zmz3b8+EPf7jnfqtXr8Ztt912yLieycnJnvutWbMGAOByuXD++ecfxS1XFOVEIRaLoVAo9NzWbDaxsLDQc9vatWtRLpdX7Nrxute9Dm9+85sRjUZx8cUXP+n9brzxRlx++eU9Uxnq9foh2wwA8XgcV155Ja688kqUy2WcddZZ+MhHPtIjtG02G66//nq84hWvwB/8wR/ghz/84WEnUSiKcuKxdu1a3HLLLXjRi170lIuLtExPTEzIdyMAWF5e/o026LVr1wIAHn744ae8Hj7Z98hnYhsPh8/nwytf+Up89atfxUUXXXSIq5I89NBDePzxx/GlL30Jf/zHfyy3P9kEh7Vr1+J973sf3ve+92FiYgKnnHIKrrnmGnz1q1+V+ySTSdx4440488wzcd555+FnP/sZhoaGjngflN+M9mgrR41vf/vbPT3G99xzD+6++25cdNFFctvatWuxe/duLC8vy20PPPAA7rjjjp7nomA93Je5ZwpWva1V7rvvvht33XVXz/127dqFVquF//f//p/c1u12ZbQE6evrwznnnIN/+Zd/OeRLNICeY6IoynODtWvXHtJf/YUvfOGQivZrXvMa3HXXXfjRj350yHMUCgW02+0jet3f//3fx4c//GF89rOffUpLu8PhOMSFdO211x6yfQe33QSDQaxbtw6NRuOQ53S73fjmN7+JF7zgBTKxQVGUE5/XvOY16HQ6+NjHPnbI39rttnynO//88+FyuXDttdf2XF+ezvSE5z//+RgfH8enPvWpQ74jWp+LM70Pvs8zsY1PxlVXXYUPf/jDT9o+CBz+u6dpmjK6jFSr1UMSy9euXYtQKHTY6+7IyAhuueUW1Go1XHDBBYdcs5WVQSvaylFj3bp1OPPMM/H2t78djUYDn/rUp5BIJHqsjm984xvxD//wD9i1axfe9KY3IZ1O4/Of/zw2b94MwzDkfj6fD5s2bcJ//ud/YsOGDYjH49iyZctv3ZPz23DJJZfgm9/8Jl71qlfhZS97GaampvD5z38emzZt6pn3+spXvhKnnXYa3ve+92FychIbN27Ed7/7XeRyOQC9q6qf+cxncOaZZ2Lr1q14y1vegjVr1mBpaQl33XUXZmdn8cADDzxj+6coyrHnzW9+M972trfh0ksvxQUXXIAHHngAP/rRjw6pdvz5n/85vvvd7+KSSy7BFVdcgR07dqBSqeChhx7CjTfeiOnp6SetkByOSCRy2PndB3PJJZfgK1/5CiKRCDZt2oS77roLt9xyS8+YHwDYtGkTzjnnHOzYsQPxeBz33nsvbrzxRrzzne887PP6fD5873vfw7nnnouLLroIP/nJT57R67uiKCvP2Wefjbe+9a24+uqr8atf/QovfelL4XK5MDExgRtuuAGf/vSn8fu///tIpVK46qqrcPXVV+OSSy7BxRdfjF/+8pf44Q9/+BuvY3a7HZ/73Ofw8pe/HKeccgquvPJKDA4OYvfu3XjkkUdkMXLHjh0AgD/90z/Frl274HA4cNlllz0j2/hkbN++Hdu3b3/K+2zcuBFr167FVVddhbm5OYTDYXzjG984pIr++OOP47zzzsNrXvMabNq0CU6nE9/61rewtLSEyy677LDPvW7dOvz3f/83zjnnHOzatQu33norwuHwb7UvypNwTLLOleOeJxvvxVEsVjiKgHC819///d+b11xz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X/rSl6yvfOUr1iuvvGKdOHHC+sQnPmE5nU7r6NGjlmXpMX096P3x4tF75Oaj98jNR++Pbx69P148en/cfPT+uPlcyffHq05o33333daDDz4o/x4Oh9bMzIz18MMPX8atujq48CY5Go2sVCpl/ef//J/la5VKxXK73dZf/MVfWJZlWcePH7cAWN/5znfkOY8++qhls9ms9fX1t2zbr2RyuZwFwHriiScsyzp3DJ1Op/VXf/VX8pyXXnrJAmAdOHDAsqxz/3lNTExYmUxGnvOZz3zGCoVCVrfbfWt34AomGo1af/7nf67H9HWi98c3h94jLw16j7w06P3x4tD745tD74+XBr0/XhqulPvjVWUd7/V6eP7553HffffJ1yYmJnDffffhwIEDl3HLrk7Onj2LTCYzdjzD4TDuueceOZ4HDhxAJBLBnXfeKc+57777MDExgWeeeeYt3+YrkWq1CgCIxWIAgOeffx79fn/suO7duxcLCwtjx/Wmm27C1NSUPOe9730varUajh079hZu/ZXJcDjE5z//eTSbTezfv1+P6etA74+bj94jNwe9R24uen+8ePT+uPno/XFz0Pvj5nKl3R8db+qn32IKhQKGw+HYgQCAqakpvPzyy5dpq65eMpkMALzm8eT3MpkMksnk2PcdDgdisZg851pmNBrhl3/5l/H2t78dN954I4Bzx8zlciESiYw998Lj+lrHnd+7Vjly5Aj279+PTqeDQCCARx55BPv27cOhQ4f0mP4T6P1x89F75JtH75Gbh94f3zh6f9x89P745tH74+Zxpd4fryqhrShXGg8++CCOHj2KJ5988nJvypZgz549OHToEKrVKv76r/8aDzzwAJ544onLvVmKorxB9B65eej9UVG2Fnp/3Dyu1PvjVWUdj8fjsNvtr0qKy2azSKVSl2mrrl54zL7X8UylUsjlcmPfHwwGKJVK1/wx/9jHPoYvf/nL+MY3voG5uTn5eiqVQq/XQ6VSGXv+hcf1tY47v3et4nK5sGvXLtxxxx14+OGHccstt+CP//iP9Zi+DvT+uPnoPfLNoffIzUXvj28cvT9uPnp/fHPo/XFzuVLvj1eV0Ha5XLjjjjvw+OOPy9dGoxEef/xx7N+//zJu2dXJ9u3bkUqlxo5nrVbDM888I8dz//79qFQqeP755+U5X//61zEajXDPPfe85dt8JWBZFj72sY/hkUcewde//nVs37597Pt33HEHnE7n2HE9ceIEVlZWxo7rkSNHxv4DeuyxxxAKhbBv3763ZkeuAkajEbrdrh7T14HeHzcfvUe+MfQe+dag98fXj94fNx+9P74x9P741nDF3B/fVJTaZeDzn/+85Xa7rf/5P/+ndfz4cevDH/6wFYlExpLilPPU63Xr4MGD1sGDBy0A1h/+4R9aBw8etJaXly3LOjeaIRKJWF/84hetw4cPWz/yIz/ymqMZbrvtNuuZZ56xnnzySWv37t3X9GiGj370o1Y4HLa++c1vWul0Wh6tVkue85GPfMRaWFiwvv71r1vPPfectX//fmv//v3yfY4SeM973mMdOnTI+ru/+zsrkUhcs6MZLMuyPv7xj1tPPPGEdfbsWevw4cPWxz/+cctms1lf+9rXLMvSY/p60PvjxaP3yM1H75Gbj94f3zx6f7x49P64+ej9cfO5ku+PV53QtizL+pM/+RNrYWHBcrlc1t133209/fTTl3uTrli+8Y1vWABe9XjggQcsyzo3nuG3fuu3rKmpKcvtdlvvfve7rRMnToy9RrFYtH7yJ3/SCgQCVigUsv7Nv/k3Vr1evwx7c2XwWscTgPXZz35WntNut61f+IVfsKLRqOXz+awf+7Efs9Lp9NjrLC0tWe973/ssr9drxeNx69d+7desfr//Fu/NlcPP/uzPWouLi5bL5bISiYT17ne/W26SlqXH9PWi98eLQ++Rm4/eIzcfvT9uDnp/vDj0/rj56P1x87mS7482y7KsN1cTVxRFURRFURRFURSFXFU92oqiKIqiKIqiKIpypaNCW1EURVEURVEURVE2ERXaiqIoiqIoiqIoirKJqNBWFEVRFEVRFEVRlE1EhbaiKIqiKIqiKIqibCIqtBVFURRFURRFURRlE1GhrSiKoiiKoiiKoiibiAptRVEURVEURVEURdlEVGgriqIoiqIoiqIoyiaiQltRFEVRFEVRFEVRNhEV2oqiKIqiKIqiKIqyifx/vHAOR0ttXQsAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# make predictions\n", + "predict(cfg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52b7abaa", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + } + }, + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/predict.py b/TensorFlow2/Segmentation/Contrib/UNet3P/predict.py new file mode 100644 index 000000000..e838feded --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/predict.py @@ -0,0 +1,101 @@ +""" +Prediction script used to visualize model output +""" +import os +import hydra +from omegaconf import DictConfig + +from data_generators import tf_data_generator +from utils.general_utils import join_paths, suppress_warnings +from utils.images_utils import display +from utils.images_utils import postprocess_mask, denormalize_mask +from models.model import prepare_model + + +def predict(cfg: DictConfig): + """ + Predict and visualize given data + """ + + # suppress TensorFlow and DALI warnings + suppress_warnings() + + # set batch size to one + cfg.HYPER_PARAMETERS.BATCH_SIZE = 1 + + # data generator + val_generator = tf_data_generator.DataGenerator(cfg, mode="VAL") + + # create model + model = prepare_model(cfg) + + # weights model path + checkpoint_path = join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.MODEL_CHECKPOINT.PATH, + f"{cfg.MODEL.WEIGHTS_FILE_NAME}.hdf5" + ) + + assert os.path.exists(checkpoint_path), \ + f"Model weight's file does not exist at \n{checkpoint_path}" + + # load model weights + model.load_weights(checkpoint_path, by_name=True, skip_mismatch=True) + # model.summary() + + # check mask are available or not + mask_available = True + if cfg.DATASET.VAL.MASK_PATH is None or \ + str(cfg.DATASET.VAL.MASK_PATH).lower() == "none": + mask_available = False + + showed_images = 0 + for batch_data in val_generator: # for each batch + batch_images = batch_data[0] + if mask_available: + batch_mask = batch_data[1] + + # make prediction on batch + batch_predictions = model.predict_on_batch(batch_images) + if len(model.outputs) > 1: + batch_predictions = batch_predictions[0] + + for index in range(len(batch_images)): + + image = batch_images[index] # for each image + if cfg.SHOW_CENTER_CHANNEL_IMAGE: + # for UNet3+ show only center channel as image + image = image[:, :, 1] + + # do postprocessing on predicted mask + prediction = batch_predictions[index] + prediction = postprocess_mask(prediction, cfg.OUTPUT.CLASSES) + # denormalize mask for better visualization + prediction = denormalize_mask(prediction, cfg.OUTPUT.CLASSES) + + if mask_available: + mask = batch_mask[index] + mask = postprocess_mask(mask, cfg.OUTPUT.CLASSES) + mask = denormalize_mask(mask, cfg.OUTPUT.CLASSES) + + # if np.unique(mask).shape[0] == 2: + if mask_available: + display([image, mask, prediction], show_true_mask=True) + else: + display([image, prediction], show_true_mask=False) + + showed_images += 1 + # stop after displaying below number of images + # if showed_images >= 10: break + + +@hydra.main(version_base=None, config_path="configs", config_name="config") +def main(cfg: DictConfig): + """ + Read config file and pass to prediction method + """ + predict(cfg) + + +if __name__ == "__main__": + main() diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/requirements.txt b/TensorFlow2/Segmentation/Contrib/UNet3P/requirements.txt new file mode 100644 index 000000000..bdb49797f --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/requirements.txt @@ -0,0 +1,7 @@ +hydra-core +opencv-python +jupyter +matplotlib +tqdm +nibabel +numba \ No newline at end of file diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/train.py b/TensorFlow2/Segmentation/Contrib/UNet3P/train.py new file mode 100644 index 000000000..a6e27f7da --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/train.py @@ -0,0 +1,215 @@ +""" +Training script +""" +import numpy as np +from datetime import datetime, timedelta +import hydra +from omegaconf import DictConfig +import tensorflow as tf +from tensorflow.keras import mixed_precision +from tensorflow.keras.callbacks import ( + EarlyStopping, + ModelCheckpoint, + TensorBoard, + CSVLogger +) + +from data_generators import data_generator +from data_preparation.verify_data import verify_data +from utils.general_utils import create_directory, join_paths, set_gpus, \ + suppress_warnings +from models.model import prepare_model +from losses.loss import DiceCoefficient +from losses.unet_loss import unet3p_hybrid_loss +from callbacks.timing_callback import TimingCallback + + +def create_training_folders(cfg: DictConfig): + """ + Create directories to store Model CheckPoint and TensorBoard logs. + """ + create_directory( + join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.MODEL_CHECKPOINT.PATH + ) + ) + create_directory( + join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.TENSORBOARD.PATH + ) + ) + + +def train(cfg: DictConfig): + """ + Training method + """ + + # suppress TensorFlow and DALI warnings + suppress_warnings() + + print("Verifying data ...") + verify_data(cfg) + + if cfg.MODEL.TYPE == "unet3plus_deepsup_cgm": + raise ValueError( + "UNet3+ with Deep Supervision and Classification Guided Module" + "\nModel exist but training script is not supported for this variant" + "please choose other variants from config file" + ) + + if cfg.USE_MULTI_GPUS.VALUE: + # change number of visible gpus for training + set_gpus(cfg.USE_MULTI_GPUS.GPU_IDS) + # update batch size according to available gpus + data_generator.update_batch_size(cfg) + + # create folders to store training checkpoints and logs + create_training_folders(cfg) + + if cfg.OPTIMIZATION.AMP: + print("Enabling Automatic Mixed Precision(AMP) training") + policy = mixed_precision.Policy('mixed_float16') + mixed_precision.set_global_policy(policy) + + if cfg.OPTIMIZATION.XLA: + print("Enabling Accelerated Linear Algebra(XLA) training") + tf.config.optimizer.set_jit(True) + + # create model + strategy = None + if cfg.USE_MULTI_GPUS.VALUE: + # multi gpu training using tensorflow mirrored strategy + strategy = tf.distribute.MirroredStrategy( + cross_device_ops=tf.distribute.HierarchicalCopyAllReduce() + ) + print('Number of visible gpu devices: {}'.format(strategy.num_replicas_in_sync)) + with strategy.scope(): + optimizer = tf.keras.optimizers.Adam( + learning_rate=cfg.HYPER_PARAMETERS.LEARNING_RATE + ) # optimizer + if cfg.OPTIMIZATION.AMP: + optimizer = mixed_precision.LossScaleOptimizer( + optimizer, + dynamic=True + ) + dice_coef = DiceCoefficient(post_processed=True, classes=cfg.OUTPUT.CLASSES) + dice_coef = tf.keras.metrics.MeanMetricWrapper(name="dice_coef", fn=dice_coef) + model = prepare_model(cfg, training=True) + else: + optimizer = tf.keras.optimizers.Adam( + learning_rate=cfg.HYPER_PARAMETERS.LEARNING_RATE + ) # optimizer + if cfg.OPTIMIZATION.AMP: + optimizer = mixed_precision.LossScaleOptimizer( + optimizer, + dynamic=True + ) + dice_coef = DiceCoefficient(post_processed=True, classes=cfg.OUTPUT.CLASSES) + dice_coef = tf.keras.metrics.MeanMetricWrapper(name="dice_coef", fn=dice_coef) + model = prepare_model(cfg, training=True) + + model.compile( + optimizer=optimizer, + loss=unet3p_hybrid_loss, + metrics=[dice_coef], + ) + model.summary() + + # data generators + train_generator = data_generator.get_data_generator(cfg, "TRAIN", strategy) + val_generator = data_generator.get_data_generator(cfg, "VAL", strategy) + + # verify generator + # for i, (batch_images, batch_mask) in enumerate(val_generator): + # print(len(batch_images)) + # if i >= 3: break + + # the tensorboard log directory will be a unique subdirectory + # based on the start time for the run + tb_log_dir = join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.TENSORBOARD.PATH, + "{}".format(datetime.now().strftime("%Y.%m.%d.%H.%M.%S")) + ) + print("TensorBoard directory\n" + tb_log_dir) + + checkpoint_path = join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.MODEL_CHECKPOINT.PATH, + f"{cfg.MODEL.WEIGHTS_FILE_NAME}.hdf5" + ) + print("Weights path\n" + checkpoint_path) + + csv_log_path = join_paths( + cfg.WORK_DIR, + cfg.CALLBACKS.CSV_LOGGER.PATH, + f"training_logs_{cfg.MODEL.TYPE}.csv" + ) + print("Logs path\n" + csv_log_path) + + # evaluation metric + evaluation_metric = "val_dice_coef" + if len(model.outputs) > 1: + evaluation_metric = f"val_{model.output_names[0]}_dice_coef" + + # Timing, TensorBoard, EarlyStopping, ModelCheckpoint, CSVLogger callbacks + timing_callback = TimingCallback() + callbacks = [ + TensorBoard(log_dir=tb_log_dir, write_graph=False, profile_batch=0), + EarlyStopping( + patience=cfg.CALLBACKS.EARLY_STOPPING.PATIENCE, + verbose=cfg.VERBOSE + ), + ModelCheckpoint( + checkpoint_path, + verbose=cfg.VERBOSE, + save_weights_only=cfg.CALLBACKS.MODEL_CHECKPOINT.SAVE_WEIGHTS_ONLY, + save_best_only=cfg.CALLBACKS.MODEL_CHECKPOINT.SAVE_BEST_ONLY, + monitor=evaluation_metric, + mode="max" + + ), + CSVLogger( + csv_log_path, + append=cfg.CALLBACKS.CSV_LOGGER.APPEND_LOGS + ), + timing_callback + ] + + training_steps = data_generator.get_iterations(cfg, mode="TRAIN") + validation_steps = data_generator.get_iterations(cfg, mode="VAL") + + # start training + model.fit( + x=train_generator, + steps_per_epoch=training_steps, + validation_data=val_generator, + validation_steps=validation_steps, + epochs=cfg.HYPER_PARAMETERS.EPOCHS, + callbacks=callbacks, + workers=cfg.DATALOADER_WORKERS, + ) + + training_time = timing_callback.train_end_time - timing_callback.train_start_time + training_time = timedelta(seconds=training_time) + print(f"Total training time {training_time}") + + mean_time = np.mean(timing_callback.batch_time) + throughput = data_generator.get_batch_size(cfg) / mean_time + print(f"Training latency: {round(mean_time * 1e3, 2)} msec") + print(f"Training throughput/FPS: {round(throughput, 2)} samples/sec") + + +@hydra.main(version_base=None, config_path="configs", config_name="config") +def main(cfg: DictConfig): + """ + Read config file and pass to train method for training + """ + train(cfg) + + +if __name__ == "__main__": + main() diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/utils/general_utils.py b/TensorFlow2/Segmentation/Contrib/UNet3P/utils/general_utils.py new file mode 100644 index 000000000..9eea67b8d --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/utils/general_utils.py @@ -0,0 +1,123 @@ +""" +General Utility functions +""" +import os +import tensorflow as tf +from omegaconf import DictConfig +from .images_utils import image_to_mask_name + + +def create_directory(path): + """ + Create Directory if it already does not exist. + """ + if not os.path.exists(path): + os.makedirs(path) + + +def join_paths(*paths): + """ + Concatenate multiple paths. + """ + return os.path.normpath(os.path.sep.join(path.rstrip(r"\/") for path in paths)) + + +def set_gpus(gpu_ids): + """ + Change number of visible gpus for tensorflow. + gpu_ids: Could be integer or list of integers. + In case Integer: if integer value is -1 then use all available gpus. + otherwise if positive number, then use given number of gpus. + In case list of Integer: each integer will be considered as gpu id + """ + all_gpus = tf.config.experimental.list_physical_devices('GPU') + all_gpus_length = len(all_gpus) + if isinstance(gpu_ids, int): + if gpu_ids == -1: + gpu_ids = range(all_gpus_length) + else: + gpu_ids = min(gpu_ids, all_gpus_length) + gpu_ids = range(gpu_ids) + + selected_gpus = [all_gpus[gpu_id] for gpu_id in gpu_ids if gpu_id < all_gpus_length] + + try: + tf.config.experimental.set_visible_devices(selected_gpus, 'GPU') + except RuntimeError as e: + # Visible devices must be set at program startup + print(e) + + +def get_gpus_count(): + """ + Return length of available gpus. + """ + return len(tf.config.experimental.list_logical_devices('GPU')) + + +def get_data_paths(cfg: DictConfig, mode: str, mask_available: bool): + """ + Return list of absolute images/mask paths. + There are two options you can either pass directory path or list. + In case of directory, it should contain relative path of images/mask + folder from project root path. + In case of list of images, every element should contain absolute path + for each image and mask. + For prediction, you can set mask path to None if mask are not + available for visualization. + """ + + # read images from directory + if isinstance(cfg.DATASET[mode].IMAGES_PATH, str): + # has only images name not full path + images_paths = os.listdir( + join_paths( + cfg.WORK_DIR, + cfg.DATASET[mode].IMAGES_PATH + ) + ) + + if mask_available: + mask_paths = [ + image_to_mask_name(image_name) for image_name in images_paths + ] + # create full mask paths from folder + mask_paths = [ + join_paths( + cfg.WORK_DIR, + cfg.DATASET[mode].MASK_PATH, + mask_name + ) for mask_name in mask_paths + ] + + # create full images paths from folder + images_paths = [ + join_paths( + cfg.WORK_DIR, + cfg.DATASET[mode].IMAGES_PATH, + image_name + ) for image_name in images_paths + ] + else: + # read images and mask from absolute paths given in list + images_paths = list(cfg.DATASET[mode].IMAGES_PATH) + if mask_available: + mask_paths = list(cfg.DATASET[mode].MASK_PATH) + + if mask_available: + return images_paths, mask_paths + else: + return images_paths, + + +def suppress_warnings(): + """ + Suppress TensorFlow warnings. + """ + import logging + logging.getLogger('tensorflow').setLevel(logging.ERROR) + logging.getLogger('dali').setLevel(logging.ERROR) + os.environ["KMP_AFFINITY"] = "noverbose" + os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' + import tensorflow as tf + tf.autograph.set_verbosity(3) diff --git a/TensorFlow2/Segmentation/Contrib/UNet3P/utils/images_utils.py b/TensorFlow2/Segmentation/Contrib/UNet3P/utils/images_utils.py new file mode 100644 index 000000000..d97e482af --- /dev/null +++ b/TensorFlow2/Segmentation/Contrib/UNet3P/utils/images_utils.py @@ -0,0 +1,118 @@ +""" +Utility functions for image processing +""" +import numpy as np +import cv2 +from omegaconf import DictConfig +import matplotlib.pyplot as plt + + +def read_image(img_path, color_mode): + """ + Read and return image as np array from given path. + In case of color image, it returns image in BGR mode. + """ + return cv2.imread(img_path, color_mode) + + +def resize_image(img, height, width, resize_method=cv2.INTER_CUBIC): + """ + Resize image + """ + return cv2.resize(img, dsize=(width, height), interpolation=resize_method) + + +def prepare_image(path: str, resize: DictConfig, normalize_type: str): + """ + Prepare image for model. + read image --> resize --> normalize --> return as float32 + """ + image = read_image(path, cv2.IMREAD_COLOR) + image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + + if resize.VALUE: + # TODO verify image resizing method + image = resize_image(image, resize.HEIGHT, resize.WIDTH, cv2.INTER_AREA) + + if normalize_type == "normalize": + image = image / 255.0 + + image = image.astype(np.float32) + + return image + + +def prepare_mask(path: str, resize: dict, normalize_mask: dict): + """ + Prepare mask for model. + read mask --> resize --> normalize --> return as int32 + """ + mask = read_image(path, cv2.IMREAD_GRAYSCALE) + + if resize.VALUE: + mask = resize_image(mask, resize.HEIGHT, resize.WIDTH, cv2.INTER_NEAREST) + + if normalize_mask.VALUE: + mask = mask / normalize_mask.NORMALIZE_VALUE + + mask = mask.astype(np.int32) + + return mask + + +def image_to_mask_name(image_name: str): + """ + Convert image file name to it's corresponding mask file name e.g. + image name --> mask name + image_28_0.png mask_28_0.png + replace image with mask + """ + + return image_name.replace('image', 'mask') + + +def postprocess_mask(mask, classes, output_type=np.int32): + """ + Post process model output. + Covert probabilities into indexes based on maximum value. + """ + if classes == 1: + mask = np.where(mask > .5, 1.0, 0.0) + else: + mask = np.argmax(mask, axis=-1) + return mask.astype(output_type) + + +def denormalize_mask(mask, classes): + """ + Denormalize mask by multiplying each class with higher + integer (255 / classes) for better visualization. + """ + mask = mask * (255 / classes) + return mask.astype(np.int32) + + +def display(display_list, show_true_mask=False): + """ + Show list of images. it could be + either [image, true_mask, predicted_mask] or [image, predicted_mask]. + Set show_true_mask to True if true mask is available or vice versa + """ + if show_true_mask: + title_list = ('Input Image', 'True Mask', 'Predicted Mask') + plt.figure(figsize=(12, 4)) + else: + title_list = ('Input Image', 'Predicted Mask') + plt.figure(figsize=(8, 4)) + + for i in range(len(display_list)): + plt.subplot(1, len(display_list), i + 1) + if title_list is not None: + plt.title(title_list[i]) + if len(np.squeeze(display_list[i]).shape) == 2: + plt.imshow(np.squeeze(display_list[i]), cmap='gray') + plt.axis('on') + else: + plt.imshow(np.squeeze(display_list[i])) + plt.axis('on') + plt.show() diff --git a/TensorFlow2/Segmentation/UNet_Medical/data_loading/data_loader.py b/TensorFlow2/Segmentation/UNet_Medical/data_loading/data_loader.py index 7d08b88ab..f5f30b919 100755 --- a/TensorFlow2/Segmentation/UNet_Medical/data_loading/data_loader.py +++ b/TensorFlow2/Segmentation/UNet_Medical/data_loading/data_loader.py @@ -68,7 +68,7 @@ def _load_multipage_tiff(self, path): def _get_val_train_indices(self, length, fold, ratio=0.8): assert 0 < ratio <= 1, "Train/total data ratio must be in range (0.0, 1.0]" np.random.seed(self._seed) - indices = np.arange(0, length, 1, dtype=np.int) + indices = np.arange(0, length, 1, dtype=np.int32) np.random.shuffle(indices) if fold is not None: indices = deque(indices) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/.dockerignore b/Tools/DGLPyTorch/SyntheticGraphGeneration/.dockerignore new file mode 100644 index 000000000..8e80d5aa1 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/.dockerignore @@ -0,0 +1,14 @@ +**/.idea +**/save +**/.ipynb_checkpoints +**/__pycache__ +**/.gitkeep +**/dask-worker-space +**/preprocessed +docker_scripts +generated* +.git +.gitignore +Dockerfile +.dockerignore +README.md diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/.gitignore b/Tools/DGLPyTorch/SyntheticGraphGeneration/.gitignore new file mode 100644 index 000000000..ab30eefea --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/.gitignore @@ -0,0 +1,8 @@ +/save/ +/data/ +__pycache__ +.ipynb_checkpoints/ +*.csv +*.txt +dask-worker-space +exp diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/Dockerfile b/Tools/DGLPyTorch/SyntheticGraphGeneration/Dockerfile new file mode 100644 index 000000000..8019e85b0 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/Dockerfile @@ -0,0 +1,27 @@ +# - image +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.12-py3 +FROM ${FROM_IMAGE_NAME} + +# - SNAP dependencies +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get install -y gnuplot graphviz \ + && rm -rf /var/lib/apt/lists/* + +ENV DEBIAN_FRONTEND=interactive + +# - requirements +ADD requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir dgl-cu113 dglgo -f https://data.dgl.ai/wheels/repo.html +RUN pip install -U --no-deps dython + +# - dir +WORKDIR /workspace/ +COPY . . + +# - envs +RUN echo 'alias syngen="python syngen"' >> ~/.bashrc +ENV PYTHONPATH "${PYTHONPATH}:/workspace/" +RUN jupyter nbextension enable --py --sys-prefix widgetsnbextension diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/README.md b/Tools/DGLPyTorch/SyntheticGraphGeneration/README.md new file mode 100644 index 000000000..b78d3a35b --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/README.md @@ -0,0 +1,523 @@ +# Synthetic Graph Generation + +This repository implements a tool for generating graphs with an arbitrary size, including node and edge tabular features. + +## Table Of Contents +- [Solution overview](#solution-overview) + * [Synthetic Graph Generation architecture](#synthetic-graph-generation-architecture) + * [Default configuration](#default-configuration) + * [Feature support matrix](#feature-support-matrix) + * [Features](#features) + * [Models](#models) +- [Setup](#setup) + * [Requirements](#requirements) +- [Quick Start Guide](#quick-start-guide) +- [Advanced](#advanced) + * [Repository structure](#repository-structure) + * [Important scripts and files](#important-scripts-and-files) + * [Parameters](#parameters) + * [Command-line options](#command-line-options) + * [Define the synthesizer pipeline](#define-the-synthesizer-pipeline) + * [Getting the data](#getting-the-data) + + [List of datasets](#list-of-datasets) +- [Performance](#Performance) + * [Results](#results) +- [Release notes](#release-notes) + * [Changelog](#changelog) + * [Known issues](#known-issues) +- [Reference](#reference) + * [Cite](#cite) + +## Solution overview + +Synthetic data generation has become pervasive with imploding amounts of data and demand to deploy machine learning models leveraging such data. There has been an increasing interest in leveraging graph-based neural network model on graph datasets, though many public datasets are of a much smaller scale than that used in real-world applications. Synthetic Graph Generation is a common problem in multiple domains for various applications, including the generation of big graphs with similar properties to original or anonymizing data that cannot be shared. The Synthetic Graph Generation tool enables users to generate arbitrary graphs based on provided real data. + +### Synthetic Graph Generation architecture + +The tool has the following architecture. + +![Synthetic Graph Generation architecture](img/syngen_architecture.png) + +The module is composed of three parts: a structural generator, which fits the graph structure, feature generator, which fits the feature distribution contained in the graph; and finally, an aligner, which aligns the generated features with the generated graph structure + +#### Graph structural generator + +The graph structural generator fits graph structure and generate a corresponding graph containing the nodes and edges. + +#### Feature generator + +The feature generator fits the feature distribution contained in the graph and generates the corresponding features. +There is the option to allow users to generate features associated with nodes, edges, or both. + +#### Aligner + +The aligner aligns the generated features taken from the feature generator with the graph structure generated by a graph structural generator. + +### Feature support matrix + +This tool supports the following features: + +| Feature | Synthetic Graph Generation | +|------------------------------|----------------------------| +| Non-partite graph generation | Yes | +| N-partite graph generation | Yes | +| Undirected graph generation | Yes | +| Directed graph generation | Yes | +| Self-loops generation | Yes | +| Edge features generation | Yes | +| Node features generation | Yes | + +#### Features + +* Non-partite graph generation is a task to generate a graph that doesn't contain any explicit partites (disjoint and independent sets of nodes). + +* N-partite graph generation is a task to generate a graph that consists of an arbitrary number of partites. + +* Undirected graph generation is a task to generate a graph made up of a set of vertices connected by not ordered edges. + +* Directed graph generation is a task to generate a graph made up of a set of vertices connected by directed edges. + +* Self-loops generation is a task to generate edges that connect a vertex to itself. + +* Edge features generation is a task to generate features associated with an edge. + +* Node features generation is a task to generate features associated with a node. + + +### Models + +Structural graph generation +``` +- RMAT +- Random (Erdos-Renyi) +``` + +Tabular features +``` +- KDE +- Gaussian +- Uniform +- Random +- CTGAN (Conditional GAN) +``` + +Aligner +``` +- XGBoost +``` + +## Setup + +The following section lists the requirements you need to run the Synthetic Graph Generation tool. + +### Requirements + +This repository contains a Dockerfile that extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: +- [NVIDIA Ampere Architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/), [NVIDIA Volta](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) or [NVIDIA Turing](https://www.nvidia.com/en-us/geforce/turing/) based GPU +- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) +- Custom Docker containers built for this tool. Refer to the steps in the [Quick Start Guide](#quick-start-guide). + +For more information about how to get started with NGC containers, refer to the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: +- [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) +- [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) + +For those unable to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). + + + +## Quick Start Guide + +### Getting Started + +To use the tool, perform the following steps. +For the specifics concerning generation and training, refer to the [Advanced section](#advanced). + + +1. Clone the repository. +``` +git clone https://github.com/NVIDIA/DeepLearningExamples +``` + +2. Go to the `SyntheticGraphGeneration` tool directory within the `DeepLearningExamples` repository: +``` +cd DeepLearningExamples/Tools/DGLPyTorch/SyntheticGraphGeneration +``` + +3. Build the SyntheticGraphGeneration container. +``` +bash docker_scripts/build_docker.sh +``` + +4. Download the datasets. (It is advisable to run this command inside docker interactive container to ensure environment setup, see 6.1) + +``` +bash scripts/get_datasets.sh +``` + +**Note**: This script requires a manual download of 4 datasets (tabformer, ieee, paysim, credit) and putting them into `./data` directory with the correct naming. The instruction for the manual download will be printed during the preprocessing. If the raw data is not present or the dataset is already preprocessed, the preprocessing will be skipped. + +5. Run the SyntheticGraphGeneration Jupyter notebook. + +5.1. Run the Docker notebook container. +``` +bash docker_scripts/run_docker_notebook.sh +``` + +5.2 Open Jupyter notebook. +``` +http://localhost:9916/tree/demos +``` + +6. Run the SyntheticGraphGeneration CLI. + +6.1. Run the Docker interactive container. +``` +bash docker_scripts/run_docker_interactive.sh +``` + +6.2. Run Command Line Interface (CLI) command. + +The tool contains 3 run commands: `preprocess`, ``synthesize` and `pretrain` + +For example, to synthesize a graph similar to the [IEEE](https://www.kaggle.com/c/ieee-fraud-detection) dataset, run the following commands: + +1. Convert IEEE into the SynGen format: + +``` +syngen preprocess \ +--dataset ieee \ +--source-path /workspace/data/ieee-fraud/ \ +--destination-path /workspace/data/ieee-preprocessed +``` + +**Note**: `--source-path` points to the location where the IEEE dataset is extracted, +and `destination-path` points to the location where the IEEE dataset in SynGen format is saved. + + +2. Prepare SynGen configuration manually or using: + +``` +syngen mimic-dataset \ +--dataset-path /workspace/data/ieee-preprocessed \ +--output-file /workspace/configurations/my_ieee_config.json \ +--tab-gen kde \ +--edge-scale 1 \ +--node-scale 1 +``` + +**Note**: In the above commands, the `kde` tabular generator will be used to generate all tabular features. + +3. Generate synthetic IEEE + +``` +syngen synthesize \ +--config-path /workspace/configurations/my_ieee_config.json \ +--save-path /workspace/data/ieee-generated +``` + +**Note**: `--save-path` points to the location where the generated data in SynGen format is saved. + +Following the above command, the `pretrain` command can be used to pre-train or fine-tune the given generated sample. + +``` +syngen pretrain \ +--model gat_ec \ +--hidden-dim 64 \ +--out-dim 32 \ +--n-layers 1 \ +--n-heads 2 \ +--weight-decay 0.0 \ +--learning-rate 0.0005 \ +--batch-size 256 \ +--pretrain-epochs 5 \ +--finetune-epochs 5 \ +--data-path /workspace/data/ieee-preprocessed \ +--edge-name user-product \ +--pretraining-data-path /workspace/data/ieee-generated \ +--pretraining-edge-name user-product \ +--task ec \ +--target-col isFraud \ +--num-classes 2 \ +--log-interval 1 +``` + +**Note**: The current set of tasks and models are solely provided as use case examples on how to use the generated synthetic data to pretrain/fine-tune on a downstream task, and generally would need extension/modifications to accomodate very large graphs or arbitrary models. + +For the complete CLI usage of the `synthesize` command run: + +``` +syngen synthesize --help +``` + +Similarly for the `pretrain`, `mimic-dataset`, and `preprocess` run: + +``` +syngen --help +``` + +## Advanced + +### Repository structure + +``` +. +├── demos # Directory with all the Jupyter examples +├── docker_scripts # Directory with Docker scripts +├── scripts # Directory with datasets scripts +├── syngen # Directory with Synthetic Graph Generation source code +│ ├── analyzer # Directory with tools for getting graph visualisation and statistics +│ │ ├── graph # Directory with graph structure analyzer +│ │ └── tabular # Directory with tabular features analyzer +│ ├── benchmark # Directory with pretraining tools +│ │ ├── data_loader # Directory with pre-defined node and edge classification datasets +│ │ ├── models # Directory with GNN model definitions +│ │ └── tasks # Directory with set of tasks that are supported for training +│ ├── cli # Directory with all cli commands +│ ├── configuration # Directory with SynGen formats +│ ├── generator # Directory with all the generators +│ │ ├── graph # Directory with graph generators and graph +│ │ └── tabular # Directory with tabular generators +│ │ ├── data_transformer # Directory with tabular data transformations used by generators +│ │ └── transforms # Directory with tabular column transforms +│ ├── graph_aligner # Directory with all the aligners +│ ├── preprocessing # Directory with the preprocessings for the supported datasets +│ │ └── datasets # Directory with example dataset preprocessing scripts used to generate data +│ ├── synthesizer # Directory with all the synthesizers +│ └── utils # Directory with the utilities +│ └── types # Directory with common data types used in the tool +``` + + +### Important scripts and files +* `scripts/get_datasets.sh` - Bash script downloading and preprocessing supported datastes +* `docker_scripts/build_docker.sh` - Bash script that builds the Docker image +* `docker_scripts/run_docker_notebook.sh` - Bash script that runs Jupyter notebook in the Docker container +* `docker_scripts/run_docker_interactive.sh` - Bash script that runs the Docker container in interactive mode +* `syngen/synthesizer/configuration_graph_synthesizer.py` - Python file with graph synthesizer + +### Parameters + +For the synthesis process, refer to the parameters in the following table. + +| Scope | parameter | Comment | Default Value | +|---------------|------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------| +| preprocess | --dataset DATASET_NAME | Dataset to preprocess into SynGen format. Available datasets : [cora, epinions, ogbn_mag, ogbn_mag240m, ieee, tabformer] | Required | +| preprocess | -sp | --source-path SOURCE_PATH | Path to downloaded raw dataset | Required | +| preprocess | -dp | --destination-path DESTINATION_PATH | Path to store the preprocessed dataset in SynGen format. | SOURCE_PATH/syngen_preprocessed | +| preprocess | --cpu | Runs all operations on CPU | | +| preprocess | --use-cache | Does nothing if the target preprocessed dataset exists | | +| preprocess | --download | Downloads the dataset to the specified SOURCE_PATH | | +| mimic-dataset | -dp | --dataset-path DATASET_PATH | Path to the dataset in SynGen format | | +| mimic-dataset | -of | --output-file OUTPUT_FILE | Path to the generated SynGen Configuration | | +| mimic-dataset | -tg | --tab-gen TABULAR_GENERATOR | Tabular Generator to use to generate all tabular features (You always can modify OUTPUT_FILE). Available options: [kde, random, gaussian, uniform, ctgan] | kde | +| mimic-dataset | -rsg | --random-struct-gen | Generates random structure based on Erdos-Renyi model instead of mimicking | | +| mimic-dataset | -es | --edge-scale EDGE_SCALE | Multiples the number of edges to generate by the provided number | | +| mimic-dataset | -en | --node-scale NODE_SCALE | Multiples the number of nodes to generate by the provided number | | +| synthesize | -cp | --config-path CONFIG_PATH | Path to SynGen Configuration file that describes how to generate a graph | Required | +| synthesize | -sp | --save-path SAVE_PATH | Save path to dump generated files | Current directory | +| synthesize | --verbose | Displays generation process progress | | +| synthesize | --cpu | Runs all operations on CPU. [Attention] Alignment is not available on CPU | | +| synthesize | --timer-path FILE_PATH | Saves generation process timings to the specified file | Required | + +For the pretraining refer to the to [Command-line options](#command-line-options), as the parameters depend on the model choice. + + +### Define the synthesizer pipeline + +In this example, we show how to define the synthesizer pipeline for [IEEE](https://www.kaggle.com/c/ieee-fraud-detection) dataset. A full example can be found in [ieee_notebook](./demos/advanced_examples/e2e_ieee_demo.ipynb). + + +#### Prepare data + +- Preprocessing class is used to convert the IEEE dataset into SynGen format. +``` +preprocessing = IEEEPreprocessing(source_path='/workspace/data/ieee-fraud', destination_path='/workspace/data/ieee_preprocessed') +feature_spec = preprocessing.transform() +``` + +#### Prepare SynGen Configuration + +- SynGen Configuration is used to specify all generation details. We use the original dataset feature spec as a base for the configuration +``` +feature_spec_for_config = feature_spec.copy() +``` + +- Tabular generator is used to generate tabular features. +``` +feature_spec_for_config[MetaData.EDGES][0][MetaData.TABULAR_GENERATORS] = [ + { + MetaData.TYPE: "kde", + MetaData.FEATURES_LIST: -1, # copies all tabular features from the original dataset + MetaData.DATA_SOURCE: { + MetaData.TYPE: "configuration", + MetaData.PATH: preprocessed_path, + MetaData.NAME: "user-product", + }, + MetaData.PARAMS: {} + } +] +``` + +- Structure generator is used to generate graph structure. +``` +feature_spec_for_config[MetaData.EDGES][0][MetaData.STRUCTURE_GENERATOR] = { + MetaData.TYPE: "RMAT", + MetaData.DATA_SOURCE: { + MetaData.TYPE: "cfg", # the equivalent of 'configuration' + MetaData.PATH: preprocessed_path, + MetaData.NAME: "user-product", + }, + MetaData.PARAMS: { + "seed": 42, + } +} +``` + +- After providing all related information, we create a `SynGenConfiguration` object. It fills out missing fields and validates provided data. +``` +config = SynGenConfiguration(feature_spec_for_config) +``` + +#### Prepare synthesizer + +- Synthesizer is a class that combines all the generators and allows the user to run end-to-end fitting and generation. + +``` +synthesizer = ConfigurationGraphSynthesizer(configuration=config, save_path='/workspace/data/ieee_generated') + +``` + +- To start fitting process, we use `fit` method provided by the synthesizer. It will automatically load all required data from the disk based on the information provided in config. +``` +synthesizer.fit() +``` + +#### Generate graph + +- To run generation, we call the `generate` method provided by the synthesizer. We use `return_data=False` because we want only to store the generated in `/workspace/data/ieee_generated` folder. In other case it will download tabular data under the `MetaData.FEATURES_DATA` key for each node and edge type and structural data under the `MetaData.STRUCTURE_DATA` key for edges. +``` +out_feature_spec = synthesizer.generate(return_data=False) +``` + +### Getting the data + +To download the datasets used as an example , use `get_datasets.sh` script + +``` +bash scripts/get_datasets.sh +``` + +**Note**: Certain datasets require a Kaggle API key, hence may require manual download. Refer to the links below. +**Note**: Each user is responsible for checking the content of datasets and the applicable licenses and determining if they are suitable for the intended use + +#### List of datasets + + +Supported datasets: + +* [Twitch](https://snap.stanford.edu/data/twitch_gamers.html) +* [LastFM](https://snap.stanford.edu/data/feather-lastfm-social.html) +* [Orkut](https://snap.stanford.edu/data/com-Orkut.html) +* [Tabformer](https://github.com/IBM/TabFormer) +* [IEEE](https://www.kaggle.com/c/ieee-fraud-detection) +* [Paysim](https://www.kaggle.com/datasets/ealaxi/paysim1) +* [Credit](https://www.kaggle.com/datasets/kartik2112/fraud-detection) +* [CORA](https://relational.fit.cvut.cz/dataset/CORA) +* [Rating](http://www.trustlet.org/downloaded_epinions.html) +* [OGBN-MAG](https://ogb.stanford.edu/docs/nodeprop/#ogbn-mag) +* [OGBN-MAG](https://ogb.stanford.edu/docs/lsc/mag240m/) + + +## Performance + +Our results were obtained by running the demo notebooks [directory](./demos) in the PyTorch NGC container on NVIDIA DGX1 V100 with 8x V100 32GB GPUs. +All the notebooks are presented in the table below. + +| | scope | notebook | description | +|-----|-------------------|---------------------------------------|---------------------------------------------------------------------------------------------| +| 1. | basic_examples | e2e_cora_demo.ipynb | a complete process of generating a non-bipartite graph dataset with node features | +| 2. | basic_examples | e2e_ieee_demo.ipynb | a complete process of generating a bipartite graph dataset with edge features | +| 3. | basic_examples | e2e_epinions_demo.ipynb | a complete process of generating a heterogeneous bipartite graph dataset with edge features | | +| 4. | advanced_examples | big_graph_generation.ipynb | a complete process of mimicking and scaling the MAG240m dataset | +| 5. | performance | struct_generator.ipynb | comparison of SynGen graph structure generators | +| 6. | performance | tabular_generator.ipynb | comparison of SynGen tabular data generators | + +Scope refers to the directories in which the notebooks are stored and the functionalities particular notebooks cover . There are +* Basic - [basic_examples](./demos/basic_examples) - notebooks with the examples of basics functionalities +* Advanced - [advanced_examples](./demos/advanced_examples) - notebooks with the examples of advanced functionalities +* Performance - [performance](./demos/performance) - notebooks with the performance experiments + +To achieve the same results, follow the steps in the [Quick Start Guide](#quick-start-guide). + +#### Results + +##### 1. Quality of the content of generated dataset vs. original dataset: + + +The quality of the content comparison was conducted on the IEEE dataset (refer to [List of datasets](#list-of-datasets) for more details) with corresponding notebook [e2e_ieee_demo.ipynb](./demos/advanced_examples/e2e_ieee_demo.ipynb) +We compared three modalities, that is, quality of generated graph structure, quality of generated tabular data and quality of aligning tabular data to the graph structure. + +* Graph structure quality + * Comparison of degree distribution for an original graph, properly generated and random (Erdős–Rényi) ![degree_distribution_quality](img/degree_distribution_quality.png) + * Comparison of basic graph statistics for an original graph, properly generated and random (Erdős–Rényi) ![graph_structure statistics](img/graph_structure statistics.png) + +* Tabular data quality + * Comparison of two first components of a PCA of real and generated data ![pca_components](img/pca_components.png) + * Comparison of basic statistics between real and generated data + + | Generator | kl divergence | correlation correlation | + |------------|---------------|-------------------------| + | GAN | 0.912 | 0.018 | + | Gaussian | 0.065 | -0.030 | + | Random | 0.617 | 0.026 | + +* Structure to tabular alignment quality + * Degree centrality for feature distribution ![degree_centrality_feature_distribution](img/degree_centrality_feature_distribution.png) + +##### 2. Performance (speed) of the synthetic dataset generation: + * Performance of graph structure generation (edges/s) + ![edge_perf](img/edge_perf.png) + * Performance of categorical tabular data generation (samples/s) + + | Dataset (CPU/GPU) | KDE | Uniform | Gaussian | Random | + |-------------------|--------|---------|----------|---------| + | ieee (CPU) | 371296 | 897421 | 530683 | 440086 | + | ieee (GPU) | 592132 | 3621726 | 983408 | 6438646 | + + +##### 3. Synthetic dataset use-case specific quality factors: + * Performance (batches/s) comparison between original vs. synthetic datasets + + | Dataset | Model | Synthetic | Original | + |---------|-------|-----------|----------| + | ieee | gat | 0.07173 | 0.07249 | + +## Release notes + +### Changelog + +August 2023 +- Heterogeneous graph generation +- Multi-GPU generation + +January 2023 +- Initial release + +### Known issues + +There are no known issues with this model. + +## Reference + +### Cite + +Cite the following paper if you find this code useful or use it in your own work: + +``` +@article{darabi2022framework, + title={A Framework for Large Scale Synthetic Graph Dataset Generation}, + author={Darabi, Sajad and Bigaj, Piotr and Majchrowski, Dawid and Morkisz, Pawel and Fit-Florea, Alex}, + journal={arXiv preprint arXiv:2210.01944}, + year={2022} +} +``` diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/cora.json b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/cora.json new file mode 100644 index 000000000..661cf16e0 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/cora.json @@ -0,0 +1,7228 @@ +{ + "nodes": [ + { + "name": "paper", + "count": 2708, + "features": [ + { + "name": "w_0", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_2", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_3", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_4", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_5", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_6", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_7", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_8", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_9", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_10", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_11", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_12", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_13", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_14", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_15", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_16", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_17", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_18", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_19", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_20", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_21", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_22", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_23", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_24", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_25", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_26", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_27", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_28", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_29", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_30", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_31", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_32", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_33", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_34", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_35", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_36", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_37", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_38", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_39", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_40", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_41", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_42", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_43", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_44", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_45", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_46", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_47", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_48", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_49", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_50", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_51", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_52", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_53", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_54", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_55", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_56", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_57", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_58", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_59", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_60", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_61", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_62", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_63", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_64", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_65", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_66", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_67", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_68", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_69", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_70", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_71", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_72", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_73", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_74", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_75", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_76", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_77", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_78", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_79", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_80", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_81", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_82", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_83", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_84", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_85", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_86", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_87", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_88", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_89", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_90", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_91", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_92", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_93", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_94", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_95", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_96", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_97", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_98", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_99", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_100", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_101", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_102", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_103", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_104", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_105", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_106", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_107", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_108", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_109", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_110", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_111", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_112", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_113", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_114", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_115", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_116", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_117", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_118", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_119", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_120", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_121", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_122", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_123", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_124", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_125", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_126", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_127", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_128", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_129", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_130", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_131", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_132", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_133", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_134", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_135", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_136", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_137", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_138", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_139", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_140", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_141", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_142", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_143", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_144", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_145", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_146", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_147", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_148", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_149", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_150", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_151", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_152", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_153", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_154", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_155", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_156", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_157", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_158", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_159", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_160", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_161", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_162", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_163", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_164", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_165", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_166", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_167", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_168", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_169", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_170", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_171", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_172", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_173", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_174", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_175", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_176", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_177", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_178", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_179", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_180", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_181", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_182", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_183", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_184", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_185", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_186", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_187", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_188", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_189", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_190", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_191", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_192", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_193", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_194", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_195", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_196", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_197", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_198", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_199", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_200", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_201", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_202", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_203", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_204", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_205", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_206", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_207", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_208", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_209", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_210", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_211", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_212", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_213", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_214", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_215", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_216", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_217", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_218", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_219", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_220", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_221", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_222", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_223", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_224", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_225", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_226", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_227", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_228", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_229", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_230", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_231", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_232", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_233", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_234", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_235", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_236", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_237", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_238", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_239", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_240", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_241", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_242", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_243", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_244", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_245", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_246", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_247", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_248", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_249", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_250", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_251", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_252", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_253", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_254", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_255", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_256", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_257", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_258", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_259", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_260", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_261", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_262", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_263", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_264", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_265", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_266", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_267", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_268", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_269", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_270", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_271", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_272", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_273", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_274", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_275", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_276", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_277", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_278", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_279", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_280", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_281", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_282", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_283", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_284", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_285", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_286", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_287", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_288", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_289", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_290", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_291", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_292", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_293", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_294", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_295", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_296", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_297", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_298", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_299", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_300", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_301", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_302", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_303", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_304", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_305", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_306", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_307", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_308", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_309", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_310", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_311", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_312", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_313", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_314", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_315", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_316", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_317", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_318", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_319", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_320", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_321", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_322", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_323", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_324", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_325", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_326", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_327", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_328", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_329", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_330", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_331", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_332", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_333", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_334", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_335", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_336", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_337", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_338", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_339", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_340", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_341", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_342", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_343", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_344", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_345", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_346", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_347", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_348", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_349", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_350", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_351", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_352", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_353", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_354", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_355", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_356", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_357", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_358", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_359", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_360", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_361", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_362", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_363", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_364", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_365", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_366", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_367", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_368", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_369", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_370", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_371", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_372", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_373", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_374", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_375", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_376", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_377", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_378", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_379", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_380", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_381", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_382", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_383", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_384", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_385", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_386", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_387", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_388", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_389", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_390", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_391", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_392", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_393", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_394", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_395", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_396", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_397", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_398", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_399", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_400", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_401", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_402", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_403", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_404", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_405", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_406", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_407", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_408", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_409", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_410", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_411", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_412", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_413", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_414", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_415", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_416", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_417", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_418", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_419", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_420", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_421", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_422", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_423", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_424", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_425", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_426", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_427", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_428", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_429", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_430", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_431", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_432", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_433", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_434", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_435", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_436", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_437", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_438", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_439", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_440", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_441", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_442", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_443", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_444", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_445", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_446", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_447", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_448", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_449", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_450", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_451", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_452", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_453", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_454", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_455", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_456", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_457", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_458", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_459", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_460", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_461", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_462", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_463", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_464", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_465", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_466", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_467", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_468", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_469", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_470", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_471", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_472", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_473", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_474", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_475", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_476", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_477", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_478", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_479", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_480", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_481", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_482", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_483", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_484", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_485", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_486", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_487", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_488", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_489", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_490", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_491", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_492", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_493", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_494", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_495", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_496", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_497", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_498", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_499", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_500", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_501", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_502", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_503", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_504", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_505", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_506", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_507", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_508", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_509", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_510", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_511", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_512", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_513", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_514", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_515", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_516", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_517", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_518", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_519", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_520", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_521", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_522", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_523", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_524", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_525", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_526", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_527", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_528", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_529", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_530", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_531", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_532", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_533", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_534", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_535", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_536", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_537", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_538", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_539", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_540", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_541", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_542", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_543", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_544", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_545", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_546", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_547", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_548", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_549", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_550", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_551", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_552", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_553", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_554", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_555", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_556", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_557", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_558", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_559", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_560", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_561", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_562", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_563", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_564", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_565", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_566", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_567", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_568", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_569", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_570", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_571", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_572", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_573", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_574", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_575", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_576", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_577", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_578", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_579", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_580", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_581", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_582", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_583", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_584", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_585", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_586", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_587", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_588", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_589", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_590", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_591", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_592", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_593", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_594", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_595", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_596", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_597", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_598", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_599", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_600", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_601", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_602", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_603", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_604", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_605", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_606", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_607", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_608", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_609", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_610", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_611", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_612", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_613", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_614", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_615", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_616", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_617", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_618", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_619", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_620", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_621", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_622", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_623", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_624", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_625", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_626", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_627", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_628", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_629", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_630", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_631", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_632", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_633", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_634", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_635", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_636", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_637", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_638", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_639", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_640", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_641", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_642", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_643", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_644", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_645", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_646", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_647", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_648", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_649", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_650", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_651", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_652", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_653", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_654", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_655", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_656", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_657", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_658", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_659", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_660", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_661", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_662", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_663", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_664", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_665", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_666", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_667", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_668", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_669", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_670", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_671", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_672", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_673", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_674", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_675", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_676", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_677", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_678", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_679", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_680", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_681", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_682", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_683", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_684", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_685", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_686", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_687", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_688", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_689", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_690", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_691", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_692", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_693", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_694", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_695", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_696", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_697", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_698", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_699", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_700", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_701", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_702", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_703", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_704", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_705", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_706", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_707", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_708", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_709", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_710", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_711", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_712", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_713", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_714", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_715", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_716", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_717", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_718", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_719", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_720", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_721", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_722", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_723", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_724", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_725", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_726", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_727", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_728", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_729", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_730", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_731", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_732", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_733", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_734", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_735", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_736", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_737", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_738", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_739", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_740", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_741", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_742", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_743", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_744", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_745", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_746", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_747", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_748", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_749", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_750", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_751", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_752", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_753", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_754", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_755", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_756", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_757", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_758", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_759", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_760", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_761", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_762", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_763", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_764", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_765", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_766", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_767", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_768", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_769", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_770", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_771", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_772", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_773", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_774", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_775", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_776", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_777", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_778", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_779", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_780", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_781", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_782", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_783", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_784", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_785", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_786", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_787", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_788", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_789", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_790", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_791", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_792", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_793", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_794", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_795", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_796", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_797", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_798", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_799", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_800", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_801", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_802", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_803", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_804", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_805", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_806", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_807", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_808", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_809", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_810", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_811", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_812", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_813", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_814", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_815", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_816", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_817", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_818", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_819", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_820", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_821", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_822", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_823", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_824", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_825", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_826", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_827", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_828", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_829", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_830", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_831", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_832", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_833", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_834", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_835", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_836", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_837", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_838", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_839", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_840", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_841", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_842", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_843", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_844", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_845", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_846", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_847", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_848", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_849", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_850", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_851", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_852", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_853", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_854", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_855", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_856", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_857", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_858", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_859", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_860", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_861", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_862", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_863", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_864", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_865", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_866", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_867", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_868", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_869", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_870", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_871", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_872", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_873", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_874", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_875", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_876", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_877", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_878", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_879", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_880", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_881", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_882", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_883", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_884", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_885", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_886", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_887", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_888", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_889", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_890", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_891", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_892", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_893", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_894", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_895", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_896", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_897", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_898", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_899", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_900", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_901", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_902", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_903", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_904", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_905", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_906", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_907", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_908", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_909", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_910", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_911", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_912", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_913", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_914", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_915", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_916", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_917", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_918", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_919", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_920", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_921", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_922", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_923", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_924", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_925", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_926", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_927", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_928", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_929", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_930", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_931", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_932", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_933", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_934", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_935", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_936", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_937", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_938", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_939", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_940", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_941", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_942", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_943", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_944", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_945", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_946", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_947", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_948", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_949", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_950", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_951", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_952", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_953", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_954", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_955", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_956", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_957", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_958", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_959", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_960", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_961", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_962", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_963", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_964", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_965", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_966", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_967", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_968", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_969", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_970", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_971", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_972", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_973", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_974", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_975", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_976", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_977", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_978", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_979", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_980", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_981", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_982", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_983", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_984", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_985", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_986", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_987", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_988", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_989", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_990", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_991", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_992", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_993", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_994", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_995", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_996", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_997", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_998", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_999", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1000", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1001", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1002", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1003", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1004", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1005", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1006", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1007", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1008", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1009", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1010", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1011", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1012", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1013", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1014", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1015", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1016", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1017", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1018", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1019", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1020", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1021", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1022", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1023", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1024", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1025", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1026", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1027", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1028", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1029", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1030", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1031", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1032", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1033", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1034", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1035", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1036", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1037", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1038", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1039", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1040", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1041", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1042", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1043", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1044", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1045", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1046", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1047", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1048", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1049", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1050", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1051", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1052", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1053", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1054", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1055", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1056", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1057", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1058", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1059", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1060", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1061", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1062", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1063", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1064", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1065", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1066", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1067", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1068", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1069", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1070", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1071", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1072", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1073", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1074", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1075", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1076", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1077", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1078", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1079", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1080", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1081", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1082", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1083", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1084", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1085", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1086", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1087", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1088", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1089", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1090", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1091", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1092", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1093", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1094", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1095", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1096", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1097", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1098", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1099", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1100", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1101", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1102", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1103", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1104", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1105", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1106", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1107", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1108", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1109", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1110", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1111", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1112", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1113", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1114", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1115", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1116", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1117", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1118", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1119", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1120", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1121", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1122", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1123", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1124", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1125", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1126", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1127", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1128", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1129", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1130", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1131", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1132", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1133", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1134", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1135", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1136", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1137", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1138", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1139", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1140", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1141", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1142", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1143", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1144", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1145", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1146", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1147", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1148", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1149", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1150", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1151", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1152", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1153", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1154", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1155", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1156", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1157", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1158", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1159", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1160", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1161", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1162", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1163", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1164", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1165", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1166", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1167", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1168", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1169", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1170", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1171", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1172", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1173", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1174", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1175", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1176", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1177", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1178", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1179", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1180", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1181", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1182", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1183", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1184", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1185", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1186", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1187", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1188", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1189", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1190", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1191", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1192", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1193", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1194", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1195", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1196", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1197", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1198", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1199", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1200", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1201", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1202", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1203", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1204", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1205", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1206", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1207", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1208", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1209", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1210", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1211", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1212", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1213", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1214", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1215", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1216", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1217", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1218", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1219", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1220", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1221", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1222", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1223", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1224", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1225", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1226", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1227", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1228", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1229", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1230", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1231", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1232", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1233", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1234", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1235", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1236", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1237", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1238", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1239", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1240", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1241", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1242", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1243", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1244", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1245", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1246", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1247", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1248", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1249", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1250", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1251", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1252", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1253", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1254", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1255", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1256", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1257", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1258", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1259", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1260", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1261", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1262", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1263", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1264", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1265", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1266", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1267", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1268", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1269", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1270", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1271", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1272", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1273", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1274", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1275", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1276", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1277", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1278", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1279", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1280", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1281", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1282", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1283", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1284", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1285", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1286", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1287", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1288", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1289", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1290", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1291", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1292", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1293", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1294", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1295", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1296", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1297", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1298", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1299", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1300", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1301", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1302", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1303", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1304", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1305", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1306", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1307", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1308", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1309", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1310", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1311", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1312", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1313", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1314", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1315", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1316", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1317", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1318", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1319", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1320", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1321", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1322", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1323", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1324", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1325", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1326", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1327", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1328", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1329", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1330", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1331", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1332", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1333", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1334", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1335", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1336", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1337", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1338", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1339", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1340", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1341", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1342", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1343", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1344", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1345", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1346", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1347", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1348", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1349", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1350", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1351", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1352", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1353", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1354", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1355", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1356", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1357", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1358", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1359", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1360", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1361", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1362", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1363", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1364", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1365", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1366", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1367", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1368", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1369", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1370", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1371", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1372", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1373", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1374", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1375", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1376", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1377", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1378", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1379", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1380", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1381", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1382", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1383", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1384", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1385", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1386", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1387", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1388", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1389", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1390", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1391", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1392", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1393", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1394", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1395", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1396", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1397", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1398", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1399", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1400", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1401", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1402", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1403", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1404", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1405", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1406", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1407", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1408", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1409", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1410", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1411", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1412", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1413", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1414", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1415", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1416", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1417", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1418", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1419", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1420", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1421", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1422", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1423", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1424", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1425", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1426", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1427", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1428", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1429", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1430", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1431", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "w_1432", + "dtype": "int64", + "feature_type": "categorical" + }, + { + "name": "label", + "dtype": "int64", + "feature_type": "categorical" + } + ], + "features_path": "paper.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/cora/syngen_preprocessed", + "name": "paper" + }, + "params": {} + } + ] + } + ], + "edges": [ + { + "name": "cite", + "count": 5428, + "src_node_type": "paper", + "dst_node_type": "paper", + "directed": false, + "features": [], + "features_path": null, + "structure_path": "cite_edge_list.parquet", + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/cora/syngen_preprocessed", + "name": ["paper", "cite", "paper"] + }, + "params": { + "seed": 42, + "has_self_loop": false + } + } + } + ], + "[gen]aligners": [ + { + "type": "xgboost", + "graphs": ["cite"], + "edges": {}, + "nodes": { + "paper": ["label"] + }, + "params": {} + } + ] +} \ No newline at end of file diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/epinions.json b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/epinions.json new file mode 100644 index 000000000..58215744d --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/epinions.json @@ -0,0 +1,92 @@ +{ + "nodes": [ + { + "name": "user", + "count": 49289, + "features": [], + "features_path": null + }, + { + "name": "item", + "count": 139738, + "features": [], + "features_path": null + } + ], + "edges": [ + { + "name": "user-item", + "count": 664824, + "src_node_type": "user", + "dst_node_type": "item", + "directed": false, + "features": [ + { + "name": "rating", + "dtype": "int64", + "feature_type": "categorical" + } + ], + "features_path": "user-item.parquet", + "structure_path": "user-item_edge_list.parquet", + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/epinions/syngen_preprocessed", + "name": "user-item" + }, + "params": { + "seed": 42 + } + }, + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": ["rating"], + "data_source": { + "type": "dataset", + "path": "/workspace/data/epinions/syngen_preprocessed/user-item.parquet" + }, + "params": { + } + } + ] + }, + { + "name": "user-user", + "count": 487183, + "src_node_type": "user", + "dst_node_type": "user", + "reverse_name": "user-user-rev", + "features": [], + "features_path": null, + "structure_path": "user-user_edge_list.parquet", + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/epinions/syngen_preprocessed", + "name": "user-user" + }, + "params": { + "seed": 42, + "has_self_loop": false + } + } + } + ], + "[gen]aligners": [ + { + "type": "xgboost", + "graphs": ["user-item", "user-user"], + "edges": { + "user-item": ["rating"] + }, + "nodes": {}, + "params": { + + } + } + ] +} \ No newline at end of file diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ieee.json b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ieee.json new file mode 100644 index 000000000..31ea5b963 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ieee.json @@ -0,0 +1,339 @@ +{ + "nodes": [ + { + "name": "user", + "count": 17090, + "features": [], + "features_path": null + }, + { + "name": "product", + "count": 197, + "features": [], + "features_path": null + } + ], + "edges": [ + { + "name": "user-product", + "count": 52008, + "src_node_type": "user", + "dst_node_type": "product", + "directed": false, + "features": [ + { + "name": "TransactionDT", + "dtype": "int64", + "feature_type": "continuous" + }, + { + "name": "TransactionAmt", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C1", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C2", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C3", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C4", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C5", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C6", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C7", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C8", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C9", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C10", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C11", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C12", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "C14", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V279", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V280", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V284", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V285", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V286", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V287", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V290", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V291", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V292", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V293", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V294", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V295", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V297", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V298", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V299", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V302", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V303", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V304", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V305", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V306", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V307", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V308", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V309", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V310", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V311", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V312", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V316", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V317", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V318", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V319", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V320", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "V321", + "dtype": "float64", + "feature_type": "continuous" + }, + { + "name": "isFraud", + "dtype": "int64", + "feature_type": "categorical" + } + ], + "features_path": "user-product.parquet", + "structure_path": "user-product_edge_list.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": [ + "TransactionDT", + "TransactionAmt", + "C1", + "C2", + "C3", + "C4", + "C5", + "C6", + "C7", + "C8", + "C9", + "C10", + "C11", + "C12", + "C14", + "V279", + "V280", + "V284", + "V285", + "V286", + "V287", + "V290", + "V291", + "V292", + "V293", + "V294", + "V295", + "V297", + "V298", + "V299", + "V302", + "V303", + "V304", + "V305", + "V306", + "V307", + "V308", + "V309", + "V310", + "V311", + "V312", + "V316", + "V317", + "V318", + "V319", + "V320", + "V321", + "isFraud" + ], + "data_source": { + "type": "cfg", + "path": "/workspace/data/ieee-preprocessed", + "name": "user-product" + }, + "params": {} + } + ], + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/ieee-preprocessed", + "name": "user-product" + }, + "params": {} + } + } + ] +} \ No newline at end of file diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ogbn_mag.json b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ogbn_mag.json new file mode 100644 index 000000000..625519d7a --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ogbn_mag.json @@ -0,0 +1,2828 @@ +{ + "nodes": [ + { + "name": "paper", + "count": 736389, + "features": [ + { + "name": "feat_0", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_1", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_2", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_3", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_4", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_5", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_6", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_7", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_8", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_9", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_10", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_11", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_12", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_13", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_14", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_15", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_16", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_17", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_18", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_19", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_20", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_21", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_22", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_23", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_24", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_25", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_26", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_27", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_28", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_29", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_30", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_31", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_32", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_33", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_34", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_35", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_36", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_37", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_38", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_39", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_40", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_41", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_42", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_43", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_44", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_45", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_46", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_47", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_48", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_49", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_50", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_51", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_52", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_53", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_54", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_55", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_56", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_57", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_58", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_59", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_60", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_61", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_62", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_63", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_64", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_65", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_66", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_67", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_68", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_69", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_70", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_71", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_72", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_73", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_74", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_75", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_76", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_77", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_78", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_79", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_80", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_81", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_82", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_83", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_84", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_85", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_86", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_87", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_88", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_89", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_90", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_91", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_92", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_93", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_94", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_95", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_96", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_97", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_98", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_99", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_100", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_101", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_102", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_103", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_104", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_105", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_106", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_107", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_108", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_109", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_110", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_111", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_112", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_113", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_114", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_115", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_116", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_117", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_118", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_119", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_120", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_121", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_122", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_123", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_124", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_125", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_126", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_127", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "year", + "dtype": "int32", + "feature_type": "categorical" + }, + { + "name": "venue", + "dtype": "int32", + "feature_type": "categorical" + } + ], + "features_path": "paper.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "paper" + }, + "params": { + "gpu": true + } + } + ] + }, + { + "name": "author", + "count": 1134649, + "features": [ + { + "name": "feat_0", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_1", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_2", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_3", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_4", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_5", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_6", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_7", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_8", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_9", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_10", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_11", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_12", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_13", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_14", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_15", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_16", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_17", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_18", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_19", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_20", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_21", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_22", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_23", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_24", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_25", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_26", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_27", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_28", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_29", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_30", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_31", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_32", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_33", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_34", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_35", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_36", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_37", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_38", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_39", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_40", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_41", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_42", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_43", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_44", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_45", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_46", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_47", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_48", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_49", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_50", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_51", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_52", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_53", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_54", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_55", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_56", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_57", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_58", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_59", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_60", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_61", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_62", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_63", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_64", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_65", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_66", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_67", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_68", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_69", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_70", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_71", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_72", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_73", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_74", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_75", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_76", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_77", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_78", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_79", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_80", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_81", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_82", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_83", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_84", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_85", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_86", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_87", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_88", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_89", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_90", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_91", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_92", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_93", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_94", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_95", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_96", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_97", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_98", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_99", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_100", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_101", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_102", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_103", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_104", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_105", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_106", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_107", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_108", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_109", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_110", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_111", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_112", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_113", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_114", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_115", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_116", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_117", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_118", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_119", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_120", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_121", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_122", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_123", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_124", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_125", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_126", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_127", + "dtype": "float32", + "feature_type": "continuous" + } + ], + "features_path": "author.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "author" + }, + "params": { + "gpu": true + } + } + ] + }, + { + "name": "institution", + "count": 8740, + "features": [ + { + "name": "feat_0", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_1", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_2", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_3", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_4", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_5", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_6", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_7", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_8", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_9", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_10", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_11", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_12", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_13", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_14", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_15", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_16", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_17", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_18", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_19", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_20", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_21", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_22", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_23", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_24", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_25", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_26", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_27", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_28", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_29", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_30", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_31", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_32", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_33", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_34", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_35", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_36", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_37", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_38", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_39", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_40", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_41", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_42", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_43", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_44", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_45", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_46", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_47", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_48", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_49", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_50", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_51", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_52", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_53", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_54", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_55", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_56", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_57", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_58", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_59", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_60", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_61", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_62", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_63", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_64", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_65", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_66", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_67", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_68", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_69", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_70", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_71", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_72", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_73", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_74", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_75", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_76", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_77", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_78", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_79", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_80", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_81", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_82", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_83", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_84", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_85", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_86", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_87", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_88", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_89", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_90", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_91", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_92", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_93", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_94", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_95", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_96", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_97", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_98", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_99", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_100", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_101", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_102", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_103", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_104", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_105", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_106", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_107", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_108", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_109", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_110", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_111", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_112", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_113", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_114", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_115", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_116", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_117", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_118", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_119", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_120", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_121", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_122", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_123", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_124", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_125", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_126", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_127", + "dtype": "float32", + "feature_type": "continuous" + } + ], + "features_path": "institution.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "institution" + }, + "params": { + "gpu": true + } + } + ] + }, + { + "name": "field_of_study", + "count": 59965, + "features": [ + { + "name": "feat_0", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_1", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_2", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_3", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_4", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_5", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_6", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_7", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_8", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_9", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_10", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_11", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_12", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_13", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_14", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_15", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_16", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_17", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_18", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_19", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_20", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_21", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_22", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_23", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_24", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_25", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_26", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_27", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_28", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_29", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_30", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_31", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_32", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_33", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_34", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_35", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_36", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_37", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_38", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_39", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_40", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_41", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_42", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_43", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_44", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_45", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_46", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_47", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_48", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_49", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_50", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_51", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_52", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_53", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_54", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_55", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_56", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_57", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_58", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_59", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_60", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_61", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_62", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_63", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_64", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_65", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_66", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_67", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_68", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_69", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_70", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_71", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_72", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_73", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_74", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_75", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_76", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_77", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_78", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_79", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_80", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_81", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_82", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_83", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_84", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_85", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_86", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_87", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_88", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_89", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_90", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_91", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_92", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_93", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_94", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_95", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_96", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_97", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_98", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_99", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_100", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_101", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_102", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_103", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_104", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_105", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_106", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_107", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_108", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_109", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_110", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_111", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_112", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_113", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_114", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_115", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_116", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_117", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_118", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_119", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_120", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_121", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_122", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_123", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_124", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_125", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_126", + "dtype": "float32", + "feature_type": "continuous" + }, + { + "name": "feat_127", + "dtype": "float32", + "feature_type": "continuous" + } + ], + "features_path": "field_of_study.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "field_of_study" + }, + "params": { + "gpu": true + } + } + ] + } + ], + "edges": [ + { + "name": "affiliated_with", + "count": 1043998, + "src_node_type": "author", + "dst_node_type": "institution", + "directed": false, + "features": [ + { + "name": "feat", + "dtype": "int64", + "feature_type": "categorical" + } + ], + "features_path": "affiliated_with_features.parquet", + "structure_path": "affiliated_with_list.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "affiliated_with" + }, + "params": { + "gpu": true + } + } + ], + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "affiliated_with" + }, + "params": { + "seed": 42, + "gpu": true + } + } + }, + { + "name": "writes", + "count": 7145660, + "src_node_type": "author", + "dst_node_type": "paper", + "directed": false, + "features": [ + { + "name": "feat", + "dtype": "int64", + "feature_type": "categorical" + } + ], + "features_path": "writes_features.parquet", + "structure_path": "writes_list.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "writes" + }, + "params": { + "gpu": true + } + } + ], + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "writes" + }, + "params": { + "seed": 42, + "gpu": true + } + } + }, + { + "name": "cites", + "count": 5416271, + "src_node_type": "paper", + "dst_node_type": "paper", + "directed": false, + "features": [ + { + "name": "feat", + "dtype": "int64", + "feature_type": "categorical" + } + ], + "features_path": "cites_features.parquet", + "structure_path": "cites_list.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "cites" + }, + "params": { + "gpu": true + } + } + ], + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "cites" + }, + "params": { + "seed": 42, + "gpu": true + } + } + }, + { + "name": "has_topic", + "count": 7505078, + "src_node_type": "paper", + "dst_node_type": "field_of_study", + "directed": false, + "features": [ + { + "name": "feat", + "dtype": "int64", + "feature_type": "categorical" + } + ], + "features_path": "has_topic_features.parquet", + "structure_path": "has_topic_list.parquet", + "[gen]tabular_generators": [ + { + "type": "kde", + "features_list": -1, + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "has_topic" + }, + "params": { + "gpu": true + } + } + ], + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/workspace/data/ogbn_mag/syngen_preprocessed", + "name": "has_topic" + }, + "params": { + "seed": 42, + "gpu": true + } + } + } + ] +} \ No newline at end of file diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ogbn_mag240m.json b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ogbn_mag240m.json new file mode 100644 index 000000000..a0bebcb90 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/configurations/ogbn_mag240m.json @@ -0,0 +1,5504 @@ +{ + "nodes": [ + { + "name": "paper", + "count": 121751666, + "features": [ + { + "name": "feat_0", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_1", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_2", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_3", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_4", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_5", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_6", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_7", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_8", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_9", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_10", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_11", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_12", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_13", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_14", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_15", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_16", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_17", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_18", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_19", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_20", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_21", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_22", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_23", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_24", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_25", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_26", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_27", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_28", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_29", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_30", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_31", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_32", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_33", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_34", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_35", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_36", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_37", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_38", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_39", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_40", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_41", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_42", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_43", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_44", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_45", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_46", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_47", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_48", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_49", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_50", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_51", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_52", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_53", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_54", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_55", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_56", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_57", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_58", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_59", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_60", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_61", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_62", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_63", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_64", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_65", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_66", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_67", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_68", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_69", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_70", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_71", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_72", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_73", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_74", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_75", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_76", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_77", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_78", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_79", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_80", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_81", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_82", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_83", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_84", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_85", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_86", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_87", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_88", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_89", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_90", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_91", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_92", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_93", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_94", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_95", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_96", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_97", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_98", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_99", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_100", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_101", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_102", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_103", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_104", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_105", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_106", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_107", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_108", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_109", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_110", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_111", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_112", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_113", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_114", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_115", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_116", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_117", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_118", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_119", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_120", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_121", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_122", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_123", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_124", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_125", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_126", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_127", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_128", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_129", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_130", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_131", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_132", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_133", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_134", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_135", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_136", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_137", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_138", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_139", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_140", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_141", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_142", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_143", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_144", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_145", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_146", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_147", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_148", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_149", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_150", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_151", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_152", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_153", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_154", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_155", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_156", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_157", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_158", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_159", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_160", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_161", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_162", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_163", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_164", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_165", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_166", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_167", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_168", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_169", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_170", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_171", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_172", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_173", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_174", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_175", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_176", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_177", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_178", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_179", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_180", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_181", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_182", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_183", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_184", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_185", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_186", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_187", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_188", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_189", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_190", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_191", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_192", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_193", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_194", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_195", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_196", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_197", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_198", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_199", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_200", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_201", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_202", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_203", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_204", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_205", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_206", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_207", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_208", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_209", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_210", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_211", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_212", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_213", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_214", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_215", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_216", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_217", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_218", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_219", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_220", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_221", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_222", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_223", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_224", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_225", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_226", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_227", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_228", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_229", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_230", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_231", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_232", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_233", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_234", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_235", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_236", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_237", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_238", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_239", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_240", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_241", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_242", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_243", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_244", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_245", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_246", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_247", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_248", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_249", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_250", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_251", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_252", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_253", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_254", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_255", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_256", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_257", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_258", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_259", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_260", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_261", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_262", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_263", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_264", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_265", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_266", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_267", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_268", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_269", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_270", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_271", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_272", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_273", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_274", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_275", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_276", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_277", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_278", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_279", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_280", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_281", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_282", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_283", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_284", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_285", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_286", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_287", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_288", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_289", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_290", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_291", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_292", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_293", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_294", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_295", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_296", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_297", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_298", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_299", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_300", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_301", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_302", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_303", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_304", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_305", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_306", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_307", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_308", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_309", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_310", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_311", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_312", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_313", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_314", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_315", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_316", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_317", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_318", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_319", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_320", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_321", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_322", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_323", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_324", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_325", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_326", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_327", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_328", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_329", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_330", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_331", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_332", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_333", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_334", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_335", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_336", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_337", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_338", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_339", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_340", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_341", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_342", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_343", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_344", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_345", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_346", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_347", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_348", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_349", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_350", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_351", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_352", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_353", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_354", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_355", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_356", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_357", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_358", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_359", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_360", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_361", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_362", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_363", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_364", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_365", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_366", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_367", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_368", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_369", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_370", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_371", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_372", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_373", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_374", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_375", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_376", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_377", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_378", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_379", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_380", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_381", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_382", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_383", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_384", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_385", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_386", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_387", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_388", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_389", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_390", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_391", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_392", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_393", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_394", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_395", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_396", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_397", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_398", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_399", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_400", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_401", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_402", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_403", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_404", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_405", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_406", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_407", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_408", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_409", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_410", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_411", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_412", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_413", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_414", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_415", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_416", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_417", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_418", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_419", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_420", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_421", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_422", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_423", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_424", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_425", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_426", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_427", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_428", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_429", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_430", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_431", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_432", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_433", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_434", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_435", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_436", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_437", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_438", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_439", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_440", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_441", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_442", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_443", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_444", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_445", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_446", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_447", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_448", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_449", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_450", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_451", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_452", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_453", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_454", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_455", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_456", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_457", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_458", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_459", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_460", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_461", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_462", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_463", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_464", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_465", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_466", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_467", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_468", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_469", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_470", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_471", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_472", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_473", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_474", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_475", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_476", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_477", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_478", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_479", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_480", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_481", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_482", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_483", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_484", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_485", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_486", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_487", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_488", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_489", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_490", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_491", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_492", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_493", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_494", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_495", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_496", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_497", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_498", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_499", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_500", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_501", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_502", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_503", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_504", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_505", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_506", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_507", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_508", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_509", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_510", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_511", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_512", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_513", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_514", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_515", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_516", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_517", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_518", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_519", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_520", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_521", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_522", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_523", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_524", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_525", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_526", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_527", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_528", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_529", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_530", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_531", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_532", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_533", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_534", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_535", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_536", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_537", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_538", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_539", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_540", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_541", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_542", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_543", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_544", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_545", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_546", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_547", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_548", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_549", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_550", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_551", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_552", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_553", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_554", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_555", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_556", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_557", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_558", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_559", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_560", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_561", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_562", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_563", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_564", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_565", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_566", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_567", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_568", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_569", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_570", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_571", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_572", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_573", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_574", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_575", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_576", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_577", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_578", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_579", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_580", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_581", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_582", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_583", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_584", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_585", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_586", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_587", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_588", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_589", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_590", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_591", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_592", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_593", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_594", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_595", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_596", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_597", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_598", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_599", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_600", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_601", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_602", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_603", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_604", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_605", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_606", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_607", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_608", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_609", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_610", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_611", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_612", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_613", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_614", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_615", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_616", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_617", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_618", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_619", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_620", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_621", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_622", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_623", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_624", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_625", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_626", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_627", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_628", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_629", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_630", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_631", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_632", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_633", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_634", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_635", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_636", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_637", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_638", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_639", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_640", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_641", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_642", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_643", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_644", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_645", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_646", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_647", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_648", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_649", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_650", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_651", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_652", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_653", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_654", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_655", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_656", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_657", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_658", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_659", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_660", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_661", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_662", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_663", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_664", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_665", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_666", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_667", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_668", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_669", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_670", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_671", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_672", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_673", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_674", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_675", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_676", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_677", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_678", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_679", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_680", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_681", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_682", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_683", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_684", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_685", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_686", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_687", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_688", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_689", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_690", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_691", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_692", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_693", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_694", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_695", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_696", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_697", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_698", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_699", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_700", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_701", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_702", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_703", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_704", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_705", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_706", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_707", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_708", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_709", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_710", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_711", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_712", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_713", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_714", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_715", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_716", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_717", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_718", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_719", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_720", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_721", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_722", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_723", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_724", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_725", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_726", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_727", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_728", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_729", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_730", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_731", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_732", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_733", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_734", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_735", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_736", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_737", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_738", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_739", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_740", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_741", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_742", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_743", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_744", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_745", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_746", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_747", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_748", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_749", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_750", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_751", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_752", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_753", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_754", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_755", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_756", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_757", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_758", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_759", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_760", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_761", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_762", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_763", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_764", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_765", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_766", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "feat_767", + "dtype": "float16", + "feature_type": "continuous", + "feature_file": "paper_feats.npy" + }, + { + "name": "year", + "dtype": "int32", + "feature_type": "categorical", + "feature_file": "year_label.npy" + }, + { + "name": "label", + "dtype": "int32", + "feature_type": "categorical", + "feature_file": "year_label.npy" + } + ], + "features_path": "paper_tabular_features", + "[gen]tabular_generators": [ + { + "type": "uniform", + "features_list": [ + "feat_0", + "feat_1", + "feat_2", + "feat_3", + "feat_4", + "feat_5", + "feat_6", + "feat_7", + "feat_8", + "feat_9", + "feat_10", + "feat_11", + "feat_12", + "feat_13", + "feat_14", + "feat_15", + "feat_16", + "feat_17", + "feat_18", + "feat_19", + "feat_20", + "feat_21", + "feat_22", + "feat_23", + "feat_24", + "feat_25", + "feat_26", + "feat_27", + "feat_28", + "feat_29", + "feat_30", + "feat_31", + "feat_32", + "feat_33", + "feat_34", + "feat_35", + "feat_36", + "feat_37", + "feat_38", + "feat_39", + "feat_40", + "feat_41", + "feat_42", + "feat_43", + "feat_44", + "feat_45", + "feat_46", + "feat_47", + "feat_48", + "feat_49", + "feat_50", + "feat_51", + "feat_52", + "feat_53", + "feat_54", + "feat_55", + "feat_56", + "feat_57", + "feat_58", + "feat_59", + "feat_60", + "feat_61", + "feat_62", + "feat_63", + "feat_64", + "feat_65", + "feat_66", + "feat_67", + "feat_68", + "feat_69", + "feat_70", + "feat_71", + "feat_72", + "feat_73", + "feat_74", + "feat_75", + "feat_76", + "feat_77", + "feat_78", + "feat_79", + "feat_80", + "feat_81", + "feat_82", + "feat_83", + "feat_84", + "feat_85", + "feat_86", + "feat_87", + "feat_88", + "feat_89", + "feat_90", + "feat_91", + "feat_92", + "feat_93", + "feat_94", + "feat_95", + "feat_96", + "feat_97", + "feat_98", + "feat_99", + "feat_100", + "feat_101", + "feat_102", + "feat_103", + "feat_104", + "feat_105", + "feat_106", + "feat_107", + "feat_108", + "feat_109", + "feat_110", + "feat_111", + "feat_112", + "feat_113", + "feat_114", + "feat_115", + "feat_116", + "feat_117", + "feat_118", + "feat_119", + "feat_120", + "feat_121", + "feat_122", + "feat_123", + "feat_124", + "feat_125", + "feat_126", + "feat_127", + "feat_128", + "feat_129", + "feat_130", + "feat_131", + "feat_132", + "feat_133", + "feat_134", + "feat_135", + "feat_136", + "feat_137", + "feat_138", + "feat_139", + "feat_140", + "feat_141", + "feat_142", + "feat_143", + "feat_144", + "feat_145", + "feat_146", + "feat_147", + "feat_148", + "feat_149", + "feat_150", + "feat_151", + "feat_152", + "feat_153", + "feat_154", + "feat_155", + "feat_156", + "feat_157", + "feat_158", + "feat_159", + "feat_160", + "feat_161", + "feat_162", + "feat_163", + "feat_164", + "feat_165", + "feat_166", + "feat_167", + "feat_168", + "feat_169", + "feat_170", + "feat_171", + "feat_172", + "feat_173", + "feat_174", + "feat_175", + "feat_176", + "feat_177", + "feat_178", + "feat_179", + "feat_180", + "feat_181", + "feat_182", + "feat_183", + "feat_184", + "feat_185", + "feat_186", + "feat_187", + "feat_188", + "feat_189", + "feat_190", + "feat_191", + "feat_192", + "feat_193", + "feat_194", + "feat_195", + "feat_196", + "feat_197", + "feat_198", + "feat_199", + "feat_200", + "feat_201", + "feat_202", + "feat_203", + "feat_204", + "feat_205", + "feat_206", + "feat_207", + "feat_208", + "feat_209", + "feat_210", + "feat_211", + "feat_212", + "feat_213", + "feat_214", + "feat_215", + "feat_216", + "feat_217", + "feat_218", + "feat_219", + "feat_220", + "feat_221", + "feat_222", + "feat_223", + "feat_224", + "feat_225", + "feat_226", + "feat_227", + "feat_228", + "feat_229", + "feat_230", + "feat_231", + "feat_232", + "feat_233", + "feat_234", + "feat_235", + "feat_236", + "feat_237", + "feat_238", + "feat_239", + "feat_240", + "feat_241", + "feat_242", + "feat_243", + "feat_244", + "feat_245", + "feat_246", + "feat_247", + "feat_248", + "feat_249", + "feat_250", + "feat_251", + "feat_252", + "feat_253", + "feat_254", + "feat_255", + "feat_256", + "feat_257", + "feat_258", + "feat_259", + "feat_260", + "feat_261", + "feat_262", + "feat_263", + "feat_264", + "feat_265", + "feat_266", + "feat_267", + "feat_268", + "feat_269", + "feat_270", + "feat_271", + "feat_272", + "feat_273", + "feat_274", + "feat_275", + "feat_276", + "feat_277", + "feat_278", + "feat_279", + "feat_280", + "feat_281", + "feat_282", + "feat_283", + "feat_284", + "feat_285", + "feat_286", + "feat_287", + "feat_288", + "feat_289", + "feat_290", + "feat_291", + "feat_292", + "feat_293", + "feat_294", + "feat_295", + "feat_296", + "feat_297", + "feat_298", + "feat_299", + "feat_300", + "feat_301", + "feat_302", + "feat_303", + "feat_304", + "feat_305", + "feat_306", + "feat_307", + "feat_308", + "feat_309", + "feat_310", + "feat_311", + "feat_312", + "feat_313", + "feat_314", + "feat_315", + "feat_316", + "feat_317", + "feat_318", + "feat_319", + "feat_320", + "feat_321", + "feat_322", + "feat_323", + "feat_324", + "feat_325", + "feat_326", + "feat_327", + "feat_328", + "feat_329", + "feat_330", + "feat_331", + "feat_332", + "feat_333", + "feat_334", + "feat_335", + "feat_336", + "feat_337", + "feat_338", + "feat_339", + "feat_340", + "feat_341", + "feat_342", + "feat_343", + "feat_344", + "feat_345", + "feat_346", + "feat_347", + "feat_348", + "feat_349", + "feat_350", + "feat_351", + "feat_352", + "feat_353", + "feat_354", + "feat_355", + "feat_356", + "feat_357", + "feat_358", + "feat_359", + "feat_360", + "feat_361", + "feat_362", + "feat_363", + "feat_364", + "feat_365", + "feat_366", + "feat_367", + "feat_368", + "feat_369", + "feat_370", + "feat_371", + "feat_372", + "feat_373", + "feat_374", + "feat_375", + "feat_376", + "feat_377", + "feat_378", + "feat_379", + "feat_380", + "feat_381", + "feat_382", + "feat_383", + "feat_384", + "feat_385", + "feat_386", + "feat_387", + "feat_388", + "feat_389", + "feat_390", + "feat_391", + "feat_392", + "feat_393", + "feat_394", + "feat_395", + "feat_396", + "feat_397", + "feat_398", + "feat_399", + "feat_400", + "feat_401", + "feat_402", + "feat_403", + "feat_404", + "feat_405", + "feat_406", + "feat_407", + "feat_408", + "feat_409", + "feat_410", + "feat_411", + "feat_412", + "feat_413", + "feat_414", + "feat_415", + "feat_416", + "feat_417", + "feat_418", + "feat_419", + "feat_420", + "feat_421", + "feat_422", + "feat_423", + "feat_424", + "feat_425", + "feat_426", + "feat_427", + "feat_428", + "feat_429", + "feat_430", + "feat_431", + "feat_432", + "feat_433", + "feat_434", + "feat_435", + "feat_436", + "feat_437", + "feat_438", + "feat_439", + "feat_440", + "feat_441", + "feat_442", + "feat_443", + "feat_444", + "feat_445", + "feat_446", + "feat_447", + "feat_448", + "feat_449", + "feat_450", + "feat_451", + "feat_452", + "feat_453", + "feat_454", + "feat_455", + "feat_456", + "feat_457", + "feat_458", + "feat_459", + "feat_460", + "feat_461", + "feat_462", + "feat_463", + "feat_464", + "feat_465", + "feat_466", + "feat_467", + "feat_468", + "feat_469", + "feat_470", + "feat_471", + "feat_472", + "feat_473", + "feat_474", + "feat_475", + "feat_476", + "feat_477", + "feat_478", + "feat_479", + "feat_480", + "feat_481", + "feat_482", + "feat_483", + "feat_484", + "feat_485", + "feat_486", + "feat_487", + "feat_488", + "feat_489", + "feat_490", + "feat_491", + "feat_492", + "feat_493", + "feat_494", + "feat_495", + "feat_496", + "feat_497", + "feat_498", + "feat_499", + "feat_500", + "feat_501", + "feat_502", + "feat_503", + "feat_504", + "feat_505", + "feat_506", + "feat_507", + "feat_508", + "feat_509", + "feat_510", + "feat_511", + "feat_512", + "feat_513", + "feat_514", + "feat_515", + "feat_516", + "feat_517", + "feat_518", + "feat_519", + "feat_520", + "feat_521", + "feat_522", + "feat_523", + "feat_524", + "feat_525", + "feat_526", + "feat_527", + "feat_528", + "feat_529", + "feat_530", + "feat_531", + "feat_532", + "feat_533", + "feat_534", + "feat_535", + "feat_536", + "feat_537", + "feat_538", + "feat_539", + "feat_540", + "feat_541", + "feat_542", + "feat_543", + "feat_544", + "feat_545", + "feat_546", + "feat_547", + "feat_548", + "feat_549", + "feat_550", + "feat_551", + "feat_552", + "feat_553", + "feat_554", + "feat_555", + "feat_556", + "feat_557", + "feat_558", + "feat_559", + "feat_560", + "feat_561", + "feat_562", + "feat_563", + "feat_564", + "feat_565", + "feat_566", + "feat_567", + "feat_568", + "feat_569", + "feat_570", + "feat_571", + "feat_572", + "feat_573", + "feat_574", + "feat_575", + "feat_576", + "feat_577", + "feat_578", + "feat_579", + "feat_580", + "feat_581", + "feat_582", + "feat_583", + "feat_584", + "feat_585", + "feat_586", + "feat_587", + "feat_588", + "feat_589", + "feat_590", + "feat_591", + "feat_592", + "feat_593", + "feat_594", + "feat_595", + "feat_596", + "feat_597", + "feat_598", + "feat_599", + "feat_600", + "feat_601", + "feat_602", + "feat_603", + "feat_604", + "feat_605", + "feat_606", + "feat_607", + "feat_608", + "feat_609", + "feat_610", + "feat_611", + "feat_612", + "feat_613", + "feat_614", + "feat_615", + "feat_616", + "feat_617", + "feat_618", + "feat_619", + "feat_620", + "feat_621", + "feat_622", + "feat_623", + "feat_624", + "feat_625", + "feat_626", + "feat_627", + "feat_628", + "feat_629", + "feat_630", + "feat_631", + "feat_632", + "feat_633", + "feat_634", + "feat_635", + "feat_636", + "feat_637", + "feat_638", + "feat_639", + "feat_640", + "feat_641", + "feat_642", + "feat_643", + "feat_644", + "feat_645", + "feat_646", + "feat_647", + "feat_648", + "feat_649", + "feat_650", + "feat_651", + "feat_652", + "feat_653", + "feat_654", + "feat_655", + "feat_656", + "feat_657", + "feat_658", + "feat_659", + "feat_660", + "feat_661", + "feat_662", + "feat_663", + "feat_664", + "feat_665", + "feat_666", + "feat_667", + "feat_668", + "feat_669", + "feat_670", + "feat_671", + "feat_672", + "feat_673", + "feat_674", + "feat_675", + "feat_676", + "feat_677", + "feat_678", + "feat_679", + "feat_680", + "feat_681", + "feat_682", + "feat_683", + "feat_684", + "feat_685", + "feat_686", + "feat_687", + "feat_688", + "feat_689", + "feat_690", + "feat_691", + "feat_692", + "feat_693", + "feat_694", + "feat_695", + "feat_696", + "feat_697", + "feat_698", + "feat_699", + "feat_700", + "feat_701", + "feat_702", + "feat_703", + "feat_704", + "feat_705", + "feat_706", + "feat_707", + "feat_708", + "feat_709", + "feat_710", + "feat_711", + "feat_712", + "feat_713", + "feat_714", + "feat_715", + "feat_716", + "feat_717", + "feat_718", + "feat_719", + "feat_720", + "feat_721", + "feat_722", + "feat_723", + "feat_724", + "feat_725", + "feat_726", + "feat_727", + "feat_728", + "feat_729", + "feat_730", + "feat_731", + "feat_732", + "feat_733", + "feat_734", + "feat_735", + "feat_736", + "feat_737", + "feat_738", + "feat_739", + "feat_740", + "feat_741", + "feat_742", + "feat_743", + "feat_744", + "feat_745", + "feat_746", + "feat_747", + "feat_748", + "feat_749", + "feat_750", + "feat_751", + "feat_752", + "feat_753", + "feat_754", + "feat_755", + "feat_756", + "feat_757", + "feat_758", + "feat_759", + "feat_760", + "feat_761", + "feat_762", + "feat_763", + "feat_764", + "feat_765", + "feat_766", + "feat_767" + ], + "feature_file": "paper_feats.npy", + "data_source": { + "type": "cfg", + "path": "/raid/ogbn_mag240m_syngen", + "name": "paper" + }, + "params": {}, + "dump_path": null + }, + { + "type": "uniform", + "features_list": [ + "year", + "label" + ], + "feature_file": "year_label.npy", + "data_source": { + "type": "cfg", + "path": "/raid/ogbn_mag240m_syngen", + "name": "paper" + }, + "params": {}, + "dump_path": null + } + ] + }, + { + "name": "author", + "count": 122383112, + "features_path": null, + "features": [] + }, + { + "name": "institution", + "count": 25721, + "features_path": null, + "features": [] + } + ], + "edges": [ + { + "name": "writes", + "count": 386022720, + "src_node_type": "author", + "dst_node_type": "paper", + "directed": false, + "features": [], + "features_path": null, + "structure_path": "writes_list.parquet", + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/raid/ogbn_mag240m_syngen", + "name": "writes" + }, + "params": {}, + "dump_path": null + } + }, + { + "name": "affiliated_with", + "count": 44592586, + "src_node_type": "author", + "dst_node_type": "institution", + "directed": false, + "features": [], + "features_path": null, + "structure_path": "affiliated_with_list.parquet", + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/raid/ogbn_mag240m_syngen", + "name": "affiliated_with" + }, + "params": {}, + "dump_path": null + } + }, + { + "name": "cites", + "count": 1297748926, + "src_node_type": "paper", + "dst_node_type": "paper", + "directed": false, + "features": [], + "features_path": null, + "structure_path": "cites_list.parquet", + "[gen]structure_generator": { + "type": "RMAT", + "data_source": { + "type": "cfg", + "path": "/raid/ogbn_mag240m_syngen", + "name": "cites" + }, + "params": {}, + "dump_path": null + } + } + ], + "path": "/raid/ogbn_mag240m_syngen" +} \ No newline at end of file diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/advanced_examples/big_graph_generation.ipynb b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/advanced_examples/big_graph_generation.ipynb new file mode 100644 index 000000000..4050a2310 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/advanced_examples/big_graph_generation.ipynb @@ -0,0 +1,16428 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "4b68ee46", + "metadata": {}, + "source": [ + "# Copyright 2023 NVIDIA Corporation. All Rights Reserved.\n", + "#\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# http://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License.\n", + "# ==============================================================================" + ] + }, + { + "cell_type": "markdown", + "id": "d02546a4", + "metadata": {}, + "source": [ + "# Big Graph Generation (MAG240m)" + ] + }, + { + "cell_type": "markdown", + "id": "5a622565", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "In this notebook, we have walked through the complete process of generating a synthetic dataset based on an MAG240m dataset.\n", + "We will cover advanced SynGen features as memmory mapping and independent chunk generation." + ] + }, + { + "cell_type": "markdown", + "id": "2691dc29", + "metadata": {}, + "source": [ + "## Preprare the dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9bd32152", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = '/raid/ogbn_mag240m/'\n", + "preprocessed_path = '/raid/ogbn_mag240m_syngen'" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0034fa78", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_syngen/writes_list.parquet parquet\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_syngen/affiliated_with_list.parquet parquet\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_syngen/cites_list.parquet parquet\n", + "INFO:syngen.cli.commands.preprocess:ogbn_mag240m successfully preprocessed into /raid/ogbn_mag240m_syngen\n" + ] + } + ], + "source": [ + "!python -m syngen preprocess --source-path=$data_path --dataset=ogbn_mag240m --destination-path=$preprocessed_path --cpu --use-cache" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0205eaae", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"nodes\": [\n", + " {\n", + " \"name\": \"paper\",\n", + " \"count\": 121751666,\n", + " \"features\": [\n", + " {\n", + " \"name\": \"feat_0\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_1\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_2\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_3\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_4\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_5\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_6\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_7\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_8\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_9\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_10\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_11\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_12\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_13\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_14\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_15\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_16\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_17\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_18\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_19\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_20\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_21\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_22\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_23\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_24\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_25\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_26\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_27\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_28\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_29\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_30\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_31\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_32\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_33\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_34\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_35\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_36\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_37\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_38\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_39\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_40\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_41\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_42\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_43\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_44\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_45\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_46\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_47\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_48\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_49\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_50\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_51\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_52\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_53\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_54\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_55\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_56\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_57\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_58\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_59\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_60\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_61\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_62\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_63\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_64\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_65\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_66\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_67\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_68\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_69\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_70\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_71\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_72\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_73\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_74\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_75\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_76\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_77\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_78\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_79\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_80\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_81\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_82\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_83\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_84\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_85\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_86\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_87\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_88\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_89\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_90\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_91\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_92\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_93\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_94\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_95\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_96\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_97\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_98\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_99\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_100\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_101\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_102\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_103\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_104\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_105\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_106\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_107\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_108\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_109\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_110\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_111\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_112\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_113\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_114\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_115\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_116\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_117\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_118\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_119\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_120\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_121\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_122\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_123\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_124\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_125\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_126\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_127\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_128\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_129\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_130\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_131\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_132\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_133\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_134\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_135\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_136\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_137\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_138\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_139\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_140\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_141\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_142\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_143\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_144\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_145\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_146\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_147\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_148\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_149\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_150\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_151\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_152\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_153\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_154\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_155\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_156\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_157\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_158\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_159\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_160\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_161\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_162\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_163\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_164\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_165\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_166\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_167\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_168\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_169\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_170\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_171\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_172\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_173\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_174\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_175\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_176\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_177\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_178\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_179\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_180\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_181\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_182\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_183\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_184\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_185\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_186\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_187\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_188\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_189\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_190\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_191\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_192\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_193\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_194\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_195\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_196\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_197\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_198\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_199\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_200\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_201\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_202\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_203\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_204\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_205\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_206\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_207\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_208\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_209\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_210\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_211\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_212\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_213\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_214\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_215\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_216\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_217\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_218\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_219\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_220\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_221\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_222\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_223\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_224\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_225\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_226\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_227\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_228\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_229\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_230\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_231\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_232\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_233\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_234\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_235\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_236\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_237\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_238\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_239\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_240\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_241\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_242\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_243\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_244\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_245\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_246\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_247\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_248\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_249\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_250\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_251\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_252\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_253\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_254\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_255\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_256\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_257\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_258\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_259\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_260\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_261\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_262\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_263\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_264\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_265\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_266\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_267\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_268\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_269\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_270\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_271\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_272\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_273\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_274\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_275\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_276\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_277\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_278\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_279\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_280\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_281\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_282\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_283\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_284\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_285\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_286\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_287\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_288\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_289\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_290\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_291\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_292\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_293\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_294\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_295\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_296\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_297\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_298\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_299\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_300\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_301\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_302\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_303\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_304\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_305\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_306\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_307\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_308\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_309\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_310\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_311\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_312\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_313\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_314\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_315\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_316\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_317\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_318\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_319\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_320\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_321\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_322\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_323\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_324\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_325\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_326\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_327\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_328\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_329\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_330\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_331\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_332\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_333\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_334\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_335\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_336\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_337\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_338\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_339\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_340\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_341\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_342\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_343\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_344\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_345\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_346\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_347\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_348\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_349\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_350\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_351\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_352\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_353\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_354\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_355\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_356\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_357\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_358\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_359\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_360\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_361\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_362\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_363\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_364\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_365\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_366\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_367\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_368\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_369\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_370\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_371\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_372\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_373\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_374\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_375\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_376\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_377\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_378\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_379\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_380\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_381\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_382\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_383\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_384\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_385\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_386\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_387\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_388\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_389\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_390\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_391\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_392\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_393\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_394\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_395\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_396\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_397\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_398\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_399\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_400\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_401\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_402\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_403\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_404\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_405\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_406\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_407\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_408\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_409\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_410\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_411\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_412\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_413\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_414\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_415\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_416\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_417\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_418\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_419\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_420\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_421\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_422\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_423\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_424\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_425\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_426\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_427\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_428\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_429\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_430\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_431\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_432\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_433\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_434\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_435\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_436\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_437\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_438\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_439\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_440\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_441\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_442\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_443\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_444\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_445\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_446\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_447\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_448\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_449\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_450\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_451\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_452\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_453\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_454\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_455\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_456\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_457\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_458\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_459\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_460\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_461\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_462\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_463\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_464\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_465\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_466\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_467\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_468\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_469\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_470\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_471\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_472\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_473\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_474\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_475\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_476\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_477\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_478\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_479\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_480\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_481\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_482\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_483\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_484\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_485\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_486\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_487\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_488\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_489\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_490\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_491\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_492\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_493\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_494\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_495\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_496\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_497\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_498\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_499\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_500\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_501\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_502\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_503\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_504\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_505\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_506\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_507\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_508\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_509\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_510\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_511\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_512\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_513\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_514\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_515\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_516\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_517\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_518\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_519\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_520\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_521\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_522\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_523\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_524\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_525\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_526\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_527\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_528\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_529\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_530\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_531\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_532\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_533\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_534\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_535\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_536\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_537\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_538\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_539\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_540\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_541\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_542\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_543\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_544\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_545\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_546\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_547\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_548\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_549\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_550\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_551\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_552\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_553\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_554\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_555\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_556\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_557\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_558\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_559\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_560\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_561\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_562\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_563\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_564\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_565\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_566\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_567\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_568\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_569\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_570\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_571\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_572\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_573\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_574\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_575\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_576\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_577\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_578\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_579\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_580\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_581\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_582\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_583\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_584\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_585\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_586\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_587\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_588\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_589\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_590\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_591\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_592\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_593\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_594\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_595\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_596\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_597\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_598\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_599\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_600\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_601\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_602\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_603\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_604\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_605\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_606\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_607\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_608\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_609\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_610\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_611\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_612\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_613\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_614\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_615\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_616\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_617\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_618\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_619\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_620\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_621\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_622\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_623\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_624\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_625\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_626\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_627\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_628\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_629\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_630\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_631\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_632\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_633\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_634\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_635\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_636\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_637\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_638\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_639\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_640\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_641\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_642\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_643\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_644\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_645\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_646\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_647\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_648\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_649\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_650\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_651\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_652\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_653\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_654\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_655\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_656\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_657\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_658\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_659\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_660\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_661\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_662\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_663\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_664\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_665\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_666\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_667\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_668\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_669\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_670\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_671\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_672\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_673\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_674\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_675\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_676\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_677\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_678\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_679\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_680\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_681\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_682\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_683\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_684\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_685\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_686\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_687\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_688\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_689\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_690\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_691\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_692\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_693\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_694\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_695\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_696\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_697\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_698\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_699\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_700\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_701\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_702\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_703\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_704\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_705\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_706\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_707\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_708\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_709\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_710\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_711\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_712\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_713\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_714\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_715\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_716\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_717\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_718\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_719\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_720\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_721\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_722\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_723\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_724\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_725\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_726\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_727\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_728\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_729\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_730\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_731\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_732\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_733\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_734\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_735\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_736\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_737\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_738\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_739\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_740\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_741\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_742\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_743\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_744\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_745\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_746\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_747\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_748\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_749\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_750\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_751\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_752\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_753\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_754\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_755\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_756\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_757\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_758\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_759\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_760\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_761\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_762\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_763\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_764\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_765\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_766\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_767\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"year\",\n", + " \"dtype\": \"int32\",\n", + " \"feature_type\": \"categorical\",\n", + " \"feature_file\": \"year_label.npy\"\n", + " },\n", + " {\n", + " \"name\": \"label\",\n", + " \"dtype\": \"int32\",\n", + " \"feature_type\": \"categorical\",\n", + " \"feature_file\": \"year_label.npy\"\n", + " }\n", + " ],\n", + " \"features_path\": \"paper_tabular_features\"\n", + " },\n", + " {\n", + " \"name\": \"author\",\n", + " \"count\": 122383112,\n", + " \"features_path\": null\n", + " },\n", + " {\n", + " \"name\": \"institution\",\n", + " \"count\": 25721,\n", + " \"features_path\": null\n", + " }\n", + " ],\n", + " \"edges\": [\n", + " {\n", + " \"name\": \"writes\",\n", + " \"count\": 386022720,\n", + " \"src_node_type\": \"author\",\n", + " \"dst_node_type\": \"paper\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"writes_list.parquet\"\n", + " },\n", + " {\n", + " \"name\": \"affiliated_with\",\n", + " \"count\": 44592586,\n", + " \"src_node_type\": \"author\",\n", + " \"dst_node_type\": \"institution\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"affiliated_with_list.parquet\"\n", + " },\n", + " {\n", + " \"name\": \"cites\",\n", + " \"count\": 1297748926,\n", + " \"src_node_type\": \"paper\",\n", + " \"dst_node_type\": \"paper\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"cites_list.parquet\"\n", + " }\n", + " ]\n", + "}" + ] + } + ], + "source": [ + "!cat $preprocessed_path/graph_metadata.json" + ] + }, + { + "cell_type": "markdown", + "id": "b951ceb4", + "metadata": {}, + "source": [ + "## Create Configurations Directory" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e182154f", + "metadata": {}, + "outputs": [], + "source": [ + "configs_dir = 'ogbn_mag240m_configs'" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "de4f2c86", + "metadata": {}, + "outputs": [], + "source": [ + "!mkdir -p $configs_dir" + ] + }, + { + "cell_type": "markdown", + "id": "ea8bf73e", + "metadata": {}, + "source": [ + "## Prepare simple SynGen Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e31275e8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "INFO:syngen.cli.commands.mimic_dataset:SynGen Configuration saved into ogbn_mag240m_configs/simple.json\n" + ] + } + ], + "source": [ + "!python -m syngen mimic-dataset --output-file=$configs_dir/simple.json --dataset-path $preprocessed_path --tab-gen uniform" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "90478272", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"nodes\": [\n", + " {\n", + " \"name\": \"paper\",\n", + " \"count\": 121751666,\n", + " \"features\": [\n", + " {\n", + " \"name\": \"feat_0\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_1\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_2\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_3\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_4\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_5\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_6\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_7\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_8\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_9\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_10\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_11\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_12\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_13\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_14\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_15\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_16\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_17\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_18\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_19\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_20\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_21\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_22\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_23\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_24\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_25\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_26\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_27\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_28\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_29\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_30\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_31\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_32\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_33\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_34\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_35\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_36\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_37\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_38\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_39\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_40\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_41\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_42\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_43\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_44\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_45\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_46\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_47\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_48\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_49\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_50\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_51\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_52\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_53\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_54\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_55\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_56\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_57\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_58\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_59\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_60\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_61\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_62\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_63\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_64\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_65\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_66\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_67\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_68\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_69\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_70\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_71\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_72\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_73\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_74\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_75\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_76\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_77\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_78\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_79\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_80\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_81\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_82\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_83\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_84\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_85\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_86\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_87\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_88\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_89\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_90\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_91\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_92\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_93\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_94\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_95\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_96\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_97\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_98\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_99\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_100\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_101\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_102\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_103\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_104\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_105\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_106\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_107\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_108\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_109\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_110\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_111\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_112\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_113\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_114\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_115\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_116\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_117\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_118\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_119\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_120\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_121\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_122\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_123\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_124\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_125\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_126\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_127\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_128\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_129\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_130\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_131\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_132\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_133\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_134\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_135\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_136\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_137\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_138\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_139\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_140\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_141\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_142\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_143\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_144\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_145\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_146\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_147\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_148\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_149\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_150\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_151\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_152\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_153\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_154\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_155\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_156\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_157\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_158\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_159\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_160\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_161\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_162\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_163\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_164\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_165\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_166\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_167\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_168\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_169\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_170\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_171\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_172\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_173\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_174\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_175\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_176\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_177\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_178\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_179\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_180\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_181\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_182\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_183\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_184\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_185\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_186\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_187\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_188\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_189\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_190\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_191\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_192\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_193\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_194\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_195\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_196\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_197\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_198\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_199\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_200\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_201\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_202\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_203\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_204\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_205\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_206\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_207\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_208\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_209\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_210\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_211\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_212\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_213\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_214\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_215\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_216\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_217\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_218\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_219\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_220\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_221\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_222\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_223\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_224\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_225\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_226\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_227\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_228\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_229\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_230\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_231\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_232\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_233\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_234\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_235\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_236\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_237\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_238\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_239\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_240\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_241\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_242\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_243\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_244\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_245\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_246\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_247\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_248\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_249\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_250\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_251\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_252\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_253\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_254\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_255\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_256\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_257\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_258\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_259\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_260\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_261\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_262\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_263\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_264\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_265\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_266\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_267\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_268\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_269\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_270\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_271\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_272\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_273\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_274\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_275\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_276\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_277\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_278\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_279\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_280\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_281\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_282\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_283\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_284\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_285\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_286\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_287\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_288\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_289\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_290\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_291\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_292\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_293\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_294\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_295\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_296\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_297\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_298\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_299\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_300\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_301\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_302\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_303\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_304\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_305\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_306\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_307\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_308\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_309\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_310\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_311\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_312\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_313\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_314\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_315\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_316\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_317\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_318\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_319\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_320\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_321\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_322\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_323\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_324\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_325\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_326\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_327\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_328\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_329\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_330\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_331\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_332\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_333\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_334\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_335\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_336\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_337\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_338\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_339\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_340\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_341\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_342\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_343\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_344\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_345\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_346\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_347\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_348\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_349\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_350\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_351\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_352\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_353\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_354\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_355\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_356\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_357\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_358\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_359\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_360\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_361\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_362\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_363\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_364\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_365\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_366\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_367\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_368\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_369\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_370\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_371\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_372\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_373\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_374\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_375\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_376\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_377\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_378\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_379\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_380\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_381\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_382\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_383\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_384\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_385\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_386\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_387\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_388\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_389\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_390\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_391\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_392\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_393\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_394\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_395\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_396\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_397\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_398\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_399\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_400\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_401\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_402\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_403\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_404\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_405\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_406\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_407\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_408\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_409\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_410\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_411\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_412\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_413\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_414\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_415\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_416\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_417\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_418\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_419\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_420\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_421\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_422\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_423\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_424\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_425\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_426\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_427\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_428\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_429\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_430\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_431\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_432\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_433\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_434\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_435\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_436\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_437\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_438\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_439\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_440\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_441\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_442\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_443\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_444\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_445\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_446\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_447\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_448\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_449\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_450\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_451\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_452\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_453\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_454\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_455\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_456\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_457\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_458\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_459\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_460\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_461\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_462\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_463\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_464\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_465\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_466\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_467\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_468\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_469\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_470\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_471\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_472\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_473\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_474\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_475\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_476\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_477\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_478\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_479\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_480\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_481\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_482\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_483\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_484\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_485\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_486\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_487\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_488\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_489\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_490\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_491\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_492\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_493\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_494\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_495\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_496\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_497\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_498\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_499\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_500\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_501\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_502\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_503\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_504\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_505\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_506\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_507\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_508\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_509\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_510\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_511\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_512\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_513\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_514\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_515\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_516\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_517\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_518\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_519\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_520\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_521\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_522\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_523\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_524\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_525\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_526\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_527\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_528\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_529\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_530\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_531\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_532\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_533\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_534\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_535\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_536\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_537\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_538\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_539\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_540\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_541\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_542\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_543\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_544\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_545\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_546\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_547\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_548\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_549\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_550\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_551\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_552\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_553\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_554\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_555\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_556\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_557\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_558\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_559\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_560\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_561\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_562\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_563\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_564\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_565\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_566\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_567\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_568\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_569\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_570\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_571\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_572\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_573\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_574\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_575\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_576\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_577\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_578\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_579\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_580\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_581\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_582\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_583\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_584\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_585\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_586\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_587\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_588\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_589\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_590\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_591\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_592\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_593\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_594\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_595\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_596\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_597\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_598\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_599\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_600\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_601\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_602\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_603\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_604\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_605\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_606\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_607\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_608\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_609\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_610\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_611\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_612\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_613\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_614\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_615\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_616\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_617\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_618\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_619\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_620\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_621\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_622\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_623\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_624\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_625\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_626\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_627\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_628\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_629\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_630\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_631\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_632\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_633\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_634\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_635\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_636\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_637\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_638\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_639\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_640\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_641\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_642\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_643\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_644\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_645\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_646\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_647\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_648\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_649\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_650\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_651\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_652\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_653\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_654\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_655\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_656\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_657\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_658\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_659\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_660\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_661\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_662\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_663\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_664\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_665\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_666\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_667\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_668\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_669\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_670\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_671\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_672\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_673\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_674\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_675\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_676\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_677\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_678\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_679\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_680\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_681\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_682\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_683\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_684\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_685\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_686\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_687\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_688\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_689\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_690\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_691\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_692\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_693\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_694\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_695\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_696\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_697\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_698\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_699\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_700\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_701\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_702\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_703\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_704\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_705\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_706\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_707\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_708\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_709\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_710\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_711\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_712\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_713\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_714\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_715\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_716\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_717\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_718\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_719\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_720\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_721\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_722\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_723\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_724\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_725\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_726\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_727\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_728\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_729\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_730\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_731\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_732\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_733\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_734\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_735\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_736\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_737\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_738\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_739\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_740\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_741\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_742\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_743\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_744\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_745\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_746\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_747\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_748\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_749\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_750\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_751\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_752\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_753\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_754\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_755\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_756\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_757\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_758\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_759\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_760\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_761\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_762\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_763\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_764\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_765\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_766\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_767\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"year\",\n", + " \"dtype\": \"int32\",\n", + " \"feature_type\": \"categorical\",\n", + " \"feature_file\": \"year_label.npy\"\n", + " },\n", + " {\n", + " \"name\": \"label\",\n", + " \"dtype\": \"int32\",\n", + " \"feature_type\": \"categorical\",\n", + " \"feature_file\": \"year_label.npy\"\n", + " }\n", + " ],\n", + " \"features_path\": \"paper_tabular_features\",\n", + " \"[gen]tabular_generators\": [\n", + " {\n", + " \"type\": \"uniform\",\n", + " \"features_list\": [\n", + " \"feat_0\",\n", + " \"feat_1\",\n", + " \"feat_2\",\n", + " \"feat_3\",\n", + " \"feat_4\",\n", + " \"feat_5\",\n", + " \"feat_6\",\n", + " \"feat_7\",\n", + " \"feat_8\",\n", + " \"feat_9\",\n", + " \"feat_10\",\n", + " \"feat_11\",\n", + " \"feat_12\",\n", + " \"feat_13\",\n", + " \"feat_14\",\n", + " \"feat_15\",\n", + " \"feat_16\",\n", + " \"feat_17\",\n", + " \"feat_18\",\n", + " \"feat_19\",\n", + " \"feat_20\",\n", + " \"feat_21\",\n", + " \"feat_22\",\n", + " \"feat_23\",\n", + " \"feat_24\",\n", + " \"feat_25\",\n", + " \"feat_26\",\n", + " \"feat_27\",\n", + " \"feat_28\",\n", + " \"feat_29\",\n", + " \"feat_30\",\n", + " \"feat_31\",\n", + " \"feat_32\",\n", + " \"feat_33\",\n", + " \"feat_34\",\n", + " \"feat_35\",\n", + " \"feat_36\",\n", + " \"feat_37\",\n", + " \"feat_38\",\n", + " \"feat_39\",\n", + " \"feat_40\",\n", + " \"feat_41\",\n", + " \"feat_42\",\n", + " \"feat_43\",\n", + " \"feat_44\",\n", + " \"feat_45\",\n", + " \"feat_46\",\n", + " \"feat_47\",\n", + " \"feat_48\",\n", + " \"feat_49\",\n", + " \"feat_50\",\n", + " \"feat_51\",\n", + " \"feat_52\",\n", + " \"feat_53\",\n", + " \"feat_54\",\n", + " \"feat_55\",\n", + " \"feat_56\",\n", + " \"feat_57\",\n", + " \"feat_58\",\n", + " \"feat_59\",\n", + " \"feat_60\",\n", + " \"feat_61\",\n", + " \"feat_62\",\n", + " \"feat_63\",\n", + " \"feat_64\",\n", + " \"feat_65\",\n", + " \"feat_66\",\n", + " \"feat_67\",\n", + " \"feat_68\",\n", + " \"feat_69\",\n", + " \"feat_70\",\n", + " \"feat_71\",\n", + " \"feat_72\",\n", + " \"feat_73\",\n", + " \"feat_74\",\n", + " \"feat_75\",\n", + " \"feat_76\",\n", + " \"feat_77\",\n", + " \"feat_78\",\n", + " \"feat_79\",\n", + " \"feat_80\",\n", + " \"feat_81\",\n", + " \"feat_82\",\n", + " \"feat_83\",\n", + " \"feat_84\",\n", + " \"feat_85\",\n", + " \"feat_86\",\n", + " \"feat_87\",\n", + " \"feat_88\",\n", + " \"feat_89\",\n", + " \"feat_90\",\n", + " \"feat_91\",\n", + " \"feat_92\",\n", + " \"feat_93\",\n", + " \"feat_94\",\n", + " \"feat_95\",\n", + " \"feat_96\",\n", + " \"feat_97\",\n", + " \"feat_98\",\n", + " \"feat_99\",\n", + " \"feat_100\",\n", + " \"feat_101\",\n", + " \"feat_102\",\n", + " \"feat_103\",\n", + " \"feat_104\",\n", + " \"feat_105\",\n", + " \"feat_106\",\n", + " \"feat_107\",\n", + " \"feat_108\",\n", + " \"feat_109\",\n", + " \"feat_110\",\n", + " \"feat_111\",\n", + " \"feat_112\",\n", + " \"feat_113\",\n", + " \"feat_114\",\n", + " \"feat_115\",\n", + " \"feat_116\",\n", + " \"feat_117\",\n", + " \"feat_118\",\n", + " \"feat_119\",\n", + " \"feat_120\",\n", + " \"feat_121\",\n", + " \"feat_122\",\n", + " \"feat_123\",\n", + " \"feat_124\",\n", + " \"feat_125\",\n", + " \"feat_126\",\n", + " \"feat_127\",\n", + " \"feat_128\",\n", + " \"feat_129\",\n", + " \"feat_130\",\n", + " \"feat_131\",\n", + " \"feat_132\",\n", + " \"feat_133\",\n", + " \"feat_134\",\n", + " \"feat_135\",\n", + " \"feat_136\",\n", + " \"feat_137\",\n", + " \"feat_138\",\n", + " \"feat_139\",\n", + " \"feat_140\",\n", + " \"feat_141\",\n", + " \"feat_142\",\n", + " \"feat_143\",\n", + " \"feat_144\",\n", + " \"feat_145\",\n", + " \"feat_146\",\n", + " \"feat_147\",\n", + " \"feat_148\",\n", + " \"feat_149\",\n", + " \"feat_150\",\n", + " \"feat_151\",\n", + " \"feat_152\",\n", + " \"feat_153\",\n", + " \"feat_154\",\n", + " \"feat_155\",\n", + " \"feat_156\",\n", + " \"feat_157\",\n", + " \"feat_158\",\n", + " \"feat_159\",\n", + " \"feat_160\",\n", + " \"feat_161\",\n", + " \"feat_162\",\n", + " \"feat_163\",\n", + " \"feat_164\",\n", + " \"feat_165\",\n", + " \"feat_166\",\n", + " \"feat_167\",\n", + " \"feat_168\",\n", + " \"feat_169\",\n", + " \"feat_170\",\n", + " \"feat_171\",\n", + " \"feat_172\",\n", + " \"feat_173\",\n", + " \"feat_174\",\n", + " \"feat_175\",\n", + " \"feat_176\",\n", + " \"feat_177\",\n", + " \"feat_178\",\n", + " \"feat_179\",\n", + " \"feat_180\",\n", + " \"feat_181\",\n", + " \"feat_182\",\n", + " \"feat_183\",\n", + " \"feat_184\",\n", + " \"feat_185\",\n", + " \"feat_186\",\n", + " \"feat_187\",\n", + " \"feat_188\",\n", + " \"feat_189\",\n", + " \"feat_190\",\n", + " \"feat_191\",\n", + " \"feat_192\",\n", + " \"feat_193\",\n", + " \"feat_194\",\n", + " \"feat_195\",\n", + " \"feat_196\",\n", + " \"feat_197\",\n", + " \"feat_198\",\n", + " \"feat_199\",\n", + " \"feat_200\",\n", + " \"feat_201\",\n", + " \"feat_202\",\n", + " \"feat_203\",\n", + " \"feat_204\",\n", + " \"feat_205\",\n", + " \"feat_206\",\n", + " \"feat_207\",\n", + " \"feat_208\",\n", + " \"feat_209\",\n", + " \"feat_210\",\n", + " \"feat_211\",\n", + " \"feat_212\",\n", + " \"feat_213\",\n", + " \"feat_214\",\n", + " \"feat_215\",\n", + " \"feat_216\",\n", + " \"feat_217\",\n", + " \"feat_218\",\n", + " \"feat_219\",\n", + " \"feat_220\",\n", + " \"feat_221\",\n", + " \"feat_222\",\n", + " \"feat_223\",\n", + " \"feat_224\",\n", + " \"feat_225\",\n", + " \"feat_226\",\n", + " \"feat_227\",\n", + " \"feat_228\",\n", + " \"feat_229\",\n", + " \"feat_230\",\n", + " \"feat_231\",\n", + " \"feat_232\",\n", + " \"feat_233\",\n", + " \"feat_234\",\n", + " \"feat_235\",\n", + " \"feat_236\",\n", + " \"feat_237\",\n", + " \"feat_238\",\n", + " \"feat_239\",\n", + " \"feat_240\",\n", + " \"feat_241\",\n", + " \"feat_242\",\n", + " \"feat_243\",\n", + " \"feat_244\",\n", + " \"feat_245\",\n", + " \"feat_246\",\n", + " \"feat_247\",\n", + " \"feat_248\",\n", + " \"feat_249\",\n", + " \"feat_250\",\n", + " \"feat_251\",\n", + " \"feat_252\",\n", + " \"feat_253\",\n", + " \"feat_254\",\n", + " \"feat_255\",\n", + " \"feat_256\",\n", + " \"feat_257\",\n", + " \"feat_258\",\n", + " \"feat_259\",\n", + " \"feat_260\",\n", + " \"feat_261\",\n", + " \"feat_262\",\n", + " \"feat_263\",\n", + " \"feat_264\",\n", + " \"feat_265\",\n", + " \"feat_266\",\n", + " \"feat_267\",\n", + " \"feat_268\",\n", + " \"feat_269\",\n", + " \"feat_270\",\n", + " \"feat_271\",\n", + " \"feat_272\",\n", + " \"feat_273\",\n", + " \"feat_274\",\n", + " \"feat_275\",\n", + " \"feat_276\",\n", + " \"feat_277\",\n", + " \"feat_278\",\n", + " \"feat_279\",\n", + " \"feat_280\",\n", + " \"feat_281\",\n", + " \"feat_282\",\n", + " \"feat_283\",\n", + " \"feat_284\",\n", + " \"feat_285\",\n", + " \"feat_286\",\n", + " \"feat_287\",\n", + " \"feat_288\",\n", + " \"feat_289\",\n", + " \"feat_290\",\n", + " \"feat_291\",\n", + " \"feat_292\",\n", + " \"feat_293\",\n", + " \"feat_294\",\n", + " \"feat_295\",\n", + " \"feat_296\",\n", + " \"feat_297\",\n", + " \"feat_298\",\n", + " \"feat_299\",\n", + " \"feat_300\",\n", + " \"feat_301\",\n", + " \"feat_302\",\n", + " \"feat_303\",\n", + " \"feat_304\",\n", + " \"feat_305\",\n", + " \"feat_306\",\n", + " \"feat_307\",\n", + " \"feat_308\",\n", + " \"feat_309\",\n", + " \"feat_310\",\n", + " \"feat_311\",\n", + " \"feat_312\",\n", + " \"feat_313\",\n", + " \"feat_314\",\n", + " \"feat_315\",\n", + " \"feat_316\",\n", + " \"feat_317\",\n", + " \"feat_318\",\n", + " \"feat_319\",\n", + " \"feat_320\",\n", + " \"feat_321\",\n", + " \"feat_322\",\n", + " \"feat_323\",\n", + " \"feat_324\",\n", + " \"feat_325\",\n", + " \"feat_326\",\n", + " \"feat_327\",\n", + " \"feat_328\",\n", + " \"feat_329\",\n", + " \"feat_330\",\n", + " \"feat_331\",\n", + " \"feat_332\",\n", + " \"feat_333\",\n", + " \"feat_334\",\n", + " \"feat_335\",\n", + " \"feat_336\",\n", + " \"feat_337\",\n", + " \"feat_338\",\n", + " \"feat_339\",\n", + " \"feat_340\",\n", + " \"feat_341\",\n", + " \"feat_342\",\n", + " \"feat_343\",\n", + " \"feat_344\",\n", + " \"feat_345\",\n", + " \"feat_346\",\n", + " \"feat_347\",\n", + " \"feat_348\",\n", + " \"feat_349\",\n", + " \"feat_350\",\n", + " \"feat_351\",\n", + " \"feat_352\",\n", + " \"feat_353\",\n", + " \"feat_354\",\n", + " \"feat_355\",\n", + " \"feat_356\",\n", + " \"feat_357\",\n", + " \"feat_358\",\n", + " \"feat_359\",\n", + " \"feat_360\",\n", + " \"feat_361\",\n", + " \"feat_362\",\n", + " \"feat_363\",\n", + " \"feat_364\",\n", + " \"feat_365\",\n", + " \"feat_366\",\n", + " \"feat_367\",\n", + " \"feat_368\",\n", + " \"feat_369\",\n", + " \"feat_370\",\n", + " \"feat_371\",\n", + " \"feat_372\",\n", + " \"feat_373\",\n", + " \"feat_374\",\n", + " \"feat_375\",\n", + " \"feat_376\",\n", + " \"feat_377\",\n", + " \"feat_378\",\n", + " \"feat_379\",\n", + " \"feat_380\",\n", + " \"feat_381\",\n", + " \"feat_382\",\n", + " \"feat_383\",\n", + " \"feat_384\",\n", + " \"feat_385\",\n", + " \"feat_386\",\n", + " \"feat_387\",\n", + " \"feat_388\",\n", + " \"feat_389\",\n", + " \"feat_390\",\n", + " \"feat_391\",\n", + " \"feat_392\",\n", + " \"feat_393\",\n", + " \"feat_394\",\n", + " \"feat_395\",\n", + " \"feat_396\",\n", + " \"feat_397\",\n", + " \"feat_398\",\n", + " \"feat_399\",\n", + " \"feat_400\",\n", + " \"feat_401\",\n", + " \"feat_402\",\n", + " \"feat_403\",\n", + " \"feat_404\",\n", + " \"feat_405\",\n", + " \"feat_406\",\n", + " \"feat_407\",\n", + " \"feat_408\",\n", + " \"feat_409\",\n", + " \"feat_410\",\n", + " \"feat_411\",\n", + " \"feat_412\",\n", + " \"feat_413\",\n", + " \"feat_414\",\n", + " \"feat_415\",\n", + " \"feat_416\",\n", + " \"feat_417\",\n", + " \"feat_418\",\n", + " \"feat_419\",\n", + " \"feat_420\",\n", + " \"feat_421\",\n", + " \"feat_422\",\n", + " \"feat_423\",\n", + " \"feat_424\",\n", + " \"feat_425\",\n", + " \"feat_426\",\n", + " \"feat_427\",\n", + " \"feat_428\",\n", + " \"feat_429\",\n", + " \"feat_430\",\n", + " \"feat_431\",\n", + " \"feat_432\",\n", + " \"feat_433\",\n", + " \"feat_434\",\n", + " \"feat_435\",\n", + " \"feat_436\",\n", + " \"feat_437\",\n", + " \"feat_438\",\n", + " \"feat_439\",\n", + " \"feat_440\",\n", + " \"feat_441\",\n", + " \"feat_442\",\n", + " \"feat_443\",\n", + " \"feat_444\",\n", + " \"feat_445\",\n", + " \"feat_446\",\n", + " \"feat_447\",\n", + " \"feat_448\",\n", + " \"feat_449\",\n", + " \"feat_450\",\n", + " \"feat_451\",\n", + " \"feat_452\",\n", + " \"feat_453\",\n", + " \"feat_454\",\n", + " \"feat_455\",\n", + " \"feat_456\",\n", + " \"feat_457\",\n", + " \"feat_458\",\n", + " \"feat_459\",\n", + " \"feat_460\",\n", + " \"feat_461\",\n", + " \"feat_462\",\n", + " \"feat_463\",\n", + " \"feat_464\",\n", + " \"feat_465\",\n", + " \"feat_466\",\n", + " \"feat_467\",\n", + " \"feat_468\",\n", + " \"feat_469\",\n", + " \"feat_470\",\n", + " \"feat_471\",\n", + " \"feat_472\",\n", + " \"feat_473\",\n", + " \"feat_474\",\n", + " \"feat_475\",\n", + " \"feat_476\",\n", + " \"feat_477\",\n", + " \"feat_478\",\n", + " \"feat_479\",\n", + " \"feat_480\",\n", + " \"feat_481\",\n", + " \"feat_482\",\n", + " \"feat_483\",\n", + " \"feat_484\",\n", + " \"feat_485\",\n", + " \"feat_486\",\n", + " \"feat_487\",\n", + " \"feat_488\",\n", + " \"feat_489\",\n", + " \"feat_490\",\n", + " \"feat_491\",\n", + " \"feat_492\",\n", + " \"feat_493\",\n", + " \"feat_494\",\n", + " \"feat_495\",\n", + " \"feat_496\",\n", + " \"feat_497\",\n", + " \"feat_498\",\n", + " \"feat_499\",\n", + " \"feat_500\",\n", + " \"feat_501\",\n", + " \"feat_502\",\n", + " \"feat_503\",\n", + " \"feat_504\",\n", + " \"feat_505\",\n", + " \"feat_506\",\n", + " \"feat_507\",\n", + " \"feat_508\",\n", + " \"feat_509\",\n", + " \"feat_510\",\n", + " \"feat_511\",\n", + " \"feat_512\",\n", + " \"feat_513\",\n", + " \"feat_514\",\n", + " \"feat_515\",\n", + " \"feat_516\",\n", + " \"feat_517\",\n", + " \"feat_518\",\n", + " \"feat_519\",\n", + " \"feat_520\",\n", + " \"feat_521\",\n", + " \"feat_522\",\n", + " \"feat_523\",\n", + " \"feat_524\",\n", + " \"feat_525\",\n", + " \"feat_526\",\n", + " \"feat_527\",\n", + " \"feat_528\",\n", + " \"feat_529\",\n", + " \"feat_530\",\n", + " \"feat_531\",\n", + " \"feat_532\",\n", + " \"feat_533\",\n", + " \"feat_534\",\n", + " \"feat_535\",\n", + " \"feat_536\",\n", + " \"feat_537\",\n", + " \"feat_538\",\n", + " \"feat_539\",\n", + " \"feat_540\",\n", + " \"feat_541\",\n", + " \"feat_542\",\n", + " \"feat_543\",\n", + " \"feat_544\",\n", + " \"feat_545\",\n", + " \"feat_546\",\n", + " \"feat_547\",\n", + " \"feat_548\",\n", + " \"feat_549\",\n", + " \"feat_550\",\n", + " \"feat_551\",\n", + " \"feat_552\",\n", + " \"feat_553\",\n", + " \"feat_554\",\n", + " \"feat_555\",\n", + " \"feat_556\",\n", + " \"feat_557\",\n", + " \"feat_558\",\n", + " \"feat_559\",\n", + " \"feat_560\",\n", + " \"feat_561\",\n", + " \"feat_562\",\n", + " \"feat_563\",\n", + " \"feat_564\",\n", + " \"feat_565\",\n", + " \"feat_566\",\n", + " \"feat_567\",\n", + " \"feat_568\",\n", + " \"feat_569\",\n", + " \"feat_570\",\n", + " \"feat_571\",\n", + " \"feat_572\",\n", + " \"feat_573\",\n", + " \"feat_574\",\n", + " \"feat_575\",\n", + " \"feat_576\",\n", + " \"feat_577\",\n", + " \"feat_578\",\n", + " \"feat_579\",\n", + " \"feat_580\",\n", + " \"feat_581\",\n", + " \"feat_582\",\n", + " \"feat_583\",\n", + " \"feat_584\",\n", + " \"feat_585\",\n", + " \"feat_586\",\n", + " \"feat_587\",\n", + " \"feat_588\",\n", + " \"feat_589\",\n", + " \"feat_590\",\n", + " \"feat_591\",\n", + " \"feat_592\",\n", + " \"feat_593\",\n", + " \"feat_594\",\n", + " \"feat_595\",\n", + " \"feat_596\",\n", + " \"feat_597\",\n", + " \"feat_598\",\n", + " \"feat_599\",\n", + " \"feat_600\",\n", + " \"feat_601\",\n", + " \"feat_602\",\n", + " \"feat_603\",\n", + " \"feat_604\",\n", + " \"feat_605\",\n", + " \"feat_606\",\n", + " \"feat_607\",\n", + " \"feat_608\",\n", + " \"feat_609\",\n", + " \"feat_610\",\n", + " \"feat_611\",\n", + " \"feat_612\",\n", + " \"feat_613\",\n", + " \"feat_614\",\n", + " \"feat_615\",\n", + " \"feat_616\",\n", + " \"feat_617\",\n", + " \"feat_618\",\n", + " \"feat_619\",\n", + " \"feat_620\",\n", + " \"feat_621\",\n", + " \"feat_622\",\n", + " \"feat_623\",\n", + " \"feat_624\",\n", + " \"feat_625\",\n", + " \"feat_626\",\n", + " \"feat_627\",\n", + " \"feat_628\",\n", + " \"feat_629\",\n", + " \"feat_630\",\n", + " \"feat_631\",\n", + " \"feat_632\",\n", + " \"feat_633\",\n", + " \"feat_634\",\n", + " \"feat_635\",\n", + " \"feat_636\",\n", + " \"feat_637\",\n", + " \"feat_638\",\n", + " \"feat_639\",\n", + " \"feat_640\",\n", + " \"feat_641\",\n", + " \"feat_642\",\n", + " \"feat_643\",\n", + " \"feat_644\",\n", + " \"feat_645\",\n", + " \"feat_646\",\n", + " \"feat_647\",\n", + " \"feat_648\",\n", + " \"feat_649\",\n", + " \"feat_650\",\n", + " \"feat_651\",\n", + " \"feat_652\",\n", + " \"feat_653\",\n", + " \"feat_654\",\n", + " \"feat_655\",\n", + " \"feat_656\",\n", + " \"feat_657\",\n", + " \"feat_658\",\n", + " \"feat_659\",\n", + " \"feat_660\",\n", + " \"feat_661\",\n", + " \"feat_662\",\n", + " \"feat_663\",\n", + " \"feat_664\",\n", + " \"feat_665\",\n", + " \"feat_666\",\n", + " \"feat_667\",\n", + " \"feat_668\",\n", + " \"feat_669\",\n", + " \"feat_670\",\n", + " \"feat_671\",\n", + " \"feat_672\",\n", + " \"feat_673\",\n", + " \"feat_674\",\n", + " \"feat_675\",\n", + " \"feat_676\",\n", + " \"feat_677\",\n", + " \"feat_678\",\n", + " \"feat_679\",\n", + " \"feat_680\",\n", + " \"feat_681\",\n", + " \"feat_682\",\n", + " \"feat_683\",\n", + " \"feat_684\",\n", + " \"feat_685\",\n", + " \"feat_686\",\n", + " \"feat_687\",\n", + " \"feat_688\",\n", + " \"feat_689\",\n", + " \"feat_690\",\n", + " \"feat_691\",\n", + " \"feat_692\",\n", + " \"feat_693\",\n", + " \"feat_694\",\n", + " \"feat_695\",\n", + " \"feat_696\",\n", + " \"feat_697\",\n", + " \"feat_698\",\n", + " \"feat_699\",\n", + " \"feat_700\",\n", + " \"feat_701\",\n", + " \"feat_702\",\n", + " \"feat_703\",\n", + " \"feat_704\",\n", + " \"feat_705\",\n", + " \"feat_706\",\n", + " \"feat_707\",\n", + " \"feat_708\",\n", + " \"feat_709\",\n", + " \"feat_710\",\n", + " \"feat_711\",\n", + " \"feat_712\",\n", + " \"feat_713\",\n", + " \"feat_714\",\n", + " \"feat_715\",\n", + " \"feat_716\",\n", + " \"feat_717\",\n", + " \"feat_718\",\n", + " \"feat_719\",\n", + " \"feat_720\",\n", + " \"feat_721\",\n", + " \"feat_722\",\n", + " \"feat_723\",\n", + " \"feat_724\",\n", + " \"feat_725\",\n", + " \"feat_726\",\n", + " \"feat_727\",\n", + " \"feat_728\",\n", + " \"feat_729\",\n", + " \"feat_730\",\n", + " \"feat_731\",\n", + " \"feat_732\",\n", + " \"feat_733\",\n", + " \"feat_734\",\n", + " \"feat_735\",\n", + " \"feat_736\",\n", + " \"feat_737\",\n", + " \"feat_738\",\n", + " \"feat_739\",\n", + " \"feat_740\",\n", + " \"feat_741\",\n", + " \"feat_742\",\n", + " \"feat_743\",\n", + " \"feat_744\",\n", + " \"feat_745\",\n", + " \"feat_746\",\n", + " \"feat_747\",\n", + " \"feat_748\",\n", + " \"feat_749\",\n", + " \"feat_750\",\n", + " \"feat_751\",\n", + " \"feat_752\",\n", + " \"feat_753\",\n", + " \"feat_754\",\n", + " \"feat_755\",\n", + " \"feat_756\",\n", + " \"feat_757\",\n", + " \"feat_758\",\n", + " \"feat_759\",\n", + " \"feat_760\",\n", + " \"feat_761\",\n", + " \"feat_762\",\n", + " \"feat_763\",\n", + " \"feat_764\",\n", + " \"feat_765\",\n", + " \"feat_766\",\n", + " \"feat_767\"\n", + " ],\n", + " \"feature_file\": \"paper_feats.npy\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"paper\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": null\n", + " },\n", + " {\n", + " \"type\": \"uniform\",\n", + " \"features_list\": [\n", + " \"year\",\n", + " \"label\"\n", + " ],\n", + " \"feature_file\": \"year_label.npy\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"paper\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": null\n", + " }\n", + " ]\n", + " },\n", + " {\n", + " \"name\": \"author\",\n", + " \"count\": 122383112,\n", + " \"features_path\": null,\n", + " \"features\": []\n", + " },\n", + " {\n", + " \"name\": \"institution\",\n", + " \"count\": 25721,\n", + " \"features_path\": null,\n", + " \"features\": []\n", + " }\n", + " ],\n", + " \"edges\": [\n", + " {\n", + " \"name\": \"writes\",\n", + " \"count\": 386022720,\n", + " \"src_node_type\": \"author\",\n", + " \"dst_node_type\": \"paper\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"writes_list.parquet\",\n", + " \"[gen]structure_generator\": {\n", + " \"type\": \"RMAT\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"writes\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": null\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"affiliated_with\",\n", + " \"count\": 44592586,\n", + " \"src_node_type\": \"author\",\n", + " \"dst_node_type\": \"institution\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"affiliated_with_list.parquet\",\n", + " \"[gen]structure_generator\": {\n", + " \"type\": \"RMAT\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"affiliated_with\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": null\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"cites\",\n", + " \"count\": 1297748926,\n", + " \"src_node_type\": \"paper\",\n", + " \"dst_node_type\": \"paper\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"cites_list.parquet\",\n", + " \"[gen]structure_generator\": {\n", + " \"type\": \"RMAT\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"cites\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": null\n", + " }\n", + " }\n", + " ],\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\"\n", + "}" + ] + } + ], + "source": [ + "!cat $configs_dir/simple.json" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "16c3bbd0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "0it [00:00, ?it/s]\n", + "100%|█████████████████████████████████████████| 768/768 [10:29<00:00, 1.22it/s]\n", + "100%|█████████████████████████████████████████████| 2/2 [00:00<00:00, 2.97it/s]\n", + "0it [00:00, ?it/s]\n", + "NODE paper FIT TOOK: 906.03\n", + "FIT NODES TOOK: 906.03\n", + "DEBUG:root:Initialized logger\n", + "DEBUG:root:Using seed: 66\n", + "DEBUG:root:Fit results dst_src: None\n", + "DEBUG:root:Fit results src_dst: (0.4493778749717661, 0.16335407041150202, 0.1362311795696754, 0.2510368750470564)\n", + "EDGE writes STRUCTURAL FIT TOOK: 110.91\n", + "DEBUG:root:Initialized logger\n", + "DEBUG:root:Using seed: 20\n", + "DEBUG:root:Fit results dst_src: None\n", + "DEBUG:root:Fit results src_dst: (0.37499999944120643, 0.12499999906867743, 0.12500000055879357, 0.3750000009313226)\n", + "EDGE affiliated_with STRUCTURAL FIT TOOK: 6.61\n", + "DEBUG:root:Initialized logger\n", + "DEBUG:root:Using seed: 99\n", + "DEBUG:root:Fit results: (0.4468597402097436, 0.14895324673658117, 0.14895324673658117, 0.25523376631709405)\n", + "EDGE cites STRUCTURAL FIT TOOK: 111.06\n", + "FIT EDGES TOOK: 228.58\n", + "FIT TOOK: 1134.61\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_simple/writes_list.parquet parquet\n", + "EDGE writes STRUCT GEN TOOK: 44.19\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_simple/affiliated_with_list.parquet parquet\n", + "EDGE affiliated_with STRUCT GEN TOOK: 5.47\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_simple/cites_list.parquet parquet\n", + "EDGE cites STRUCT GEN TOOK: 49.78\n", + "GEN STRUCT TOOK: 99.44\n", + "100%|███████████████████████████████████████████| 40/40 [04:00<00:00, 6.02s/it]\n", + "GEN TABULAR NODE FEATURES TOOK: 252.57\n", + "GEN TABULAR EDGE FEATURES TOOK: 0.00\n", + "GEN ALIGNMENT TAKE: 0.00\n" + ] + } + ], + "source": [ + "!python -m syngen synthesize --config-path $configs_dir/simple.json --save-path /raid/ogbn_mag240m_simple --verbose" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "792ef20a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.9G\t/raid/ogbn_mag240m_simple/writes_list.parquet\n", + "2.1G\t/raid/ogbn_mag240m_simple/paper_tabular_features/year_label.npy\n", + "193G\t/raid/ogbn_mag240m_simple/paper_tabular_features/paper_feats.npy\n", + "195G\t/raid/ogbn_mag240m_simple/paper_tabular_features\n", + "5.3G\t/raid/ogbn_mag240m_simple/cites_list.parquet\n", + "251M\t/raid/ogbn_mag240m_simple/affiliated_with_list.parquet\n", + "200K\t/raid/ogbn_mag240m_simple/graph_metadata.json\n", + "203G\t/raid/ogbn_mag240m_simple\n" + ] + } + ], + "source": [ + "!du -ah /raid/ogbn_mag240m_simple" + ] + }, + { + "cell_type": "markdown", + "id": "e6f4e57a", + "metadata": {}, + "source": [ + "## Prepare SynGen Configuration that stores fitted generators" + ] + }, + { + "cell_type": "markdown", + "id": "5b2370e6", + "metadata": {}, + "source": [ + "Generators fitting process takes a significant part of the entire generation, so we can store the fitted generators for the future experiments." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7dba94a3", + "metadata": {}, + "outputs": [], + "source": [ + "generators_dump_dir = 'ogbn_mag240m_gens'" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "d3206f01", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "INFO:syngen.cli.commands.mimic_dataset:SynGen Configuration saved into ogbn_mag240m_configs/with_gen_dump.json\n" + ] + } + ], + "source": [ + "!python -m syngen mimic-dataset --gen-dump-path=$generators_dump_dir --output-file=$configs_dir/with_gen_dump.json --dataset-path $preprocessed_path --tab-gen uniform" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "664e36e1", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"nodes\": [\n", + " {\n", + " \"name\": \"paper\",\n", + " \"count\": 121751666,\n", + " \"features\": [\n", + " {\n", + " \"name\": \"feat_0\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_1\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_2\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_3\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_4\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_5\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_6\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_7\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_8\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_9\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_10\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_11\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_12\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_13\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_14\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_15\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_16\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_17\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_18\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_19\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_20\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_21\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_22\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_23\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_24\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_25\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_26\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_27\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_28\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_29\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_30\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_31\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_32\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_33\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_34\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_35\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_36\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_37\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_38\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_39\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_40\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_41\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_42\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_43\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_44\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_45\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_46\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_47\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_48\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_49\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_50\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_51\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_52\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_53\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_54\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_55\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_56\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_57\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_58\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_59\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_60\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_61\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_62\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_63\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_64\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_65\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_66\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_67\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_68\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_69\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_70\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_71\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_72\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_73\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_74\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_75\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_76\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_77\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_78\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_79\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_80\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_81\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_82\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_83\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_84\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_85\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_86\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_87\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_88\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_89\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_90\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_91\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_92\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_93\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_94\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_95\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_96\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_97\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_98\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_99\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_100\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_101\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_102\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_103\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_104\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_105\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_106\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_107\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_108\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_109\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_110\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_111\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_112\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_113\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_114\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_115\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_116\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_117\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_118\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_119\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_120\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_121\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_122\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_123\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_124\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_125\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_126\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_127\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_128\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_129\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_130\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_131\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_132\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_133\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_134\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_135\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_136\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_137\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_138\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_139\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_140\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_141\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_142\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_143\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_144\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_145\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_146\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_147\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_148\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_149\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_150\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_151\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_152\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_153\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_154\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_155\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_156\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_157\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_158\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_159\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_160\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_161\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_162\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_163\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_164\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_165\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_166\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_167\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_168\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_169\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_170\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_171\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_172\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_173\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_174\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_175\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_176\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_177\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_178\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_179\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_180\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_181\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_182\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_183\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_184\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_185\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_186\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_187\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_188\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_189\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_190\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_191\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_192\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_193\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_194\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_195\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_196\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_197\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_198\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_199\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_200\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_201\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_202\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_203\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_204\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_205\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_206\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_207\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_208\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_209\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_210\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_211\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_212\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_213\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_214\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_215\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_216\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_217\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_218\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_219\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_220\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_221\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_222\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_223\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_224\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_225\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_226\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_227\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_228\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_229\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_230\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_231\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_232\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_233\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_234\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_235\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_236\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_237\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_238\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_239\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_240\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_241\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_242\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_243\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_244\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_245\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_246\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_247\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_248\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_249\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_250\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_251\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_252\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_253\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_254\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_255\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_256\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_257\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_258\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_259\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_260\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_261\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_262\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_263\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_264\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_265\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_266\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_267\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_268\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_269\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_270\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_271\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_272\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_273\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_274\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_275\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_276\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_277\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_278\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_279\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_280\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_281\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_282\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_283\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_284\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_285\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_286\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_287\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_288\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_289\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_290\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_291\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_292\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_293\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_294\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_295\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_296\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_297\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_298\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_299\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_300\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_301\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_302\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_303\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_304\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_305\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_306\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_307\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_308\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_309\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_310\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_311\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_312\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_313\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_314\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_315\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_316\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_317\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_318\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_319\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_320\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_321\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_322\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_323\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_324\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_325\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_326\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_327\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_328\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_329\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_330\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_331\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_332\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_333\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_334\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_335\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_336\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_337\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_338\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_339\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_340\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_341\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_342\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_343\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_344\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_345\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_346\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_347\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_348\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_349\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_350\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_351\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_352\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_353\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_354\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_355\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_356\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_357\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_358\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_359\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_360\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_361\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_362\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_363\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_364\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_365\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_366\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_367\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_368\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_369\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_370\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_371\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_372\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_373\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_374\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_375\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_376\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_377\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_378\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_379\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_380\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_381\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_382\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_383\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_384\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_385\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_386\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_387\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_388\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_389\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_390\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_391\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_392\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_393\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_394\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_395\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_396\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_397\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_398\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_399\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_400\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_401\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_402\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_403\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_404\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_405\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_406\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_407\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_408\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_409\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_410\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_411\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_412\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_413\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_414\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_415\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_416\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_417\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_418\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_419\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_420\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_421\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_422\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_423\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_424\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_425\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_426\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_427\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_428\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_429\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_430\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_431\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_432\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_433\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_434\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_435\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_436\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_437\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_438\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_439\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_440\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_441\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_442\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_443\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_444\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_445\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_446\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_447\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_448\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_449\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_450\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_451\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_452\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_453\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_454\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_455\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_456\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_457\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_458\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_459\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_460\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_461\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_462\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_463\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_464\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_465\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_466\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_467\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_468\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_469\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_470\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_471\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_472\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_473\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_474\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_475\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_476\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_477\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_478\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_479\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_480\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_481\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_482\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_483\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_484\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_485\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_486\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_487\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_488\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_489\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_490\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_491\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_492\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_493\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_494\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_495\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_496\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_497\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_498\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_499\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_500\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_501\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_502\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_503\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_504\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_505\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_506\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_507\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_508\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_509\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_510\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_511\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_512\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_513\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_514\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_515\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_516\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_517\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_518\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_519\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_520\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_521\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_522\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_523\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_524\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_525\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_526\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_527\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_528\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_529\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_530\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_531\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_532\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_533\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_534\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_535\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_536\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_537\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_538\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_539\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_540\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_541\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_542\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_543\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_544\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_545\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_546\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_547\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_548\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_549\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_550\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_551\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_552\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_553\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_554\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_555\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_556\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_557\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_558\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_559\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_560\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_561\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_562\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_563\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_564\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_565\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_566\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_567\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_568\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_569\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_570\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_571\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_572\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_573\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_574\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_575\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_576\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_577\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_578\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_579\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_580\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_581\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_582\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_583\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_584\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_585\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_586\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_587\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_588\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_589\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_590\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_591\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_592\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_593\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_594\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_595\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_596\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_597\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_598\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_599\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_600\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_601\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_602\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_603\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_604\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_605\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_606\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_607\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_608\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_609\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_610\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_611\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_612\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_613\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_614\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_615\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_616\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_617\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_618\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_619\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_620\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_621\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_622\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_623\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_624\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_625\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_626\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_627\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_628\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_629\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_630\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_631\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_632\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_633\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_634\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_635\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_636\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_637\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_638\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_639\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_640\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_641\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_642\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_643\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_644\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_645\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_646\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_647\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_648\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_649\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_650\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_651\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_652\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_653\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_654\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_655\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_656\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_657\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_658\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_659\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_660\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_661\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_662\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_663\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_664\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_665\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_666\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_667\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_668\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_669\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_670\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_671\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_672\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_673\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_674\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_675\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_676\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_677\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_678\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_679\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_680\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_681\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_682\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_683\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_684\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_685\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_686\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_687\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_688\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_689\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_690\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_691\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_692\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_693\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_694\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_695\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_696\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_697\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_698\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_699\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_700\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_701\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_702\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_703\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_704\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_705\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_706\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_707\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_708\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_709\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_710\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_711\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_712\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_713\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_714\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_715\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_716\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_717\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_718\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_719\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_720\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_721\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_722\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_723\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_724\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_725\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_726\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_727\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_728\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_729\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_730\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_731\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_732\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_733\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_734\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_735\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_736\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_737\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_738\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_739\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_740\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_741\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_742\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_743\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_744\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_745\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_746\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_747\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_748\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_749\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_750\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_751\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_752\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_753\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_754\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_755\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_756\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_757\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_758\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_759\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_760\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_761\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_762\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_763\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_764\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_765\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_766\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"feat_767\",\n", + " \"dtype\": \"float16\",\n", + " \"feature_type\": \"continuous\",\n", + " \"feature_file\": \"paper_feats.npy\"\n", + " },\n", + " {\n", + " \"name\": \"year\",\n", + " \"dtype\": \"int32\",\n", + " \"feature_type\": \"categorical\",\n", + " \"feature_file\": \"year_label.npy\"\n", + " },\n", + " {\n", + " \"name\": \"label\",\n", + " \"dtype\": \"int32\",\n", + " \"feature_type\": \"categorical\",\n", + " \"feature_file\": \"year_label.npy\"\n", + " }\n", + " ],\n", + " \"features_path\": \"paper_tabular_features\",\n", + " \"[gen]tabular_generators\": [\n", + " {\n", + " \"type\": \"uniform\",\n", + " \"features_list\": [\n", + " \"feat_0\",\n", + " \"feat_1\",\n", + " \"feat_2\",\n", + " \"feat_3\",\n", + " \"feat_4\",\n", + " \"feat_5\",\n", + " \"feat_6\",\n", + " \"feat_7\",\n", + " \"feat_8\",\n", + " \"feat_9\",\n", + " \"feat_10\",\n", + " \"feat_11\",\n", + " \"feat_12\",\n", + " \"feat_13\",\n", + " \"feat_14\",\n", + " \"feat_15\",\n", + " \"feat_16\",\n", + " \"feat_17\",\n", + " \"feat_18\",\n", + " \"feat_19\",\n", + " \"feat_20\",\n", + " \"feat_21\",\n", + " \"feat_22\",\n", + " \"feat_23\",\n", + " \"feat_24\",\n", + " \"feat_25\",\n", + " \"feat_26\",\n", + " \"feat_27\",\n", + " \"feat_28\",\n", + " \"feat_29\",\n", + " \"feat_30\",\n", + " \"feat_31\",\n", + " \"feat_32\",\n", + " \"feat_33\",\n", + " \"feat_34\",\n", + " \"feat_35\",\n", + " \"feat_36\",\n", + " \"feat_37\",\n", + " \"feat_38\",\n", + " \"feat_39\",\n", + " \"feat_40\",\n", + " \"feat_41\",\n", + " \"feat_42\",\n", + " \"feat_43\",\n", + " \"feat_44\",\n", + " \"feat_45\",\n", + " \"feat_46\",\n", + " \"feat_47\",\n", + " \"feat_48\",\n", + " \"feat_49\",\n", + " \"feat_50\",\n", + " \"feat_51\",\n", + " \"feat_52\",\n", + " \"feat_53\",\n", + " \"feat_54\",\n", + " \"feat_55\",\n", + " \"feat_56\",\n", + " \"feat_57\",\n", + " \"feat_58\",\n", + " \"feat_59\",\n", + " \"feat_60\",\n", + " \"feat_61\",\n", + " \"feat_62\",\n", + " \"feat_63\",\n", + " \"feat_64\",\n", + " \"feat_65\",\n", + " \"feat_66\",\n", + " \"feat_67\",\n", + " \"feat_68\",\n", + " \"feat_69\",\n", + " \"feat_70\",\n", + " \"feat_71\",\n", + " \"feat_72\",\n", + " \"feat_73\",\n", + " \"feat_74\",\n", + " \"feat_75\",\n", + " \"feat_76\",\n", + " \"feat_77\",\n", + " \"feat_78\",\n", + " \"feat_79\",\n", + " \"feat_80\",\n", + " \"feat_81\",\n", + " \"feat_82\",\n", + " \"feat_83\",\n", + " \"feat_84\",\n", + " \"feat_85\",\n", + " \"feat_86\",\n", + " \"feat_87\",\n", + " \"feat_88\",\n", + " \"feat_89\",\n", + " \"feat_90\",\n", + " \"feat_91\",\n", + " \"feat_92\",\n", + " \"feat_93\",\n", + " \"feat_94\",\n", + " \"feat_95\",\n", + " \"feat_96\",\n", + " \"feat_97\",\n", + " \"feat_98\",\n", + " \"feat_99\",\n", + " \"feat_100\",\n", + " \"feat_101\",\n", + " \"feat_102\",\n", + " \"feat_103\",\n", + " \"feat_104\",\n", + " \"feat_105\",\n", + " \"feat_106\",\n", + " \"feat_107\",\n", + " \"feat_108\",\n", + " \"feat_109\",\n", + " \"feat_110\",\n", + " \"feat_111\",\n", + " \"feat_112\",\n", + " \"feat_113\",\n", + " \"feat_114\",\n", + " \"feat_115\",\n", + " \"feat_116\",\n", + " \"feat_117\",\n", + " \"feat_118\",\n", + " \"feat_119\",\n", + " \"feat_120\",\n", + " \"feat_121\",\n", + " \"feat_122\",\n", + " \"feat_123\",\n", + " \"feat_124\",\n", + " \"feat_125\",\n", + " \"feat_126\",\n", + " \"feat_127\",\n", + " \"feat_128\",\n", + " \"feat_129\",\n", + " \"feat_130\",\n", + " \"feat_131\",\n", + " \"feat_132\",\n", + " \"feat_133\",\n", + " \"feat_134\",\n", + " \"feat_135\",\n", + " \"feat_136\",\n", + " \"feat_137\",\n", + " \"feat_138\",\n", + " \"feat_139\",\n", + " \"feat_140\",\n", + " \"feat_141\",\n", + " \"feat_142\",\n", + " \"feat_143\",\n", + " \"feat_144\",\n", + " \"feat_145\",\n", + " \"feat_146\",\n", + " \"feat_147\",\n", + " \"feat_148\",\n", + " \"feat_149\",\n", + " \"feat_150\",\n", + " \"feat_151\",\n", + " \"feat_152\",\n", + " \"feat_153\",\n", + " \"feat_154\",\n", + " \"feat_155\",\n", + " \"feat_156\",\n", + " \"feat_157\",\n", + " \"feat_158\",\n", + " \"feat_159\",\n", + " \"feat_160\",\n", + " \"feat_161\",\n", + " \"feat_162\",\n", + " \"feat_163\",\n", + " \"feat_164\",\n", + " \"feat_165\",\n", + " \"feat_166\",\n", + " \"feat_167\",\n", + " \"feat_168\",\n", + " \"feat_169\",\n", + " \"feat_170\",\n", + " \"feat_171\",\n", + " \"feat_172\",\n", + " \"feat_173\",\n", + " \"feat_174\",\n", + " \"feat_175\",\n", + " \"feat_176\",\n", + " \"feat_177\",\n", + " \"feat_178\",\n", + " \"feat_179\",\n", + " \"feat_180\",\n", + " \"feat_181\",\n", + " \"feat_182\",\n", + " \"feat_183\",\n", + " \"feat_184\",\n", + " \"feat_185\",\n", + " \"feat_186\",\n", + " \"feat_187\",\n", + " \"feat_188\",\n", + " \"feat_189\",\n", + " \"feat_190\",\n", + " \"feat_191\",\n", + " \"feat_192\",\n", + " \"feat_193\",\n", + " \"feat_194\",\n", + " \"feat_195\",\n", + " \"feat_196\",\n", + " \"feat_197\",\n", + " \"feat_198\",\n", + " \"feat_199\",\n", + " \"feat_200\",\n", + " \"feat_201\",\n", + " \"feat_202\",\n", + " \"feat_203\",\n", + " \"feat_204\",\n", + " \"feat_205\",\n", + " \"feat_206\",\n", + " \"feat_207\",\n", + " \"feat_208\",\n", + " \"feat_209\",\n", + " \"feat_210\",\n", + " \"feat_211\",\n", + " \"feat_212\",\n", + " \"feat_213\",\n", + " \"feat_214\",\n", + " \"feat_215\",\n", + " \"feat_216\",\n", + " \"feat_217\",\n", + " \"feat_218\",\n", + " \"feat_219\",\n", + " \"feat_220\",\n", + " \"feat_221\",\n", + " \"feat_222\",\n", + " \"feat_223\",\n", + " \"feat_224\",\n", + " \"feat_225\",\n", + " \"feat_226\",\n", + " \"feat_227\",\n", + " \"feat_228\",\n", + " \"feat_229\",\n", + " \"feat_230\",\n", + " \"feat_231\",\n", + " \"feat_232\",\n", + " \"feat_233\",\n", + " \"feat_234\",\n", + " \"feat_235\",\n", + " \"feat_236\",\n", + " \"feat_237\",\n", + " \"feat_238\",\n", + " \"feat_239\",\n", + " \"feat_240\",\n", + " \"feat_241\",\n", + " \"feat_242\",\n", + " \"feat_243\",\n", + " \"feat_244\",\n", + " \"feat_245\",\n", + " \"feat_246\",\n", + " \"feat_247\",\n", + " \"feat_248\",\n", + " \"feat_249\",\n", + " \"feat_250\",\n", + " \"feat_251\",\n", + " \"feat_252\",\n", + " \"feat_253\",\n", + " \"feat_254\",\n", + " \"feat_255\",\n", + " \"feat_256\",\n", + " \"feat_257\",\n", + " \"feat_258\",\n", + " \"feat_259\",\n", + " \"feat_260\",\n", + " \"feat_261\",\n", + " \"feat_262\",\n", + " \"feat_263\",\n", + " \"feat_264\",\n", + " \"feat_265\",\n", + " \"feat_266\",\n", + " \"feat_267\",\n", + " \"feat_268\",\n", + " \"feat_269\",\n", + " \"feat_270\",\n", + " \"feat_271\",\n", + " \"feat_272\",\n", + " \"feat_273\",\n", + " \"feat_274\",\n", + " \"feat_275\",\n", + " \"feat_276\",\n", + " \"feat_277\",\n", + " \"feat_278\",\n", + " \"feat_279\",\n", + " \"feat_280\",\n", + " \"feat_281\",\n", + " \"feat_282\",\n", + " \"feat_283\",\n", + " \"feat_284\",\n", + " \"feat_285\",\n", + " \"feat_286\",\n", + " \"feat_287\",\n", + " \"feat_288\",\n", + " \"feat_289\",\n", + " \"feat_290\",\n", + " \"feat_291\",\n", + " \"feat_292\",\n", + " \"feat_293\",\n", + " \"feat_294\",\n", + " \"feat_295\",\n", + " \"feat_296\",\n", + " \"feat_297\",\n", + " \"feat_298\",\n", + " \"feat_299\",\n", + " \"feat_300\",\n", + " \"feat_301\",\n", + " \"feat_302\",\n", + " \"feat_303\",\n", + " \"feat_304\",\n", + " \"feat_305\",\n", + " \"feat_306\",\n", + " \"feat_307\",\n", + " \"feat_308\",\n", + " \"feat_309\",\n", + " \"feat_310\",\n", + " \"feat_311\",\n", + " \"feat_312\",\n", + " \"feat_313\",\n", + " \"feat_314\",\n", + " \"feat_315\",\n", + " \"feat_316\",\n", + " \"feat_317\",\n", + " \"feat_318\",\n", + " \"feat_319\",\n", + " \"feat_320\",\n", + " \"feat_321\",\n", + " \"feat_322\",\n", + " \"feat_323\",\n", + " \"feat_324\",\n", + " \"feat_325\",\n", + " \"feat_326\",\n", + " \"feat_327\",\n", + " \"feat_328\",\n", + " \"feat_329\",\n", + " \"feat_330\",\n", + " \"feat_331\",\n", + " \"feat_332\",\n", + " \"feat_333\",\n", + " \"feat_334\",\n", + " \"feat_335\",\n", + " \"feat_336\",\n", + " \"feat_337\",\n", + " \"feat_338\",\n", + " \"feat_339\",\n", + " \"feat_340\",\n", + " \"feat_341\",\n", + " \"feat_342\",\n", + " \"feat_343\",\n", + " \"feat_344\",\n", + " \"feat_345\",\n", + " \"feat_346\",\n", + " \"feat_347\",\n", + " \"feat_348\",\n", + " \"feat_349\",\n", + " \"feat_350\",\n", + " \"feat_351\",\n", + " \"feat_352\",\n", + " \"feat_353\",\n", + " \"feat_354\",\n", + " \"feat_355\",\n", + " \"feat_356\",\n", + " \"feat_357\",\n", + " \"feat_358\",\n", + " \"feat_359\",\n", + " \"feat_360\",\n", + " \"feat_361\",\n", + " \"feat_362\",\n", + " \"feat_363\",\n", + " \"feat_364\",\n", + " \"feat_365\",\n", + " \"feat_366\",\n", + " \"feat_367\",\n", + " \"feat_368\",\n", + " \"feat_369\",\n", + " \"feat_370\",\n", + " \"feat_371\",\n", + " \"feat_372\",\n", + " \"feat_373\",\n", + " \"feat_374\",\n", + " \"feat_375\",\n", + " \"feat_376\",\n", + " \"feat_377\",\n", + " \"feat_378\",\n", + " \"feat_379\",\n", + " \"feat_380\",\n", + " \"feat_381\",\n", + " \"feat_382\",\n", + " \"feat_383\",\n", + " \"feat_384\",\n", + " \"feat_385\",\n", + " \"feat_386\",\n", + " \"feat_387\",\n", + " \"feat_388\",\n", + " \"feat_389\",\n", + " \"feat_390\",\n", + " \"feat_391\",\n", + " \"feat_392\",\n", + " \"feat_393\",\n", + " \"feat_394\",\n", + " \"feat_395\",\n", + " \"feat_396\",\n", + " \"feat_397\",\n", + " \"feat_398\",\n", + " \"feat_399\",\n", + " \"feat_400\",\n", + " \"feat_401\",\n", + " \"feat_402\",\n", + " \"feat_403\",\n", + " \"feat_404\",\n", + " \"feat_405\",\n", + " \"feat_406\",\n", + " \"feat_407\",\n", + " \"feat_408\",\n", + " \"feat_409\",\n", + " \"feat_410\",\n", + " \"feat_411\",\n", + " \"feat_412\",\n", + " \"feat_413\",\n", + " \"feat_414\",\n", + " \"feat_415\",\n", + " \"feat_416\",\n", + " \"feat_417\",\n", + " \"feat_418\",\n", + " \"feat_419\",\n", + " \"feat_420\",\n", + " \"feat_421\",\n", + " \"feat_422\",\n", + " \"feat_423\",\n", + " \"feat_424\",\n", + " \"feat_425\",\n", + " \"feat_426\",\n", + " \"feat_427\",\n", + " \"feat_428\",\n", + " \"feat_429\",\n", + " \"feat_430\",\n", + " \"feat_431\",\n", + " \"feat_432\",\n", + " \"feat_433\",\n", + " \"feat_434\",\n", + " \"feat_435\",\n", + " \"feat_436\",\n", + " \"feat_437\",\n", + " \"feat_438\",\n", + " \"feat_439\",\n", + " \"feat_440\",\n", + " \"feat_441\",\n", + " \"feat_442\",\n", + " \"feat_443\",\n", + " \"feat_444\",\n", + " \"feat_445\",\n", + " \"feat_446\",\n", + " \"feat_447\",\n", + " \"feat_448\",\n", + " \"feat_449\",\n", + " \"feat_450\",\n", + " \"feat_451\",\n", + " \"feat_452\",\n", + " \"feat_453\",\n", + " \"feat_454\",\n", + " \"feat_455\",\n", + " \"feat_456\",\n", + " \"feat_457\",\n", + " \"feat_458\",\n", + " \"feat_459\",\n", + " \"feat_460\",\n", + " \"feat_461\",\n", + " \"feat_462\",\n", + " \"feat_463\",\n", + " \"feat_464\",\n", + " \"feat_465\",\n", + " \"feat_466\",\n", + " \"feat_467\",\n", + " \"feat_468\",\n", + " \"feat_469\",\n", + " \"feat_470\",\n", + " \"feat_471\",\n", + " \"feat_472\",\n", + " \"feat_473\",\n", + " \"feat_474\",\n", + " \"feat_475\",\n", + " \"feat_476\",\n", + " \"feat_477\",\n", + " \"feat_478\",\n", + " \"feat_479\",\n", + " \"feat_480\",\n", + " \"feat_481\",\n", + " \"feat_482\",\n", + " \"feat_483\",\n", + " \"feat_484\",\n", + " \"feat_485\",\n", + " \"feat_486\",\n", + " \"feat_487\",\n", + " \"feat_488\",\n", + " \"feat_489\",\n", + " \"feat_490\",\n", + " \"feat_491\",\n", + " \"feat_492\",\n", + " \"feat_493\",\n", + " \"feat_494\",\n", + " \"feat_495\",\n", + " \"feat_496\",\n", + " \"feat_497\",\n", + " \"feat_498\",\n", + " \"feat_499\",\n", + " \"feat_500\",\n", + " \"feat_501\",\n", + " \"feat_502\",\n", + " \"feat_503\",\n", + " \"feat_504\",\n", + " \"feat_505\",\n", + " \"feat_506\",\n", + " \"feat_507\",\n", + " \"feat_508\",\n", + " \"feat_509\",\n", + " \"feat_510\",\n", + " \"feat_511\",\n", + " \"feat_512\",\n", + " \"feat_513\",\n", + " \"feat_514\",\n", + " \"feat_515\",\n", + " \"feat_516\",\n", + " \"feat_517\",\n", + " \"feat_518\",\n", + " \"feat_519\",\n", + " \"feat_520\",\n", + " \"feat_521\",\n", + " \"feat_522\",\n", + " \"feat_523\",\n", + " \"feat_524\",\n", + " \"feat_525\",\n", + " \"feat_526\",\n", + " \"feat_527\",\n", + " \"feat_528\",\n", + " \"feat_529\",\n", + " \"feat_530\",\n", + " \"feat_531\",\n", + " \"feat_532\",\n", + " \"feat_533\",\n", + " \"feat_534\",\n", + " \"feat_535\",\n", + " \"feat_536\",\n", + " \"feat_537\",\n", + " \"feat_538\",\n", + " \"feat_539\",\n", + " \"feat_540\",\n", + " \"feat_541\",\n", + " \"feat_542\",\n", + " \"feat_543\",\n", + " \"feat_544\",\n", + " \"feat_545\",\n", + " \"feat_546\",\n", + " \"feat_547\",\n", + " \"feat_548\",\n", + " \"feat_549\",\n", + " \"feat_550\",\n", + " \"feat_551\",\n", + " \"feat_552\",\n", + " \"feat_553\",\n", + " \"feat_554\",\n", + " \"feat_555\",\n", + " \"feat_556\",\n", + " \"feat_557\",\n", + " \"feat_558\",\n", + " \"feat_559\",\n", + " \"feat_560\",\n", + " \"feat_561\",\n", + " \"feat_562\",\n", + " \"feat_563\",\n", + " \"feat_564\",\n", + " \"feat_565\",\n", + " \"feat_566\",\n", + " \"feat_567\",\n", + " \"feat_568\",\n", + " \"feat_569\",\n", + " \"feat_570\",\n", + " \"feat_571\",\n", + " \"feat_572\",\n", + " \"feat_573\",\n", + " \"feat_574\",\n", + " \"feat_575\",\n", + " \"feat_576\",\n", + " \"feat_577\",\n", + " \"feat_578\",\n", + " \"feat_579\",\n", + " \"feat_580\",\n", + " \"feat_581\",\n", + " \"feat_582\",\n", + " \"feat_583\",\n", + " \"feat_584\",\n", + " \"feat_585\",\n", + " \"feat_586\",\n", + " \"feat_587\",\n", + " \"feat_588\",\n", + " \"feat_589\",\n", + " \"feat_590\",\n", + " \"feat_591\",\n", + " \"feat_592\",\n", + " \"feat_593\",\n", + " \"feat_594\",\n", + " \"feat_595\",\n", + " \"feat_596\",\n", + " \"feat_597\",\n", + " \"feat_598\",\n", + " \"feat_599\",\n", + " \"feat_600\",\n", + " \"feat_601\",\n", + " \"feat_602\",\n", + " \"feat_603\",\n", + " \"feat_604\",\n", + " \"feat_605\",\n", + " \"feat_606\",\n", + " \"feat_607\",\n", + " \"feat_608\",\n", + " \"feat_609\",\n", + " \"feat_610\",\n", + " \"feat_611\",\n", + " \"feat_612\",\n", + " \"feat_613\",\n", + " \"feat_614\",\n", + " \"feat_615\",\n", + " \"feat_616\",\n", + " \"feat_617\",\n", + " \"feat_618\",\n", + " \"feat_619\",\n", + " \"feat_620\",\n", + " \"feat_621\",\n", + " \"feat_622\",\n", + " \"feat_623\",\n", + " \"feat_624\",\n", + " \"feat_625\",\n", + " \"feat_626\",\n", + " \"feat_627\",\n", + " \"feat_628\",\n", + " \"feat_629\",\n", + " \"feat_630\",\n", + " \"feat_631\",\n", + " \"feat_632\",\n", + " \"feat_633\",\n", + " \"feat_634\",\n", + " \"feat_635\",\n", + " \"feat_636\",\n", + " \"feat_637\",\n", + " \"feat_638\",\n", + " \"feat_639\",\n", + " \"feat_640\",\n", + " \"feat_641\",\n", + " \"feat_642\",\n", + " \"feat_643\",\n", + " \"feat_644\",\n", + " \"feat_645\",\n", + " \"feat_646\",\n", + " \"feat_647\",\n", + " \"feat_648\",\n", + " \"feat_649\",\n", + " \"feat_650\",\n", + " \"feat_651\",\n", + " \"feat_652\",\n", + " \"feat_653\",\n", + " \"feat_654\",\n", + " \"feat_655\",\n", + " \"feat_656\",\n", + " \"feat_657\",\n", + " \"feat_658\",\n", + " \"feat_659\",\n", + " \"feat_660\",\n", + " \"feat_661\",\n", + " \"feat_662\",\n", + " \"feat_663\",\n", + " \"feat_664\",\n", + " \"feat_665\",\n", + " \"feat_666\",\n", + " \"feat_667\",\n", + " \"feat_668\",\n", + " \"feat_669\",\n", + " \"feat_670\",\n", + " \"feat_671\",\n", + " \"feat_672\",\n", + " \"feat_673\",\n", + " \"feat_674\",\n", + " \"feat_675\",\n", + " \"feat_676\",\n", + " \"feat_677\",\n", + " \"feat_678\",\n", + " \"feat_679\",\n", + " \"feat_680\",\n", + " \"feat_681\",\n", + " \"feat_682\",\n", + " \"feat_683\",\n", + " \"feat_684\",\n", + " \"feat_685\",\n", + " \"feat_686\",\n", + " \"feat_687\",\n", + " \"feat_688\",\n", + " \"feat_689\",\n", + " \"feat_690\",\n", + " \"feat_691\",\n", + " \"feat_692\",\n", + " \"feat_693\",\n", + " \"feat_694\",\n", + " \"feat_695\",\n", + " \"feat_696\",\n", + " \"feat_697\",\n", + " \"feat_698\",\n", + " \"feat_699\",\n", + " \"feat_700\",\n", + " \"feat_701\",\n", + " \"feat_702\",\n", + " \"feat_703\",\n", + " \"feat_704\",\n", + " \"feat_705\",\n", + " \"feat_706\",\n", + " \"feat_707\",\n", + " \"feat_708\",\n", + " \"feat_709\",\n", + " \"feat_710\",\n", + " \"feat_711\",\n", + " \"feat_712\",\n", + " \"feat_713\",\n", + " \"feat_714\",\n", + " \"feat_715\",\n", + " \"feat_716\",\n", + " \"feat_717\",\n", + " \"feat_718\",\n", + " \"feat_719\",\n", + " \"feat_720\",\n", + " \"feat_721\",\n", + " \"feat_722\",\n", + " \"feat_723\",\n", + " \"feat_724\",\n", + " \"feat_725\",\n", + " \"feat_726\",\n", + " \"feat_727\",\n", + " \"feat_728\",\n", + " \"feat_729\",\n", + " \"feat_730\",\n", + " \"feat_731\",\n", + " \"feat_732\",\n", + " \"feat_733\",\n", + " \"feat_734\",\n", + " \"feat_735\",\n", + " \"feat_736\",\n", + " \"feat_737\",\n", + " \"feat_738\",\n", + " \"feat_739\",\n", + " \"feat_740\",\n", + " \"feat_741\",\n", + " \"feat_742\",\n", + " \"feat_743\",\n", + " \"feat_744\",\n", + " \"feat_745\",\n", + " \"feat_746\",\n", + " \"feat_747\",\n", + " \"feat_748\",\n", + " \"feat_749\",\n", + " \"feat_750\",\n", + " \"feat_751\",\n", + " \"feat_752\",\n", + " \"feat_753\",\n", + " \"feat_754\",\n", + " \"feat_755\",\n", + " \"feat_756\",\n", + " \"feat_757\",\n", + " \"feat_758\",\n", + " \"feat_759\",\n", + " \"feat_760\",\n", + " \"feat_761\",\n", + " \"feat_762\",\n", + " \"feat_763\",\n", + " \"feat_764\",\n", + " \"feat_765\",\n", + " \"feat_766\",\n", + " \"feat_767\"\n", + " ],\n", + " \"feature_file\": \"paper_feats.npy\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"paper\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": \"ogbn_mag240m_gens/nodes_paper_tab_gen_0.pkl\"\n", + " },\n", + " {\n", + " \"type\": \"uniform\",\n", + " \"features_list\": [\n", + " \"year\",\n", + " \"label\"\n", + " ],\n", + " \"feature_file\": \"year_label.npy\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"paper\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": \"ogbn_mag240m_gens/nodes_paper_tab_gen_1.pkl\"\n", + " }\n", + " ]\n", + " },\n", + " {\n", + " \"name\": \"author\",\n", + " \"count\": 122383112,\n", + " \"features_path\": null,\n", + " \"features\": []\n", + " },\n", + " {\n", + " \"name\": \"institution\",\n", + " \"count\": 25721,\n", + " \"features_path\": null,\n", + " \"features\": []\n", + " }\n", + " ],\n", + " \"edges\": [\n", + " {\n", + " \"name\": \"writes\",\n", + " \"count\": 386022720,\n", + " \"src_node_type\": \"author\",\n", + " \"dst_node_type\": \"paper\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"writes_list.parquet\",\n", + " \"[gen]structure_generator\": {\n", + " \"type\": \"RMAT\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"writes\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": \"ogbn_mag240m_gens/writes_struct_gen.pkl\"\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"affiliated_with\",\n", + " \"count\": 44592586,\n", + " \"src_node_type\": \"author\",\n", + " \"dst_node_type\": \"institution\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"affiliated_with_list.parquet\",\n", + " \"[gen]structure_generator\": {\n", + " \"type\": \"RMAT\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"affiliated_with\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": \"ogbn_mag240m_gens/affiliated_with_struct_gen.pkl\"\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"cites\",\n", + " \"count\": 1297748926,\n", + " \"src_node_type\": \"paper\",\n", + " \"dst_node_type\": \"paper\",\n", + " \"directed\": false,\n", + " \"features\": [],\n", + " \"features_path\": null,\n", + " \"structure_path\": \"cites_list.parquet\",\n", + " \"[gen]structure_generator\": {\n", + " \"type\": \"RMAT\",\n", + " \"data_source\": {\n", + " \"type\": \"cfg\",\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\",\n", + " \"name\": \"cites\"\n", + " },\n", + " \"params\": {},\n", + " \"dump_path\": \"ogbn_mag240m_gens/cites_struct_gen.pkl\"\n", + " }\n", + " }\n", + " ],\n", + " \"path\": \"/raid/ogbn_mag240m_syngen\"\n", + "}" + ] + } + ], + "source": [ + "!cat $configs_dir/with_gen_dump.json" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "25a65d4e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "0it [00:00, ?it/s]\n", + "100%|█████████████████████████████████████████| 768/768 [10:16<00:00, 1.24it/s]\n", + "100%|█████████████████████████████████████████████| 2/2 [00:00<00:00, 2.99it/s]\n", + "0it [00:00, ?it/s]\n", + "NODE paper FIT TOOK: 705.66\n", + "FIT NODES TOOK: 705.66\n", + "DEBUG:root:Initialized logger\n", + "DEBUG:root:Using seed: 20\n", + "DEBUG:root:Fit results dst_src: None\n", + "DEBUG:root:Fit results src_dst: (0.4493778749717661, 0.16335407041150202, 0.1362311795696754, 0.2510368750470564)\n", + "EDGE writes STRUCTURAL FIT TOOK: 112.65\n", + "DEBUG:root:Initialized logger\n", + "DEBUG:root:Using seed: 99\n", + "DEBUG:root:Fit results dst_src: None\n", + "DEBUG:root:Fit results src_dst: (0.37499999944120643, 0.12499999906867743, 0.12500000055879357, 0.3750000009313226)\n", + "EDGE affiliated_with STRUCTURAL FIT TOOK: 6.82\n", + "DEBUG:root:Initialized logger\n", + "DEBUG:root:Using seed: 1\n", + "DEBUG:root:Fit results: (0.4468597402097436, 0.14895324673658117, 0.14895324673658117, 0.25523376631709405)\n", + "EDGE cites STRUCTURAL FIT TOOK: 114.06\n", + "FIT EDGES TOOK: 233.54\n", + "FIT TOOK: 939.19\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_with_gen_dump/writes_list.parquet parquet\n", + "EDGE writes STRUCT GEN TOOK: 43.66\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_with_gen_dump/affiliated_with_list.parquet parquet\n", + "EDGE affiliated_with STRUCT GEN TOOK: 6.35\n", + "INFO:syngen.utils.io_utils:writing to file /raid/ogbn_mag240m_with_gen_dump/cites_list.parquet parquet\n", + "EDGE cites STRUCT GEN TOOK: 50.64\n", + "GEN STRUCT TOOK: 100.65\n", + "100%|███████████████████████████████████████████| 40/40 [04:12<00:00, 6.31s/it]\n", + "GEN TABULAR NODE FEATURES TOOK: 264.07\n", + "GEN TABULAR EDGE FEATURES TOOK: 0.00\n", + "GEN ALIGNMENT TAKE: 0.00\n" + ] + } + ], + "source": [ + "!python -m syngen synthesize --config-path $configs_dir/with_gen_dump.json --save-path /raid/ogbn_mag240m_with_gen_dump --verbose" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "d3f0e6e9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.9G\t/raid/ogbn_mag240m_with_gen_dump/writes_list.parquet\n", + "2.1G\t/raid/ogbn_mag240m_with_gen_dump/paper_tabular_features/year_label.npy\n", + "193G\t/raid/ogbn_mag240m_with_gen_dump/paper_tabular_features/paper_feats.npy\n", + "195G\t/raid/ogbn_mag240m_with_gen_dump/paper_tabular_features\n", + "4.9G\t/raid/ogbn_mag240m_with_gen_dump/cites_list.parquet\n", + "251M\t/raid/ogbn_mag240m_with_gen_dump/affiliated_with_list.parquet\n", + "200K\t/raid/ogbn_mag240m_with_gen_dump/graph_metadata.json\n", + "202G\t/raid/ogbn_mag240m_with_gen_dump\n" + ] + } + ], + "source": [ + "!du -ah /raid/ogbn_mag240m_with_gen_dump" + ] + }, + { + "cell_type": "markdown", + "id": "8650c6e3", + "metadata": {}, + "source": [ + "## Prepare SynGen Configuration that scales the dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "dd08ec91", + "metadata": {}, + "outputs": [], + "source": [ + "import os" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "1ba81eae", + "metadata": {}, + "outputs": [], + "source": [ + "scale_config_files = {}\n", + "for scale in [1, 2, 4]:\n", + " edges_scale = scale ** 3\n", + " out_file = f'{configs_dir}/scale_nodes_{scale}_edges_{edges_scale}.json'\n", + " scale_config_files[scale] = out_file\n", + " if os.path.exists(out_file):\n", + " continue\n", + " !python -m syngen mimic-dataset --node-scale=$scale --edge-scale=$edges_scale --gen-dump-path=$generators_dump_dir --output-file=$out_file --dataset-path $preprocessed_path --tab-gen uniform" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ca2d09bf", + "metadata": {}, + "outputs": [], + "source": [ + "def generate_scale(scale):\n", + " config_file = scale_config_files[scale]\n", + " out_dir = f\"/raid/scale_{scale}\"\n", + " !python -m syngen synthesize --config-path $config_file --save-path $out_dir --verbose\n", + " !du -ah $out_dir" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "49e340d6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "NODE paper FIT TOOK: 0.02\n", + "FIT NODES TOOK: 0.02\n", + "EDGE writes STRUCTURAL FIT TOOK: 0.00\n", + "EDGE affiliated_with STRUCTURAL FIT TOOK: 0.00\n", + "EDGE cites STRUCTURAL FIT TOOK: 0.00\n", + "FIT EDGES TOOK: 0.01\n", + "FIT TOOK: 0.03\n", + "100%|█████████████████████████████████████████| 256/256 [01:59<00:00, 2.15it/s]\n", + "INFO:syngen.utils.io_utils:writing to file /raid/scale_2/writes_list.parquet parquet\n", + "EDGE writes STRUCT GEN TOOK: 206.77\n", + "100%|██████████████████████████████████████| 4096/4096 [00:36<00:00, 111.33it/s]\n", + "INFO:syngen.utils.io_utils:writing to file /raid/scale_2/affiliated_with_list.parquet parquet\n", + "EDGE affiliated_with STRUCT GEN TOOK: 66.71\n", + "100%|█████████████████████████████████████████| 528/528 [03:28<00:00, 2.53it/s]\n", + "INFO:syngen.utils.io_utils:writing to file /raid/scale_2/cites_list.parquet parquet\n", + "EDGE cites STRUCT GEN TOOK: 394.74\n", + "GEN STRUCT TOOK: 668.22\n", + "100%|███████████████████████████████████████████| 79/79 [09:52<00:00, 7.50s/it]\n", + "GEN TABULAR NODE FEATURES TOOK: 616.06\n", + "GEN TABULAR EDGE FEATURES TOOK: 0.00\n", + "GEN ALIGNMENT TAKE: 0.00\n", + "23G\t/raid/scale_2/writes_list.parquet\n", + "4.1G\t/raid/scale_2/paper_tabular_features/year_label.npy\n", + "385G\t/raid/scale_2/paper_tabular_features/paper_feats.npy\n", + "389G\t/raid/scale_2/paper_tabular_features\n", + "43G\t/raid/scale_2/cites_list.parquet\n", + "2.0G\t/raid/scale_2/affiliated_with_list.parquet\n", + "200K\t/raid/scale_2/graph_metadata.json\n", + "456G\t/raid/scale_2\n" + ] + } + ], + "source": [ + "generate_scale(2)" + ] + }, + { + "cell_type": "markdown", + "id": "fdffa9f7", + "metadata": {}, + "source": [ + "## Memory-mapped files for edge lists" + ] + }, + { + "cell_type": "markdown", + "id": "db036564", + "metadata": {}, + "source": [ + "Instead of chunk concatenation after the generation SynGen supports memory mapped files that allow multi-process writing into the single file. To enable this feature, you need to specify the edge `structure_path` as `.npy` file. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "4374298b", + "metadata": {}, + "outputs": [], + "source": [ + "import json" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "0f8a8580", + "metadata": {}, + "outputs": [], + "source": [ + "memmap_scale_config_files = {}\n", + "\n", + "for scale, config_file in scale_config_files.items():\n", + " with open(config_file, 'r') as f:\n", + " cfg = json.load(f)\n", + " \n", + " for edge_info in cfg[\"edges\"]:\n", + " edge_info['structure_path'] = edge_info['structure_path'].split('.')[0] + '.npy'\n", + " \n", + " memmap_cfg_file = config_file[:-5] + \"_memmap.json\"\n", + " memmap_scale_config_files[scale] = memmap_cfg_file\n", + " \n", + " if os.path.exists(memmap_cfg_file):\n", + " continue\n", + " \n", + " with open(memmap_cfg_file, 'w') as f:\n", + " json.dump(cfg, f, indent=4)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "d84f4ab9", + "metadata": {}, + "outputs": [], + "source": [ + "def generate_scale_memmap(scale):\n", + " config_file = memmap_scale_config_files[scale]\n", + " out_dir = f\"/raid/scale_{scale}_memmap\"\n", + " !python -m syngen synthesize --config-path $config_file --save-path $out_dir --verbose\n", + " !du -ah $out_dir" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "01ae38b5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DGL backend not selected or invalid. Assuming PyTorch for now.\n", + "Setting the default backend to \"pytorch\". You can change it in the ~/.dgl/config.json file or export the DGLBACKEND environment variable. Valid options are: pytorch, mxnet, tensorflow (all lowercase)\n", + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "NODE paper FIT TOOK: 0.08\n", + "FIT NODES TOOK: 0.08\n", + "EDGE writes STRUCTURAL FIT TOOK: 0.03\n", + "EDGE affiliated_with STRUCTURAL FIT TOOK: 0.04\n", + "EDGE cites STRUCTURAL FIT TOOK: 0.02\n", + "FIT EDGES TOOK: 0.10\n", + "FIT TOOK: 0.17\n", + "100%|█████████████████████████████████████████████| 4/4 [00:30<00:00, 7.72s/it]\n", + "EDGE writes STRUCT GEN TOOK: 32.58\n", + "EDGE affiliated_with STRUCT GEN TOOK: 4.20\n", + "100%|███████████████████████████████████████████| 10/10 [00:23<00:00, 2.31s/it]\n", + "EDGE cites STRUCT GEN TOOK: 24.36\n", + "GEN STRUCT TOOK: 61.14\n", + "100%|███████████████████████████████████████████| 40/40 [03:17<00:00, 4.93s/it]\n", + "GEN TABULAR NODE FEATURES TOOK: 209.58\n", + "GEN TABULAR EDGE FEATURES TOOK: 0.00\n", + "GEN ALIGNMENT TAKE: 0.00\n", + "2.9G\t/raid/scale_1_memmap/writes_list.npy\n", + "341M\t/raid/scale_1_memmap/affiliated_with_list.npy\n", + "2.0G\t/raid/scale_1_memmap/paper_tabular_features/year_label.npy\n", + "192G\t/raid/scale_1_memmap/paper_tabular_features/paper_feats.npy\n", + "194G\t/raid/scale_1_memmap/paper_tabular_features\n", + "200K\t/raid/scale_1_memmap/graph_metadata.json\n", + "4.9G\t/raid/scale_1_memmap/cites_list.npy\n", + "203G\t/raid/scale_1_memmap\n" + ] + } + ], + "source": [ + "generate_scale_memmap(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "8e24fc93", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "NODE paper FIT TOOK: 0.01\n", + "FIT NODES TOOK: 0.01\n", + "EDGE writes STRUCTURAL FIT TOOK: 0.00\n", + "EDGE affiliated_with STRUCTURAL FIT TOOK: 0.01\n", + "EDGE cites STRUCTURAL FIT TOOK: 0.01\n", + "FIT EDGES TOOK: 0.02\n", + "FIT TOOK: 0.03\n", + "100%|█████████████████████████████████████████| 256/256 [01:47<00:00, 2.37it/s]\n", + "EDGE writes STRUCT GEN TOOK: 110.77\n", + "100%|██████████████████████████████████████| 4096/4096 [00:25<00:00, 159.79it/s]\n", + "EDGE affiliated_with STRUCT GEN TOOK: 39.71\n", + "100%|█████████████████████████████████████████| 528/528 [01:54<00:00, 4.62it/s]\n", + "EDGE cites STRUCT GEN TOOK: 116.67\n", + "GEN STRUCT TOOK: 267.15\n", + "100%|███████████████████████████████████████████| 78/78 [06:55<00:00, 5.33s/it]\n", + "GEN TABULAR NODE FEATURES TOOK: 438.53\n", + "GEN TABULAR EDGE FEATURES TOOK: 0.00\n", + "GEN ALIGNMENT TAKE: 0.00\n", + "24G\t/raid/scale_2_memmap/writes_list.npy\n", + "2.7G\t/raid/scale_2_memmap/affiliated_with_list.npy\n", + "4.0G\t/raid/scale_2_memmap/paper_tabular_features/year_label.npy\n", + "385G\t/raid/scale_2_memmap/paper_tabular_features/paper_feats.npy\n", + "389G\t/raid/scale_2_memmap/paper_tabular_features\n", + "200K\t/raid/scale_2_memmap/graph_metadata.json\n", + "42G\t/raid/scale_2_memmap/cites_list.npy\n", + "456G\t/raid/scale_2_memmap\n" + ] + } + ], + "source": [ + "generate_scale_memmap(2)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "97cbf2e3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "INFO:__main__:=========================================\n", + "INFO:__main__:| Synthetic Graph Generation Tool |\n", + "INFO:__main__:=========================================\n", + "NODE paper FIT TOOK: 0.01\n", + "FIT NODES TOOK: 0.01\n", + "EDGE writes STRUCTURAL FIT TOOK: 0.01\n", + "EDGE affiliated_with STRUCTURAL FIT TOOK: 0.01\n", + "EDGE cites STRUCTURAL FIT TOOK: 0.01\n", + "FIT EDGES TOOK: 0.02\n", + "FIT TOOK: 0.03\n", + "100%|█████████████████████████████████████| 16384/16384 [27:41<00:00, 9.86it/s]\n", + "EDGE writes STRUCT GEN TOOK: 1669.94\n", + "100%|███████████████████████████████████████| 4096/4096 [01:30<00:00, 45.09it/s]\n", + "EDGE affiliated_with STRUCT GEN TOOK: 107.36\n", + "100%|███████████████████████████████████████| 8256/8256 [21:34<00:00, 6.38it/s]\n", + "EDGE cites STRUCT GEN TOOK: 1301.40\n", + "GEN STRUCT TOOK: 3078.70\n", + "100%|█████████████████████████████████████████| 157/157 [16:05<00:00, 6.15s/it]\n", + "100%|█████████████████████████████████████████████| 3/3 [00:31<00:00, 10.60s/it]\n", + "GEN TABULAR NODE FEATURES TOOK: 1009.78\n", + "GEN TABULAR EDGE FEATURES TOOK: 0.00\n", + "GEN ALIGNMENT TAKE: 0.00\n", + "185G\t/raid/scale_4_memmap/writes_list.npy\n", + "22G\t/raid/scale_4_memmap/affiliated_with_list.npy\n", + "8.1G\t/raid/scale_4_memmap/paper_tabular_features/year_label.npy\n", + "769G\t/raid/scale_4_memmap/paper_tabular_features/paper_feats.npy\n", + "777G\t/raid/scale_4_memmap/paper_tabular_features\n", + "200K\t/raid/scale_4_memmap/graph_metadata.json\n", + "329G\t/raid/scale_4_memmap/cites_list.npy\n", + "1.3T\t/raid/scale_4_memmap\n" + ] + } + ], + "source": [ + "generate_scale_memmap(4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cccea097", + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_cora_demo.ipynb b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_cora_demo.ipynb new file mode 100644 index 000000000..de8dec8ad --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_cora_demo.ipynb @@ -0,0 +1,10049 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "572b9773", + "metadata": {}, + "source": [ + "# Copyright 2023 NVIDIA Corporation. All Rights Reserved.\n", + "#\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# http://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License.\n", + "# ==============================================================================" + ] + }, + { + "cell_type": "markdown", + "id": "abb63ccc", + "metadata": {}, + "source": [ + "# End to end graph generation demo (CORA)" + ] + }, + { + "cell_type": "markdown", + "id": "0b044e39", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "In this notebook, we have walked through the complete process of generating a synthetic dataset based on a CORA dataset. The CORA dataset consists of scientific publications classified into one of seven classes. Each publication in the dataset is described by a 0/1-valued word vector indicating the absence/presence of the corresponding word from the dictionary, so we can interpret the CORA dataset as a graph with categorical node features.\n", + "\n", + "Content:\n", + "\n", + "1. [Prepare the original dataset](#1)\n", + "1. [Preprare SynGen Configuration](#2)\n", + "1. [Dataset Generation](#3)\n", + "1. [Tabular data evaluation](#4)\n", + "1. [Structure evaluation](#5)" + ] + }, + { + "cell_type": "markdown", + "id": "3a3a6525", + "metadata": {}, + "source": [ + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b4a5825e", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n" + ] + } + ], + "source": [ + "# preprocessing\n", + "from syngen.preprocessing.datasets import CORAPreprocessing\n", + "\n", + "# config\n", + "from syngen.configuration import SynGenConfiguration\n", + "\n", + "# generation\n", + "from syngen.synthesizer import ConfigurationGraphSynthesizer\n", + "\n", + "# evaluation\n", + "from syngen.analyzer.tabular import TabularMetrics\n", + "from syngen.analyzer.graph import Graph\n", + "from syngen.analyzer.graph.stats import get_dd_simmilarity_score\n", + "from syngen.analyzer.graph.analyser import AnalysisModule\n", + "\n", + "# utils\n", + "import copy\n", + "from syngen.utils.types import MetaData" + ] + }, + { + "cell_type": "markdown", + "id": "2a6b8d9c", + "metadata": {}, + "source": [ + "\n", + "## Prepare original dataset" + ] + }, + { + "cell_type": "markdown", + "id": "be21bba6", + "metadata": {}, + "source": [ + "SynGen requires the data to be in SynGen dataset format or simply SynGen format, so firstly, we transform the raw Cora dataset into SynGen format. If you don't download Cora before, you may pass `download=True` as `CoraPreprocessing` class supports automatic downloading." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "53f9a37e", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = '/workspace/data/cora'\n", + "preprocessed_path = '/workspace/data/cora_preprocessed'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "897b6660", + "metadata": {}, + "outputs": [], + "source": [ + "preprocessing = CORAPreprocessing(source_path=data_path, destination_path=preprocessed_path, download=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1b346e41", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_original = preprocessing.transform(use_cache=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a2b24750", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'nodes': [{'name': 'paper',\n", + " 'count': 2708,\n", + " 'features': [{'name': 'w_0',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'},\n", + " {'name': 'w_1', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_2', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_3', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_4', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_5', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_6', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_7', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_8', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_9', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_10', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_11', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_12', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_13', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_14', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_15', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_16', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_17', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_18', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_19', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_20', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_21', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_22', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_23', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_24', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_25', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_26', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_27', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_28', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_29', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_30', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_31', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_32', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_33', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_34', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_35', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_36', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_37', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_38', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_39', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_40', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_41', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_42', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_43', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_44', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_45', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_46', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_47', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_48', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_49', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_50', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_51', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_52', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_53', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_54', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_55', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_56', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_57', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_58', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_59', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_60', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_61', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_62', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_63', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_64', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_65', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_66', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_67', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_68', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_69', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_70', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_71', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_72', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_73', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_74', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_75', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_76', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_77', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_78', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_79', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_80', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_81', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_82', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_83', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_84', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_85', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_86', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_87', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_88', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_89', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_90', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_91', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_92', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_93', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_94', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_95', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_96', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_97', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_98', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_99', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_100', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_101', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_102', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_103', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_104', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_105', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_106', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_107', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_108', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_109', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_110', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_111', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_112', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_113', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_114', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_115', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_116', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_117', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_118', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_119', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_120', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_121', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_122', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_123', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_124', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_125', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_126', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_127', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_128', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_129', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_130', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_131', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_132', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_133', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_134', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_135', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_136', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_137', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_138', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_139', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_140', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_141', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_142', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_143', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_144', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_145', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_146', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_147', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_148', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_149', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_150', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_151', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_152', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_153', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_154', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_155', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_156', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_157', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_158', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_159', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_160', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_161', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_162', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_163', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_164', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_165', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_166', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_167', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_168', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_169', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_170', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_171', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_172', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_173', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_174', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_175', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_176', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_177', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_178', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_179', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_180', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_181', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_182', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_183', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_184', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_185', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_186', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_187', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_188', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_189', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_190', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_191', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_192', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_193', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_194', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_195', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_196', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_197', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_198', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_199', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_200', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_201', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_202', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_203', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_204', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_205', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_206', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_207', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_208', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_209', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_210', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_211', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_212', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_213', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_214', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_215', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_216', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_217', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_218', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_219', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_220', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_221', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_222', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_223', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_224', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_225', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_226', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_227', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_228', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_229', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_230', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_231', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_232', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_233', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_234', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_235', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_236', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_237', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_238', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_239', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_240', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_241', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_242', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_243', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_244', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_245', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_246', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_247', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_248', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_249', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_250', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_251', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_252', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_253', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_254', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_255', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_256', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_257', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_258', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_259', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_260', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_261', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_262', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_263', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_264', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_265', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_266', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_267', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_268', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_269', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_270', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_271', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_272', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_273', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_274', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_275', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_276', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_277', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_278', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_279', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_280', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_281', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_282', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_283', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_284', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_285', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_286', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_287', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_288', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_289', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_290', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_291', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_292', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_293', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_294', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_295', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_296', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_297', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_298', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_299', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_300', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_301', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_302', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_303', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_304', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_305', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_306', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_307', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_308', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_309', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_310', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_311', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_312', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_313', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_314', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_315', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_316', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_317', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_318', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_319', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_320', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_321', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_322', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_323', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_324', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_325', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_326', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_327', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_328', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_329', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_330', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_331', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_332', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_333', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_334', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_335', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_336', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_337', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_338', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_339', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_340', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_341', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_342', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_343', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_344', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_345', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_346', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_347', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_348', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_349', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_350', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_351', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_352', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_353', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_354', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_355', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_356', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_357', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_358', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_359', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_360', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_361', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_362', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_363', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_364', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_365', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_366', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_367', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_368', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_369', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_370', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_371', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_372', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_373', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_374', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_375', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_376', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_377', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_378', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_379', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_380', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_381', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_382', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_383', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_384', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_385', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_386', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_387', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_388', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_389', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_390', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_391', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_392', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_393', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_394', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_395', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_396', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_397', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_398', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_399', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_400', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_401', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_402', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_403', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_404', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_405', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_406', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_407', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_408', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_409', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_410', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_411', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_412', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_413', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_414', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_415', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_416', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_417', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_418', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_419', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_420', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_421', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_422', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_423', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_424', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_425', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_426', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_427', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_428', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_429', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_430', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_431', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_432', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_433', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_434', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_435', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_436', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_437', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_438', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_439', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_440', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_441', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_442', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_443', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_444', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_445', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_446', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_447', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_448', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_449', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_450', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_451', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_452', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_453', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_454', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_455', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_456', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_457', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_458', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_459', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_460', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_461', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_462', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_463', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_464', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_465', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_466', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_467', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_468', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_469', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_470', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_471', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_472', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_473', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_474', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_475', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_476', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_477', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_478', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_479', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_480', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_481', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_482', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_483', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_484', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_485', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_486', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_487', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_488', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_489', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_490', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_491', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_492', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_493', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_494', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_495', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_496', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_497', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_498', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_499', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_500', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_501', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_502', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_503', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_504', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_505', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_506', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_507', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_508', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_509', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_510', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_511', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_512', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_513', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_514', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_515', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_516', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_517', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_518', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_519', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_520', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_521', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_522', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_523', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_524', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_525', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_526', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_527', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_528', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_529', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_530', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_531', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_532', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_533', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_534', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_535', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_536', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_537', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_538', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_539', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_540', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_541', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_542', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_543', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_544', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_545', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_546', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_547', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_548', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_549', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_550', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_551', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_552', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_553', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_554', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_555', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_556', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_557', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_558', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_559', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_560', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_561', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_562', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_563', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_564', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_565', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_566', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_567', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_568', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_569', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_570', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_571', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_572', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_573', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_574', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_575', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_576', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_577', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_578', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_579', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_580', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_581', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_582', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_583', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_584', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_585', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_586', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_587', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_588', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_589', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_590', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_591', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_592', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_593', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_594', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_595', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_596', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_597', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_598', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_599', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_600', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_601', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_602', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_603', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_604', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_605', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_606', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_607', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_608', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_609', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_610', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_611', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_612', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_613', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_614', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_615', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_616', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_617', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_618', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_619', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_620', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_621', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_622', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_623', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_624', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_625', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_626', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_627', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_628', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_629', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_630', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_631', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_632', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_633', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_634', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_635', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_636', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_637', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_638', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_639', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_640', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_641', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_642', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_643', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_644', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_645', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_646', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_647', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_648', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_649', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_650', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_651', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_652', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_653', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_654', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_655', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_656', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_657', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_658', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_659', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_660', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_661', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_662', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_663', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_664', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_665', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_666', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_667', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_668', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_669', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_670', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_671', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_672', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_673', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_674', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_675', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_676', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_677', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_678', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_679', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_680', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_681', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_682', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_683', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_684', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_685', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_686', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_687', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_688', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_689', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_690', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_691', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_692', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_693', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_694', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_695', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_696', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_697', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_698', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_699', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_700', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_701', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_702', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_703', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_704', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_705', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_706', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_707', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_708', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_709', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_710', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_711', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_712', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_713', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_714', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_715', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_716', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_717', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_718', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_719', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_720', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_721', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_722', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_723', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_724', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_725', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_726', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_727', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_728', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_729', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_730', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_731', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_732', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_733', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_734', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_735', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_736', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_737', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_738', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_739', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_740', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_741', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_742', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_743', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_744', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_745', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_746', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_747', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_748', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_749', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_750', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_751', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_752', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_753', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_754', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_755', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_756', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_757', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_758', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_759', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_760', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_761', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_762', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_763', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_764', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_765', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_766', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_767', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_768', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_769', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_770', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_771', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_772', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_773', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_774', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_775', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_776', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_777', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_778', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_779', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_780', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_781', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_782', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_783', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_784', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_785', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_786', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_787', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_788', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_789', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_790', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_791', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_792', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_793', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_794', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_795', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_796', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_797', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_798', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_799', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_800', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_801', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_802', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_803', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_804', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_805', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_806', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_807', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_808', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_809', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_810', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_811', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_812', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_813', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_814', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_815', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_816', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_817', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_818', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_819', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_820', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_821', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_822', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_823', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_824', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_825', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_826', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_827', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_828', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_829', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_830', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_831', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_832', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_833', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_834', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_835', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_836', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_837', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_838', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_839', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_840', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_841', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_842', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_843', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_844', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_845', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_846', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_847', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_848', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_849', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_850', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_851', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_852', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_853', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_854', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_855', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_856', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_857', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_858', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_859', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_860', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_861', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_862', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_863', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_864', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_865', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_866', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_867', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_868', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_869', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_870', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_871', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_872', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_873', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_874', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_875', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_876', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_877', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_878', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_879', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_880', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_881', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_882', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_883', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_884', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_885', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_886', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_887', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_888', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_889', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_890', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_891', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_892', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_893', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_894', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_895', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_896', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_897', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_898', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_899', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_900', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_901', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_902', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_903', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_904', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_905', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_906', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_907', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_908', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_909', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_910', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_911', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_912', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_913', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_914', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_915', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_916', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_917', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_918', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_919', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_920', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_921', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_922', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_923', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_924', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_925', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_926', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_927', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_928', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_929', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_930', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_931', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_932', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_933', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_934', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_935', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_936', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_937', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_938', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_939', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_940', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_941', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_942', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_943', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_944', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_945', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_946', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_947', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_948', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_949', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_950', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_951', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_952', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_953', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_954', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_955', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_956', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_957', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_958', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_959', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_960', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_961', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_962', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_963', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_964', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_965', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_966', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_967', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_968', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_969', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_970', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_971', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_972', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_973', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_974', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_975', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_976', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_977', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_978', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_979', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_980', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_981', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_982', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_983', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_984', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_985', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_986', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_987', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_988', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_989', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_990', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_991', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_992', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_993', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_994', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_995', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_996', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_997', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_998', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_999', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " ...],\n", + " 'features_path': 'paper.parquet'}],\n", + " 'edges': [{'name': 'cite',\n", + " 'count': 5428,\n", + " 'src_node_type': 'paper',\n", + " 'dst_node_type': 'paper',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'cite_edge_list.parquet'}],\n", + " : '/workspace/data/cora_preprocessed'}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_original" + ] + }, + { + "cell_type": "markdown", + "id": "a9a9d4b7", + "metadata": {}, + "source": [ + "\n", + "## Preprare SynGen Configuration" + ] + }, + { + "cell_type": "markdown", + "id": "fa1f375d", + "metadata": {}, + "source": [ + "SynGen generation process is driven by the configuration that is the superset of the SynGen format metadata file. Let us create two configurations: a proper one that will mimic Cora dataset tabular and structural features and a random one." + ] + }, + { + "cell_type": "markdown", + "id": "fab950fe", + "metadata": {}, + "source": [ + "### Proper Synthetic " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "81e2c5b6", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_synthetic = feature_spec_original.copy()\n", + "\n", + "feature_spec_synthetic[MetaData.NODES][0][MetaData.TABULAR_GENERATORS] = [\n", + " {\n", + " MetaData.TYPE: \"kde\",\n", + " MetaData.FEATURES_LIST: -1, # copies all tabular features\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'configuration',\n", + " MetaData.PATH: preprocessed_path,\n", + " MetaData.NAME: \"paper\",\n", + " },\n", + " MetaData.PARAMS: {\n", + " }\n", + " }\n", + "]\n", + "\n", + "feature_spec_synthetic[MetaData.EDGES][0][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'cfg', # the same a 'configuration'\n", + " MetaData.PATH: preprocessed_path,\n", + " MetaData.NAME: \"cite\",\n", + " },\n", + " MetaData.PARAMS: {\n", + " \"has_self_loop\": False,\n", + " }\n", + "}\n", + "\n", + "# aligns 'label' node feature based on the 'cite' edges\n", + "feature_spec_synthetic[MetaData.ALIGNERS] = [\n", + " {\n", + " MetaData.TYPE: \"xgboost\",\n", + " MetaData.GRAPHS: ['cite'],\n", + " MetaData.NODES: {\"paper\": [\"label\"]},\n", + " MetaData.EDGES: {},\n", + " MetaData.PARAMS: {},\n", + " }\n", + "]\n", + "\n", + "config_proper = SynGenConfiguration(feature_spec_synthetic)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "da4d090a", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'cite',\n", + " 'count': 5428,\n", + " 'src_node_type': 'paper',\n", + " 'dst_node_type': 'paper',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'cite_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/cora_preprocessed',\n", + " : 'cite'},\n", + " : {'has_self_loop': False}}}],\n", + " : [{'name': 'paper',\n", + " 'count': 2708,\n", + " 'features': [{'name': 'w_0',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'},\n", + " {'name': 'w_1', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_2', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_3', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_4', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_5', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_6', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_7', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_8', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_9', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_10', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_11', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_12', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_13', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_14', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_15', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_16', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_17', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_18', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_19', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_20', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_21', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_22', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_23', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_24', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_25', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_26', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_27', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_28', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_29', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_30', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_31', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_32', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_33', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_34', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_35', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_36', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_37', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_38', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_39', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_40', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_41', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_42', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_43', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_44', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_45', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_46', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_47', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_48', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_49', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_50', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_51', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_52', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_53', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_54', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_55', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_56', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_57', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_58', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_59', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_60', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_61', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_62', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_63', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_64', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_65', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_66', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_67', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_68', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_69', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_70', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_71', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_72', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_73', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_74', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_75', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_76', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_77', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_78', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_79', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_80', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_81', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_82', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_83', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_84', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_85', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_86', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_87', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_88', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_89', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_90', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_91', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_92', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_93', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_94', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_95', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_96', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_97', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_98', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_99', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_100', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_101', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_102', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_103', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_104', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_105', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_106', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_107', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_108', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_109', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_110', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_111', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_112', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_113', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_114', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_115', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_116', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_117', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_118', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_119', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_120', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_121', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_122', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_123', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_124', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_125', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_126', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_127', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_128', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_129', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_130', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_131', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_132', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_133', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_134', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_135', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_136', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_137', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_138', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_139', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_140', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_141', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_142', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_143', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_144', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_145', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_146', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_147', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_148', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_149', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_150', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_151', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_152', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_153', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_154', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_155', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_156', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_157', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_158', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_159', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_160', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_161', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_162', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_163', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_164', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_165', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_166', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_167', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_168', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_169', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_170', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_171', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_172', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_173', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_174', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_175', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_176', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_177', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_178', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_179', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_180', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_181', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_182', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_183', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_184', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_185', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_186', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_187', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_188', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_189', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_190', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_191', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_192', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_193', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_194', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_195', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_196', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_197', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_198', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_199', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_200', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_201', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_202', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_203', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_204', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_205', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_206', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_207', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_208', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_209', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_210', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_211', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_212', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_213', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_214', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_215', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_216', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_217', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_218', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_219', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_220', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_221', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_222', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_223', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_224', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_225', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_226', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_227', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_228', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_229', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_230', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_231', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_232', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_233', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_234', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_235', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_236', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_237', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_238', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_239', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_240', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_241', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_242', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_243', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_244', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_245', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_246', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_247', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_248', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_249', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_250', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_251', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_252', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_253', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_254', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_255', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_256', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_257', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_258', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_259', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_260', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_261', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_262', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_263', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_264', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_265', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_266', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_267', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_268', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_269', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_270', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_271', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_272', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_273', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_274', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_275', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_276', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_277', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_278', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_279', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_280', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_281', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_282', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_283', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_284', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_285', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_286', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_287', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_288', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_289', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_290', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_291', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_292', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_293', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_294', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_295', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_296', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_297', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_298', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_299', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_300', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_301', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_302', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_303', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_304', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_305', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_306', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_307', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_308', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_309', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_310', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_311', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_312', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_313', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_314', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_315', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_316', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_317', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_318', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_319', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_320', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_321', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_322', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_323', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_324', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_325', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_326', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_327', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_328', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_329', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_330', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_331', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_332', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_333', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_334', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_335', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_336', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_337', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_338', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_339', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_340', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_341', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_342', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_343', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_344', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_345', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_346', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_347', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_348', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_349', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_350', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_351', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_352', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_353', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_354', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_355', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_356', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_357', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_358', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_359', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_360', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_361', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_362', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_363', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_364', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_365', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_366', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_367', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_368', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_369', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_370', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_371', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_372', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_373', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_374', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_375', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_376', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_377', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_378', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_379', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_380', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_381', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_382', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_383', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_384', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_385', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_386', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_387', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_388', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_389', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_390', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_391', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_392', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_393', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_394', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_395', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_396', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_397', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_398', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_399', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_400', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_401', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_402', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_403', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_404', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_405', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_406', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_407', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_408', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_409', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_410', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_411', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_412', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_413', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_414', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_415', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_416', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_417', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_418', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_419', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_420', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_421', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_422', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_423', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_424', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_425', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_426', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_427', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_428', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_429', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_430', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_431', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_432', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_433', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_434', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_435', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_436', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_437', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_438', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_439', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_440', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_441', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_442', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_443', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_444', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_445', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_446', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_447', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_448', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_449', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_450', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_451', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_452', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_453', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_454', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_455', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_456', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_457', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_458', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_459', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_460', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_461', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_462', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_463', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_464', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_465', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_466', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_467', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_468', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_469', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_470', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_471', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_472', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_473', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_474', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_475', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_476', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_477', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_478', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_479', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_480', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_481', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_482', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_483', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_484', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_485', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_486', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_487', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_488', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_489', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_490', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_491', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_492', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_493', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_494', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_495', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_496', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_497', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_498', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_499', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_500', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_501', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_502', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_503', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_504', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_505', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_506', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_507', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_508', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_509', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_510', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_511', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_512', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_513', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_514', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_515', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_516', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_517', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_518', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_519', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_520', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_521', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_522', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_523', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_524', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_525', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_526', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_527', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_528', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_529', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_530', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_531', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_532', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_533', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_534', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_535', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_536', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_537', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_538', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_539', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_540', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_541', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_542', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_543', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_544', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_545', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_546', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_547', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_548', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_549', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_550', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_551', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_552', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_553', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_554', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_555', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_556', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_557', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_558', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_559', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_560', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_561', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_562', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_563', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_564', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_565', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_566', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_567', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_568', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_569', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_570', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_571', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_572', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_573', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_574', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_575', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_576', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_577', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_578', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_579', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_580', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_581', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_582', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_583', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_584', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_585', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_586', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_587', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_588', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_589', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_590', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_591', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_592', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_593', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_594', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_595', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_596', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_597', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_598', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_599', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_600', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_601', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_602', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_603', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_604', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_605', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_606', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_607', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_608', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_609', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_610', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_611', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_612', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_613', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_614', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_615', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_616', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_617', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_618', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_619', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_620', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_621', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_622', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_623', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_624', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_625', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_626', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_627', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_628', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_629', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_630', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_631', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_632', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_633', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_634', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_635', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_636', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_637', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_638', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_639', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_640', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_641', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_642', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_643', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_644', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_645', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_646', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_647', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_648', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_649', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_650', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_651', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_652', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_653', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_654', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_655', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_656', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_657', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_658', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_659', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_660', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_661', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_662', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_663', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_664', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_665', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_666', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_667', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_668', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_669', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_670', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_671', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_672', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_673', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_674', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_675', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_676', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_677', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_678', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_679', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_680', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_681', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_682', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_683', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_684', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_685', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_686', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_687', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_688', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_689', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_690', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_691', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_692', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_693', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_694', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_695', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_696', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_697', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_698', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_699', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_700', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_701', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_702', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_703', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_704', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_705', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_706', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_707', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_708', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_709', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_710', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_711', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_712', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_713', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_714', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_715', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_716', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_717', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_718', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_719', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_720', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_721', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_722', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_723', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_724', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_725', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_726', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_727', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_728', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_729', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_730', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_731', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_732', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_733', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_734', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_735', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_736', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_737', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_738', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_739', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_740', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_741', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_742', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_743', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_744', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_745', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_746', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_747', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_748', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_749', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_750', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_751', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_752', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_753', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_754', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_755', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_756', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_757', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_758', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_759', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_760', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_761', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_762', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_763', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_764', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_765', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_766', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_767', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_768', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_769', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_770', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_771', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_772', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_773', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_774', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_775', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_776', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_777', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_778', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_779', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_780', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_781', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_782', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_783', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_784', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_785', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_786', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_787', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_788', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_789', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_790', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_791', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_792', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_793', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_794', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_795', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_796', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_797', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_798', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_799', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_800', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_801', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_802', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_803', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_804', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_805', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_806', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_807', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_808', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_809', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_810', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_811', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_812', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_813', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_814', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_815', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_816', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_817', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_818', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_819', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_820', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_821', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_822', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_823', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_824', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_825', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_826', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_827', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_828', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_829', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_830', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_831', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_832', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_833', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_834', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_835', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_836', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_837', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_838', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_839', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_840', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_841', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_842', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_843', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_844', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_845', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_846', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_847', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_848', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_849', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_850', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_851', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_852', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_853', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_854', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_855', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_856', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_857', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_858', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_859', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_860', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_861', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_862', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_863', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_864', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_865', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_866', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_867', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_868', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_869', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_870', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_871', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_872', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_873', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_874', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_875', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_876', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_877', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_878', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_879', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_880', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_881', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_882', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_883', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_884', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_885', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_886', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_887', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_888', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_889', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_890', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_891', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_892', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_893', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_894', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_895', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_896', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_897', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_898', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_899', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_900', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_901', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_902', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_903', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_904', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_905', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_906', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_907', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_908', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_909', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_910', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_911', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_912', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_913', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_914', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_915', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_916', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_917', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_918', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_919', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_920', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_921', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_922', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_923', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_924', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_925', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_926', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_927', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_928', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_929', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_930', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_931', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_932', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_933', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_934', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_935', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_936', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_937', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_938', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_939', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_940', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_941', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_942', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_943', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_944', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_945', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_946', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_947', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_948', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_949', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_950', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_951', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_952', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_953', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_954', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_955', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_956', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_957', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_958', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_959', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_960', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_961', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_962', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_963', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_964', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_965', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_966', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_967', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_968', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_969', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_970', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_971', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_972', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_973', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_974', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_975', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_976', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_977', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_978', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_979', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_980', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_981', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_982', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_983', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_984', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_985', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_986', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_987', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_988', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_989', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_990', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_991', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_992', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_993', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_994', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_995', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_996', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_997', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_998', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_999', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " ...],\n", + " 'features_path': 'paper.parquet',\n", + " : [{: 'kde',\n", + " : ['w_0',\n", + " 'w_1',\n", + " 'w_2',\n", + " 'w_3',\n", + " 'w_4',\n", + " 'w_5',\n", + " 'w_6',\n", + " 'w_7',\n", + " 'w_8',\n", + " 'w_9',\n", + " 'w_10',\n", + " 'w_11',\n", + " 'w_12',\n", + " 'w_13',\n", + " 'w_14',\n", + " 'w_15',\n", + " 'w_16',\n", + " 'w_17',\n", + " 'w_18',\n", + " 'w_19',\n", + " 'w_20',\n", + " 'w_21',\n", + " 'w_22',\n", + " 'w_23',\n", + " 'w_24',\n", + " 'w_25',\n", + " 'w_26',\n", + " 'w_27',\n", + " 'w_28',\n", + " 'w_29',\n", + " 'w_30',\n", + " 'w_31',\n", + " 'w_32',\n", + " 'w_33',\n", + " 'w_34',\n", + " 'w_35',\n", + " 'w_36',\n", + " 'w_37',\n", + " 'w_38',\n", + " 'w_39',\n", + " 'w_40',\n", + " 'w_41',\n", + " 'w_42',\n", + " 'w_43',\n", + " 'w_44',\n", + " 'w_45',\n", + " 'w_46',\n", + " 'w_47',\n", + " 'w_48',\n", + " 'w_49',\n", + " 'w_50',\n", + " 'w_51',\n", + " 'w_52',\n", + " 'w_53',\n", + " 'w_54',\n", + " 'w_55',\n", + " 'w_56',\n", + " 'w_57',\n", + " 'w_58',\n", + " 'w_59',\n", + " 'w_60',\n", + " 'w_61',\n", + " 'w_62',\n", + " 'w_63',\n", + " 'w_64',\n", + " 'w_65',\n", + " 'w_66',\n", + " 'w_67',\n", + " 'w_68',\n", + " 'w_69',\n", + " 'w_70',\n", + " 'w_71',\n", + " 'w_72',\n", + " 'w_73',\n", + " 'w_74',\n", + " 'w_75',\n", + " 'w_76',\n", + " 'w_77',\n", + " 'w_78',\n", + " 'w_79',\n", + " 'w_80',\n", + " 'w_81',\n", + " 'w_82',\n", + " 'w_83',\n", + " 'w_84',\n", + " 'w_85',\n", + " 'w_86',\n", + " 'w_87',\n", + " 'w_88',\n", + " 'w_89',\n", + " 'w_90',\n", + " 'w_91',\n", + " 'w_92',\n", + " 'w_93',\n", + " 'w_94',\n", + " 'w_95',\n", + " 'w_96',\n", + " 'w_97',\n", + " 'w_98',\n", + " 'w_99',\n", + " 'w_100',\n", + " 'w_101',\n", + " 'w_102',\n", + " 'w_103',\n", + " 'w_104',\n", + " 'w_105',\n", + " 'w_106',\n", + " 'w_107',\n", + " 'w_108',\n", + " 'w_109',\n", + " 'w_110',\n", + " 'w_111',\n", + " 'w_112',\n", + " 'w_113',\n", + " 'w_114',\n", + " 'w_115',\n", + " 'w_116',\n", + " 'w_117',\n", + " 'w_118',\n", + " 'w_119',\n", + " 'w_120',\n", + " 'w_121',\n", + " 'w_122',\n", + " 'w_123',\n", + " 'w_124',\n", + " 'w_125',\n", + " 'w_126',\n", + " 'w_127',\n", + " 'w_128',\n", + " 'w_129',\n", + " 'w_130',\n", + " 'w_131',\n", + " 'w_132',\n", + " 'w_133',\n", + " 'w_134',\n", + " 'w_135',\n", + " 'w_136',\n", + " 'w_137',\n", + " 'w_138',\n", + " 'w_139',\n", + " 'w_140',\n", + " 'w_141',\n", + " 'w_142',\n", + " 'w_143',\n", + " 'w_144',\n", + " 'w_145',\n", + " 'w_146',\n", + " 'w_147',\n", + " 'w_148',\n", + " 'w_149',\n", + " 'w_150',\n", + " 'w_151',\n", + " 'w_152',\n", + " 'w_153',\n", + " 'w_154',\n", + " 'w_155',\n", + " 'w_156',\n", + " 'w_157',\n", + " 'w_158',\n", + " 'w_159',\n", + " 'w_160',\n", + " 'w_161',\n", + " 'w_162',\n", + " 'w_163',\n", + " 'w_164',\n", + " 'w_165',\n", + " 'w_166',\n", + " 'w_167',\n", + " 'w_168',\n", + " 'w_169',\n", + " 'w_170',\n", + " 'w_171',\n", + " 'w_172',\n", + " 'w_173',\n", + " 'w_174',\n", + " 'w_175',\n", + " 'w_176',\n", + " 'w_177',\n", + " 'w_178',\n", + " 'w_179',\n", + " 'w_180',\n", + " 'w_181',\n", + " 'w_182',\n", + " 'w_183',\n", + " 'w_184',\n", + " 'w_185',\n", + " 'w_186',\n", + " 'w_187',\n", + " 'w_188',\n", + " 'w_189',\n", + " 'w_190',\n", + " 'w_191',\n", + " 'w_192',\n", + " 'w_193',\n", + " 'w_194',\n", + " 'w_195',\n", + " 'w_196',\n", + " 'w_197',\n", + " 'w_198',\n", + " 'w_199',\n", + " 'w_200',\n", + " 'w_201',\n", + " 'w_202',\n", + " 'w_203',\n", + " 'w_204',\n", + " 'w_205',\n", + " 'w_206',\n", + " 'w_207',\n", + " 'w_208',\n", + " 'w_209',\n", + " 'w_210',\n", + " 'w_211',\n", + " 'w_212',\n", + " 'w_213',\n", + " 'w_214',\n", + " 'w_215',\n", + " 'w_216',\n", + " 'w_217',\n", + " 'w_218',\n", + " 'w_219',\n", + " 'w_220',\n", + " 'w_221',\n", + " 'w_222',\n", + " 'w_223',\n", + " 'w_224',\n", + " 'w_225',\n", + " 'w_226',\n", + " 'w_227',\n", + " 'w_228',\n", + " 'w_229',\n", + " 'w_230',\n", + " 'w_231',\n", + " 'w_232',\n", + " 'w_233',\n", + " 'w_234',\n", + " 'w_235',\n", + " 'w_236',\n", + " 'w_237',\n", + " 'w_238',\n", + " 'w_239',\n", + " 'w_240',\n", + " 'w_241',\n", + " 'w_242',\n", + " 'w_243',\n", + " 'w_244',\n", + " 'w_245',\n", + " 'w_246',\n", + " 'w_247',\n", + " 'w_248',\n", + " 'w_249',\n", + " 'w_250',\n", + " 'w_251',\n", + " 'w_252',\n", + " 'w_253',\n", + " 'w_254',\n", + " 'w_255',\n", + " 'w_256',\n", + " 'w_257',\n", + " 'w_258',\n", + " 'w_259',\n", + " 'w_260',\n", + " 'w_261',\n", + " 'w_262',\n", + " 'w_263',\n", + " 'w_264',\n", + " 'w_265',\n", + " 'w_266',\n", + " 'w_267',\n", + " 'w_268',\n", + " 'w_269',\n", + " 'w_270',\n", + " 'w_271',\n", + " 'w_272',\n", + " 'w_273',\n", + " 'w_274',\n", + " 'w_275',\n", + " 'w_276',\n", + " 'w_277',\n", + " 'w_278',\n", + " 'w_279',\n", + " 'w_280',\n", + " 'w_281',\n", + " 'w_282',\n", + " 'w_283',\n", + " 'w_284',\n", + " 'w_285',\n", + " 'w_286',\n", + " 'w_287',\n", + " 'w_288',\n", + " 'w_289',\n", + " 'w_290',\n", + " 'w_291',\n", + " 'w_292',\n", + " 'w_293',\n", + " 'w_294',\n", + " 'w_295',\n", + " 'w_296',\n", + " 'w_297',\n", + " 'w_298',\n", + " 'w_299',\n", + " 'w_300',\n", + " 'w_301',\n", + " 'w_302',\n", + " 'w_303',\n", + " 'w_304',\n", + " 'w_305',\n", + " 'w_306',\n", + " 'w_307',\n", + " 'w_308',\n", + " 'w_309',\n", + " 'w_310',\n", + " 'w_311',\n", + " 'w_312',\n", + " 'w_313',\n", + " 'w_314',\n", + " 'w_315',\n", + " 'w_316',\n", + " 'w_317',\n", + " 'w_318',\n", + " 'w_319',\n", + " 'w_320',\n", + " 'w_321',\n", + " 'w_322',\n", + " 'w_323',\n", + " 'w_324',\n", + " 'w_325',\n", + " 'w_326',\n", + " 'w_327',\n", + " 'w_328',\n", + " 'w_329',\n", + " 'w_330',\n", + " 'w_331',\n", + " 'w_332',\n", + " 'w_333',\n", + " 'w_334',\n", + " 'w_335',\n", + " 'w_336',\n", + " 'w_337',\n", + " 'w_338',\n", + " 'w_339',\n", + " 'w_340',\n", + " 'w_341',\n", + " 'w_342',\n", + " 'w_343',\n", + " 'w_344',\n", + " 'w_345',\n", + " 'w_346',\n", + " 'w_347',\n", + " 'w_348',\n", + " 'w_349',\n", + " 'w_350',\n", + " 'w_351',\n", + " 'w_352',\n", + " 'w_353',\n", + " 'w_354',\n", + " 'w_355',\n", + " 'w_356',\n", + " 'w_357',\n", + " 'w_358',\n", + " 'w_359',\n", + " 'w_360',\n", + " 'w_361',\n", + " 'w_362',\n", + " 'w_363',\n", + " 'w_364',\n", + " 'w_365',\n", + " 'w_366',\n", + " 'w_367',\n", + " 'w_368',\n", + " 'w_369',\n", + " 'w_370',\n", + " 'w_371',\n", + " 'w_372',\n", + " 'w_373',\n", + " 'w_374',\n", + " 'w_375',\n", + " 'w_376',\n", + " 'w_377',\n", + " 'w_378',\n", + " 'w_379',\n", + " 'w_380',\n", + " 'w_381',\n", + " 'w_382',\n", + " 'w_383',\n", + " 'w_384',\n", + " 'w_385',\n", + " 'w_386',\n", + " 'w_387',\n", + " 'w_388',\n", + " 'w_389',\n", + " 'w_390',\n", + " 'w_391',\n", + " 'w_392',\n", + " 'w_393',\n", + " 'w_394',\n", + " 'w_395',\n", + " 'w_396',\n", + " 'w_397',\n", + " 'w_398',\n", + " 'w_399',\n", + " 'w_400',\n", + " 'w_401',\n", + " 'w_402',\n", + " 'w_403',\n", + " 'w_404',\n", + " 'w_405',\n", + " 'w_406',\n", + " 'w_407',\n", + " 'w_408',\n", + " 'w_409',\n", + " 'w_410',\n", + " 'w_411',\n", + " 'w_412',\n", + " 'w_413',\n", + " 'w_414',\n", + " 'w_415',\n", + " 'w_416',\n", + " 'w_417',\n", + " 'w_418',\n", + " 'w_419',\n", + " 'w_420',\n", + " 'w_421',\n", + " 'w_422',\n", + " 'w_423',\n", + " 'w_424',\n", + " 'w_425',\n", + " 'w_426',\n", + " 'w_427',\n", + " 'w_428',\n", + " 'w_429',\n", + " 'w_430',\n", + " 'w_431',\n", + " 'w_432',\n", + " 'w_433',\n", + " 'w_434',\n", + " 'w_435',\n", + " 'w_436',\n", + " 'w_437',\n", + " 'w_438',\n", + " 'w_439',\n", + " 'w_440',\n", + " 'w_441',\n", + " 'w_442',\n", + " 'w_443',\n", + " 'w_444',\n", + " 'w_445',\n", + " 'w_446',\n", + " 'w_447',\n", + " 'w_448',\n", + " 'w_449',\n", + " 'w_450',\n", + " 'w_451',\n", + " 'w_452',\n", + " 'w_453',\n", + " 'w_454',\n", + " 'w_455',\n", + " 'w_456',\n", + " 'w_457',\n", + " 'w_458',\n", + " 'w_459',\n", + " 'w_460',\n", + " 'w_461',\n", + " 'w_462',\n", + " 'w_463',\n", + " 'w_464',\n", + " 'w_465',\n", + " 'w_466',\n", + " 'w_467',\n", + " 'w_468',\n", + " 'w_469',\n", + " 'w_470',\n", + " 'w_471',\n", + " 'w_472',\n", + " 'w_473',\n", + " 'w_474',\n", + " 'w_475',\n", + " 'w_476',\n", + " 'w_477',\n", + " 'w_478',\n", + " 'w_479',\n", + " 'w_480',\n", + " 'w_481',\n", + " 'w_482',\n", + " 'w_483',\n", + " 'w_484',\n", + " 'w_485',\n", + " 'w_486',\n", + " 'w_487',\n", + " 'w_488',\n", + " 'w_489',\n", + " 'w_490',\n", + " 'w_491',\n", + " 'w_492',\n", + " 'w_493',\n", + " 'w_494',\n", + " 'w_495',\n", + " 'w_496',\n", + " 'w_497',\n", + " 'w_498',\n", + " 'w_499',\n", + " 'w_500',\n", + " 'w_501',\n", + " 'w_502',\n", + " 'w_503',\n", + " 'w_504',\n", + " 'w_505',\n", + " 'w_506',\n", + " 'w_507',\n", + " 'w_508',\n", + " 'w_509',\n", + " 'w_510',\n", + " 'w_511',\n", + " 'w_512',\n", + " 'w_513',\n", + " 'w_514',\n", + " 'w_515',\n", + " 'w_516',\n", + " 'w_517',\n", + " 'w_518',\n", + " 'w_519',\n", + " 'w_520',\n", + " 'w_521',\n", + " 'w_522',\n", + " 'w_523',\n", + " 'w_524',\n", + " 'w_525',\n", + " 'w_526',\n", + " 'w_527',\n", + " 'w_528',\n", + " 'w_529',\n", + " 'w_530',\n", + " 'w_531',\n", + " 'w_532',\n", + " 'w_533',\n", + " 'w_534',\n", + " 'w_535',\n", + " 'w_536',\n", + " 'w_537',\n", + " 'w_538',\n", + " 'w_539',\n", + " 'w_540',\n", + " 'w_541',\n", + " 'w_542',\n", + " 'w_543',\n", + " 'w_544',\n", + " 'w_545',\n", + " 'w_546',\n", + " 'w_547',\n", + " 'w_548',\n", + " 'w_549',\n", + " 'w_550',\n", + " 'w_551',\n", + " 'w_552',\n", + " 'w_553',\n", + " 'w_554',\n", + " 'w_555',\n", + " 'w_556',\n", + " 'w_557',\n", + " 'w_558',\n", + " 'w_559',\n", + " 'w_560',\n", + " 'w_561',\n", + " 'w_562',\n", + " 'w_563',\n", + " 'w_564',\n", + " 'w_565',\n", + " 'w_566',\n", + " 'w_567',\n", + " 'w_568',\n", + " 'w_569',\n", + " 'w_570',\n", + " 'w_571',\n", + " 'w_572',\n", + " 'w_573',\n", + " 'w_574',\n", + " 'w_575',\n", + " 'w_576',\n", + " 'w_577',\n", + " 'w_578',\n", + " 'w_579',\n", + " 'w_580',\n", + " 'w_581',\n", + " 'w_582',\n", + " 'w_583',\n", + " 'w_584',\n", + " 'w_585',\n", + " 'w_586',\n", + " 'w_587',\n", + " 'w_588',\n", + " 'w_589',\n", + " 'w_590',\n", + " 'w_591',\n", + " 'w_592',\n", + " 'w_593',\n", + " 'w_594',\n", + " 'w_595',\n", + " 'w_596',\n", + " 'w_597',\n", + " 'w_598',\n", + " 'w_599',\n", + " 'w_600',\n", + " 'w_601',\n", + " 'w_602',\n", + " 'w_603',\n", + " 'w_604',\n", + " 'w_605',\n", + " 'w_606',\n", + " 'w_607',\n", + " 'w_608',\n", + " 'w_609',\n", + " 'w_610',\n", + " 'w_611',\n", + " 'w_612',\n", + " 'w_613',\n", + " 'w_614',\n", + " 'w_615',\n", + " 'w_616',\n", + " 'w_617',\n", + " 'w_618',\n", + " 'w_619',\n", + " 'w_620',\n", + " 'w_621',\n", + " 'w_622',\n", + " 'w_623',\n", + " 'w_624',\n", + " 'w_625',\n", + " 'w_626',\n", + " 'w_627',\n", + " 'w_628',\n", + " 'w_629',\n", + " 'w_630',\n", + " 'w_631',\n", + " 'w_632',\n", + " 'w_633',\n", + " 'w_634',\n", + " 'w_635',\n", + " 'w_636',\n", + " 'w_637',\n", + " 'w_638',\n", + " 'w_639',\n", + " 'w_640',\n", + " 'w_641',\n", + " 'w_642',\n", + " 'w_643',\n", + " 'w_644',\n", + " 'w_645',\n", + " 'w_646',\n", + " 'w_647',\n", + " 'w_648',\n", + " 'w_649',\n", + " 'w_650',\n", + " 'w_651',\n", + " 'w_652',\n", + " 'w_653',\n", + " 'w_654',\n", + " 'w_655',\n", + " 'w_656',\n", + " 'w_657',\n", + " 'w_658',\n", + " 'w_659',\n", + " 'w_660',\n", + " 'w_661',\n", + " 'w_662',\n", + " 'w_663',\n", + " 'w_664',\n", + " 'w_665',\n", + " 'w_666',\n", + " 'w_667',\n", + " 'w_668',\n", + " 'w_669',\n", + " 'w_670',\n", + " 'w_671',\n", + " 'w_672',\n", + " 'w_673',\n", + " 'w_674',\n", + " 'w_675',\n", + " 'w_676',\n", + " 'w_677',\n", + " 'w_678',\n", + " 'w_679',\n", + " 'w_680',\n", + " 'w_681',\n", + " 'w_682',\n", + " 'w_683',\n", + " 'w_684',\n", + " 'w_685',\n", + " 'w_686',\n", + " 'w_687',\n", + " 'w_688',\n", + " 'w_689',\n", + " 'w_690',\n", + " 'w_691',\n", + " 'w_692',\n", + " 'w_693',\n", + " 'w_694',\n", + " 'w_695',\n", + " 'w_696',\n", + " 'w_697',\n", + " 'w_698',\n", + " 'w_699',\n", + " 'w_700',\n", + " 'w_701',\n", + " 'w_702',\n", + " 'w_703',\n", + " 'w_704',\n", + " 'w_705',\n", + " 'w_706',\n", + " 'w_707',\n", + " 'w_708',\n", + " 'w_709',\n", + " 'w_710',\n", + " 'w_711',\n", + " 'w_712',\n", + " 'w_713',\n", + " 'w_714',\n", + " 'w_715',\n", + " 'w_716',\n", + " 'w_717',\n", + " 'w_718',\n", + " 'w_719',\n", + " 'w_720',\n", + " 'w_721',\n", + " 'w_722',\n", + " 'w_723',\n", + " 'w_724',\n", + " 'w_725',\n", + " 'w_726',\n", + " 'w_727',\n", + " 'w_728',\n", + " 'w_729',\n", + " 'w_730',\n", + " 'w_731',\n", + " 'w_732',\n", + " 'w_733',\n", + " 'w_734',\n", + " 'w_735',\n", + " 'w_736',\n", + " 'w_737',\n", + " 'w_738',\n", + " 'w_739',\n", + " 'w_740',\n", + " 'w_741',\n", + " 'w_742',\n", + " 'w_743',\n", + " 'w_744',\n", + " 'w_745',\n", + " 'w_746',\n", + " 'w_747',\n", + " 'w_748',\n", + " 'w_749',\n", + " 'w_750',\n", + " 'w_751',\n", + " 'w_752',\n", + " 'w_753',\n", + " 'w_754',\n", + " 'w_755',\n", + " 'w_756',\n", + " 'w_757',\n", + " 'w_758',\n", + " 'w_759',\n", + " 'w_760',\n", + " 'w_761',\n", + " 'w_762',\n", + " 'w_763',\n", + " 'w_764',\n", + " 'w_765',\n", + " 'w_766',\n", + " 'w_767',\n", + " 'w_768',\n", + " 'w_769',\n", + " 'w_770',\n", + " 'w_771',\n", + " 'w_772',\n", + " 'w_773',\n", + " 'w_774',\n", + " 'w_775',\n", + " 'w_776',\n", + " 'w_777',\n", + " 'w_778',\n", + " 'w_779',\n", + " 'w_780',\n", + " 'w_781',\n", + " 'w_782',\n", + " 'w_783',\n", + " 'w_784',\n", + " 'w_785',\n", + " 'w_786',\n", + " 'w_787',\n", + " 'w_788',\n", + " 'w_789',\n", + " 'w_790',\n", + " 'w_791',\n", + " 'w_792',\n", + " 'w_793',\n", + " 'w_794',\n", + " 'w_795',\n", + " 'w_796',\n", + " 'w_797',\n", + " 'w_798',\n", + " 'w_799',\n", + " 'w_800',\n", + " 'w_801',\n", + " 'w_802',\n", + " 'w_803',\n", + " 'w_804',\n", + " 'w_805',\n", + " 'w_806',\n", + " 'w_807',\n", + " 'w_808',\n", + " 'w_809',\n", + " 'w_810',\n", + " 'w_811',\n", + " 'w_812',\n", + " 'w_813',\n", + " 'w_814',\n", + " 'w_815',\n", + " 'w_816',\n", + " 'w_817',\n", + " 'w_818',\n", + " 'w_819',\n", + " 'w_820',\n", + " 'w_821',\n", + " 'w_822',\n", + " 'w_823',\n", + " 'w_824',\n", + " 'w_825',\n", + " 'w_826',\n", + " 'w_827',\n", + " 'w_828',\n", + " 'w_829',\n", + " 'w_830',\n", + " 'w_831',\n", + " 'w_832',\n", + " 'w_833',\n", + " 'w_834',\n", + " 'w_835',\n", + " 'w_836',\n", + " 'w_837',\n", + " 'w_838',\n", + " 'w_839',\n", + " 'w_840',\n", + " 'w_841',\n", + " 'w_842',\n", + " 'w_843',\n", + " 'w_844',\n", + " 'w_845',\n", + " 'w_846',\n", + " 'w_847',\n", + " 'w_848',\n", + " 'w_849',\n", + " 'w_850',\n", + " 'w_851',\n", + " 'w_852',\n", + " 'w_853',\n", + " 'w_854',\n", + " 'w_855',\n", + " 'w_856',\n", + " 'w_857',\n", + " 'w_858',\n", + " 'w_859',\n", + " 'w_860',\n", + " 'w_861',\n", + " 'w_862',\n", + " 'w_863',\n", + " 'w_864',\n", + " 'w_865',\n", + " 'w_866',\n", + " 'w_867',\n", + " 'w_868',\n", + " 'w_869',\n", + " 'w_870',\n", + " 'w_871',\n", + " 'w_872',\n", + " 'w_873',\n", + " 'w_874',\n", + " 'w_875',\n", + " 'w_876',\n", + " 'w_877',\n", + " 'w_878',\n", + " 'w_879',\n", + " 'w_880',\n", + " 'w_881',\n", + " 'w_882',\n", + " 'w_883',\n", + " 'w_884',\n", + " 'w_885',\n", + " 'w_886',\n", + " 'w_887',\n", + " 'w_888',\n", + " 'w_889',\n", + " 'w_890',\n", + " 'w_891',\n", + " 'w_892',\n", + " 'w_893',\n", + " 'w_894',\n", + " 'w_895',\n", + " 'w_896',\n", + " 'w_897',\n", + " 'w_898',\n", + " 'w_899',\n", + " 'w_900',\n", + " 'w_901',\n", + " 'w_902',\n", + " 'w_903',\n", + " 'w_904',\n", + " 'w_905',\n", + " 'w_906',\n", + " 'w_907',\n", + " 'w_908',\n", + " 'w_909',\n", + " 'w_910',\n", + " 'w_911',\n", + " 'w_912',\n", + " 'w_913',\n", + " 'w_914',\n", + " 'w_915',\n", + " 'w_916',\n", + " 'w_917',\n", + " 'w_918',\n", + " 'w_919',\n", + " 'w_920',\n", + " 'w_921',\n", + " 'w_922',\n", + " 'w_923',\n", + " 'w_924',\n", + " 'w_925',\n", + " 'w_926',\n", + " 'w_927',\n", + " 'w_928',\n", + " 'w_929',\n", + " 'w_930',\n", + " 'w_931',\n", + " 'w_932',\n", + " 'w_933',\n", + " 'w_934',\n", + " 'w_935',\n", + " 'w_936',\n", + " 'w_937',\n", + " 'w_938',\n", + " 'w_939',\n", + " 'w_940',\n", + " 'w_941',\n", + " 'w_942',\n", + " 'w_943',\n", + " 'w_944',\n", + " 'w_945',\n", + " 'w_946',\n", + " 'w_947',\n", + " 'w_948',\n", + " 'w_949',\n", + " 'w_950',\n", + " 'w_951',\n", + " 'w_952',\n", + " 'w_953',\n", + " 'w_954',\n", + " 'w_955',\n", + " 'w_956',\n", + " 'w_957',\n", + " 'w_958',\n", + " 'w_959',\n", + " 'w_960',\n", + " 'w_961',\n", + " 'w_962',\n", + " 'w_963',\n", + " 'w_964',\n", + " 'w_965',\n", + " 'w_966',\n", + " 'w_967',\n", + " 'w_968',\n", + " 'w_969',\n", + " 'w_970',\n", + " 'w_971',\n", + " 'w_972',\n", + " 'w_973',\n", + " 'w_974',\n", + " 'w_975',\n", + " 'w_976',\n", + " 'w_977',\n", + " 'w_978',\n", + " 'w_979',\n", + " 'w_980',\n", + " 'w_981',\n", + " 'w_982',\n", + " 'w_983',\n", + " 'w_984',\n", + " 'w_985',\n", + " 'w_986',\n", + " 'w_987',\n", + " 'w_988',\n", + " 'w_989',\n", + " 'w_990',\n", + " 'w_991',\n", + " 'w_992',\n", + " 'w_993',\n", + " 'w_994',\n", + " 'w_995',\n", + " 'w_996',\n", + " 'w_997',\n", + " 'w_998',\n", + " 'w_999',\n", + " ...],\n", + " : {: 'configuration',\n", + " : '/workspace/data/cora_preprocessed',\n", + " : 'paper'},\n", + " : {}}]}],\n", + " : [{: 'xgboost',\n", + " : ['cite'],\n", + " : {'paper': ['label']},\n", + " : {},\n", + " : {}}]}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config_proper" + ] + }, + { + "cell_type": "markdown", + "id": "7059b02e", + "metadata": {}, + "source": [ + "### Random " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "72ae8a2f", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_random = feature_spec_original.copy() \n", + "\n", + "feature_spec_random[MetaData.NODES][0][MetaData.TABULAR_GENERATORS] = [\n", + " {\n", + " MetaData.TYPE: \"random\",\n", + " MetaData.FEATURES_LIST: -1, # copies all tabular features\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'random',\n", + " },\n", + " MetaData.PARAMS: {\n", + " }\n", + " }\n", + "]\n", + "\n", + "feature_spec_random[MetaData.EDGES][0][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'rnd', # the save as 'random' \n", + " },\n", + " MetaData.PARAMS: {\n", + " \"has_self_loop\": False,\n", + " }\n", + "}\n", + "\n", + "config_random = SynGenConfiguration(feature_spec_random)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "fb4b8747", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'cite',\n", + " 'count': 5428,\n", + " 'src_node_type': 'paper',\n", + " 'dst_node_type': 'paper',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'cite_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {'has_self_loop': False}}}],\n", + " : [{'name': 'paper',\n", + " 'count': 2708,\n", + " 'features': [{'name': 'w_0',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'},\n", + " {'name': 'w_1', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_2', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_3', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_4', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_5', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_6', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_7', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_8', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_9', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_10', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_11', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_12', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_13', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_14', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_15', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_16', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_17', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_18', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_19', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_20', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_21', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_22', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_23', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_24', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_25', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_26', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_27', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_28', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_29', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_30', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_31', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_32', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_33', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_34', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_35', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_36', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_37', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_38', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_39', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_40', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_41', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_42', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_43', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_44', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_45', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_46', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_47', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_48', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_49', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_50', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_51', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_52', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_53', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_54', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_55', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_56', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_57', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_58', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_59', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_60', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_61', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_62', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_63', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_64', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_65', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_66', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_67', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_68', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_69', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_70', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_71', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_72', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_73', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_74', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_75', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_76', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_77', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_78', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_79', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_80', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_81', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_82', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_83', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_84', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_85', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_86', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_87', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_88', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_89', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_90', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_91', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_92', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_93', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_94', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_95', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_96', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_97', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_98', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_99', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_100', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_101', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_102', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_103', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_104', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_105', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_106', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_107', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_108', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_109', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_110', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_111', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_112', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_113', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_114', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_115', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_116', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_117', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_118', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_119', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_120', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_121', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_122', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_123', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_124', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_125', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_126', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_127', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_128', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_129', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_130', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_131', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_132', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_133', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_134', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_135', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_136', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_137', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_138', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_139', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_140', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_141', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_142', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_143', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_144', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_145', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_146', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_147', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_148', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_149', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_150', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_151', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_152', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_153', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_154', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_155', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_156', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_157', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_158', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_159', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_160', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_161', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_162', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_163', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_164', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_165', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_166', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_167', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_168', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_169', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_170', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_171', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_172', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_173', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_174', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_175', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_176', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_177', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_178', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_179', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_180', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_181', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_182', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_183', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_184', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_185', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_186', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_187', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_188', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_189', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_190', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_191', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_192', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_193', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_194', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_195', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_196', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_197', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_198', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_199', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_200', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_201', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_202', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_203', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_204', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_205', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_206', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_207', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_208', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_209', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_210', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_211', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_212', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_213', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_214', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_215', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_216', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_217', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_218', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_219', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_220', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_221', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_222', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_223', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_224', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_225', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_226', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_227', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_228', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_229', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_230', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_231', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_232', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_233', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_234', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_235', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_236', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_237', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_238', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_239', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_240', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_241', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_242', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_243', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_244', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_245', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_246', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_247', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_248', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_249', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_250', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_251', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_252', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_253', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_254', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_255', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_256', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_257', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_258', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_259', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_260', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_261', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_262', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_263', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_264', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_265', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_266', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_267', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_268', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_269', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_270', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_271', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_272', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_273', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_274', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_275', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_276', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_277', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_278', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_279', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_280', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_281', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_282', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_283', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_284', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_285', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_286', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_287', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_288', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_289', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_290', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_291', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_292', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_293', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_294', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_295', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_296', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_297', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_298', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_299', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_300', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_301', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_302', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_303', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_304', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_305', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_306', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_307', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_308', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_309', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_310', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_311', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_312', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_313', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_314', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_315', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_316', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_317', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_318', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_319', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_320', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_321', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_322', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_323', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_324', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_325', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_326', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_327', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_328', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_329', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_330', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_331', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_332', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_333', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_334', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_335', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_336', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_337', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_338', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_339', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_340', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_341', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_342', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_343', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_344', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_345', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_346', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_347', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_348', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_349', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_350', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_351', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_352', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_353', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_354', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_355', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_356', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_357', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_358', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_359', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_360', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_361', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_362', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_363', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_364', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_365', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_366', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_367', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_368', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_369', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_370', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_371', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_372', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_373', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_374', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_375', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_376', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_377', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_378', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_379', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_380', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_381', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_382', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_383', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_384', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_385', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_386', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_387', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_388', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_389', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_390', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_391', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_392', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_393', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_394', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_395', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_396', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_397', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_398', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_399', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_400', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_401', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_402', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_403', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_404', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_405', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_406', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_407', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_408', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_409', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_410', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_411', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_412', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_413', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_414', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_415', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_416', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_417', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_418', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_419', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_420', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_421', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_422', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_423', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_424', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_425', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_426', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_427', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_428', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_429', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_430', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_431', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_432', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_433', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_434', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_435', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_436', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_437', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_438', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_439', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_440', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_441', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_442', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_443', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_444', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_445', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_446', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_447', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_448', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_449', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_450', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_451', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_452', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_453', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_454', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_455', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_456', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_457', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_458', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_459', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_460', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_461', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_462', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_463', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_464', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_465', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_466', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_467', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_468', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_469', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_470', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_471', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_472', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_473', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_474', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_475', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_476', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_477', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_478', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_479', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_480', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_481', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_482', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_483', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_484', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_485', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_486', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_487', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_488', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_489', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_490', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_491', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_492', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_493', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_494', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_495', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_496', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_497', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_498', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_499', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_500', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_501', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_502', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_503', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_504', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_505', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_506', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_507', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_508', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_509', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_510', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_511', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_512', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_513', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_514', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_515', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_516', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_517', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_518', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_519', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_520', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_521', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_522', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_523', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_524', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_525', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_526', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_527', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_528', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_529', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_530', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_531', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_532', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_533', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_534', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_535', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_536', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_537', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_538', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_539', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_540', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_541', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_542', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_543', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_544', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_545', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_546', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_547', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_548', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_549', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_550', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_551', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_552', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_553', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_554', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_555', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_556', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_557', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_558', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_559', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_560', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_561', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_562', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_563', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_564', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_565', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_566', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_567', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_568', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_569', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_570', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_571', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_572', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_573', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_574', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_575', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_576', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_577', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_578', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_579', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_580', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_581', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_582', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_583', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_584', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_585', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_586', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_587', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_588', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_589', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_590', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_591', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_592', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_593', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_594', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_595', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_596', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_597', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_598', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_599', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_600', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_601', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_602', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_603', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_604', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_605', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_606', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_607', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_608', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_609', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_610', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_611', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_612', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_613', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_614', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_615', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_616', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_617', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_618', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_619', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_620', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_621', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_622', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_623', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_624', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_625', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_626', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_627', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_628', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_629', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_630', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_631', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_632', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_633', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_634', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_635', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_636', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_637', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_638', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_639', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_640', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_641', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_642', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_643', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_644', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_645', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_646', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_647', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_648', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_649', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_650', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_651', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_652', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_653', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_654', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_655', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_656', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_657', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_658', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_659', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_660', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_661', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_662', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_663', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_664', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_665', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_666', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_667', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_668', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_669', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_670', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_671', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_672', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_673', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_674', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_675', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_676', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_677', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_678', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_679', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_680', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_681', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_682', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_683', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_684', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_685', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_686', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_687', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_688', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_689', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_690', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_691', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_692', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_693', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_694', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_695', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_696', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_697', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_698', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_699', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_700', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_701', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_702', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_703', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_704', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_705', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_706', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_707', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_708', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_709', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_710', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_711', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_712', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_713', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_714', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_715', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_716', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_717', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_718', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_719', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_720', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_721', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_722', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_723', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_724', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_725', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_726', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_727', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_728', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_729', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_730', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_731', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_732', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_733', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_734', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_735', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_736', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_737', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_738', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_739', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_740', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_741', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_742', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_743', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_744', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_745', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_746', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_747', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_748', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_749', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_750', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_751', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_752', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_753', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_754', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_755', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_756', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_757', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_758', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_759', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_760', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_761', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_762', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_763', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_764', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_765', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_766', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_767', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_768', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_769', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_770', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_771', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_772', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_773', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_774', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_775', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_776', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_777', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_778', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_779', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_780', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_781', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_782', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_783', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_784', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_785', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_786', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_787', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_788', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_789', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_790', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_791', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_792', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_793', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_794', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_795', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_796', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_797', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_798', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_799', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_800', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_801', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_802', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_803', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_804', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_805', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_806', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_807', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_808', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_809', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_810', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_811', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_812', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_813', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_814', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_815', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_816', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_817', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_818', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_819', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_820', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_821', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_822', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_823', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_824', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_825', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_826', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_827', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_828', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_829', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_830', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_831', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_832', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_833', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_834', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_835', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_836', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_837', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_838', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_839', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_840', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_841', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_842', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_843', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_844', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_845', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_846', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_847', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_848', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_849', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_850', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_851', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_852', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_853', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_854', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_855', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_856', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_857', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_858', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_859', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_860', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_861', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_862', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_863', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_864', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_865', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_866', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_867', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_868', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_869', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_870', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_871', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_872', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_873', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_874', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_875', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_876', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_877', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_878', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_879', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_880', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_881', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_882', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_883', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_884', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_885', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_886', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_887', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_888', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_889', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_890', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_891', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_892', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_893', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_894', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_895', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_896', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_897', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_898', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_899', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_900', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_901', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_902', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_903', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_904', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_905', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_906', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_907', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_908', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_909', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_910', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_911', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_912', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_913', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_914', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_915', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_916', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_917', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_918', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_919', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_920', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_921', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_922', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_923', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_924', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_925', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_926', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_927', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_928', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_929', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_930', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_931', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_932', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_933', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_934', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_935', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_936', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_937', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_938', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_939', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_940', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_941', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_942', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_943', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_944', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_945', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_946', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_947', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_948', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_949', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_950', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_951', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_952', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_953', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_954', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_955', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_956', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_957', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_958', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_959', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_960', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_961', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_962', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_963', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_964', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_965', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_966', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_967', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_968', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_969', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_970', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_971', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_972', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_973', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_974', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_975', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_976', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_977', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_978', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_979', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_980', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_981', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_982', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_983', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_984', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_985', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_986', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_987', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_988', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_989', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_990', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_991', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_992', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_993', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_994', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_995', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_996', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_997', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_998', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_999', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " ...],\n", + " 'features_path': 'paper.parquet',\n", + " : [{: 'random',\n", + " : ['w_0',\n", + " 'w_1',\n", + " 'w_2',\n", + " 'w_3',\n", + " 'w_4',\n", + " 'w_5',\n", + " 'w_6',\n", + " 'w_7',\n", + " 'w_8',\n", + " 'w_9',\n", + " 'w_10',\n", + " 'w_11',\n", + " 'w_12',\n", + " 'w_13',\n", + " 'w_14',\n", + " 'w_15',\n", + " 'w_16',\n", + " 'w_17',\n", + " 'w_18',\n", + " 'w_19',\n", + " 'w_20',\n", + " 'w_21',\n", + " 'w_22',\n", + " 'w_23',\n", + " 'w_24',\n", + " 'w_25',\n", + " 'w_26',\n", + " 'w_27',\n", + " 'w_28',\n", + " 'w_29',\n", + " 'w_30',\n", + " 'w_31',\n", + " 'w_32',\n", + " 'w_33',\n", + " 'w_34',\n", + " 'w_35',\n", + " 'w_36',\n", + " 'w_37',\n", + " 'w_38',\n", + " 'w_39',\n", + " 'w_40',\n", + " 'w_41',\n", + " 'w_42',\n", + " 'w_43',\n", + " 'w_44',\n", + " 'w_45',\n", + " 'w_46',\n", + " 'w_47',\n", + " 'w_48',\n", + " 'w_49',\n", + " 'w_50',\n", + " 'w_51',\n", + " 'w_52',\n", + " 'w_53',\n", + " 'w_54',\n", + " 'w_55',\n", + " 'w_56',\n", + " 'w_57',\n", + " 'w_58',\n", + " 'w_59',\n", + " 'w_60',\n", + " 'w_61',\n", + " 'w_62',\n", + " 'w_63',\n", + " 'w_64',\n", + " 'w_65',\n", + " 'w_66',\n", + " 'w_67',\n", + " 'w_68',\n", + " 'w_69',\n", + " 'w_70',\n", + " 'w_71',\n", + " 'w_72',\n", + " 'w_73',\n", + " 'w_74',\n", + " 'w_75',\n", + " 'w_76',\n", + " 'w_77',\n", + " 'w_78',\n", + " 'w_79',\n", + " 'w_80',\n", + " 'w_81',\n", + " 'w_82',\n", + " 'w_83',\n", + " 'w_84',\n", + " 'w_85',\n", + " 'w_86',\n", + " 'w_87',\n", + " 'w_88',\n", + " 'w_89',\n", + " 'w_90',\n", + " 'w_91',\n", + " 'w_92',\n", + " 'w_93',\n", + " 'w_94',\n", + " 'w_95',\n", + " 'w_96',\n", + " 'w_97',\n", + " 'w_98',\n", + " 'w_99',\n", + " 'w_100',\n", + " 'w_101',\n", + " 'w_102',\n", + " 'w_103',\n", + " 'w_104',\n", + " 'w_105',\n", + " 'w_106',\n", + " 'w_107',\n", + " 'w_108',\n", + " 'w_109',\n", + " 'w_110',\n", + " 'w_111',\n", + " 'w_112',\n", + " 'w_113',\n", + " 'w_114',\n", + " 'w_115',\n", + " 'w_116',\n", + " 'w_117',\n", + " 'w_118',\n", + " 'w_119',\n", + " 'w_120',\n", + " 'w_121',\n", + " 'w_122',\n", + " 'w_123',\n", + " 'w_124',\n", + " 'w_125',\n", + " 'w_126',\n", + " 'w_127',\n", + " 'w_128',\n", + " 'w_129',\n", + " 'w_130',\n", + " 'w_131',\n", + " 'w_132',\n", + " 'w_133',\n", + " 'w_134',\n", + " 'w_135',\n", + " 'w_136',\n", + " 'w_137',\n", + " 'w_138',\n", + " 'w_139',\n", + " 'w_140',\n", + " 'w_141',\n", + " 'w_142',\n", + " 'w_143',\n", + " 'w_144',\n", + " 'w_145',\n", + " 'w_146',\n", + " 'w_147',\n", + " 'w_148',\n", + " 'w_149',\n", + " 'w_150',\n", + " 'w_151',\n", + " 'w_152',\n", + " 'w_153',\n", + " 'w_154',\n", + " 'w_155',\n", + " 'w_156',\n", + " 'w_157',\n", + " 'w_158',\n", + " 'w_159',\n", + " 'w_160',\n", + " 'w_161',\n", + " 'w_162',\n", + " 'w_163',\n", + " 'w_164',\n", + " 'w_165',\n", + " 'w_166',\n", + " 'w_167',\n", + " 'w_168',\n", + " 'w_169',\n", + " 'w_170',\n", + " 'w_171',\n", + " 'w_172',\n", + " 'w_173',\n", + " 'w_174',\n", + " 'w_175',\n", + " 'w_176',\n", + " 'w_177',\n", + " 'w_178',\n", + " 'w_179',\n", + " 'w_180',\n", + " 'w_181',\n", + " 'w_182',\n", + " 'w_183',\n", + " 'w_184',\n", + " 'w_185',\n", + " 'w_186',\n", + " 'w_187',\n", + " 'w_188',\n", + " 'w_189',\n", + " 'w_190',\n", + " 'w_191',\n", + " 'w_192',\n", + " 'w_193',\n", + " 'w_194',\n", + " 'w_195',\n", + " 'w_196',\n", + " 'w_197',\n", + " 'w_198',\n", + " 'w_199',\n", + " 'w_200',\n", + " 'w_201',\n", + " 'w_202',\n", + " 'w_203',\n", + " 'w_204',\n", + " 'w_205',\n", + " 'w_206',\n", + " 'w_207',\n", + " 'w_208',\n", + " 'w_209',\n", + " 'w_210',\n", + " 'w_211',\n", + " 'w_212',\n", + " 'w_213',\n", + " 'w_214',\n", + " 'w_215',\n", + " 'w_216',\n", + " 'w_217',\n", + " 'w_218',\n", + " 'w_219',\n", + " 'w_220',\n", + " 'w_221',\n", + " 'w_222',\n", + " 'w_223',\n", + " 'w_224',\n", + " 'w_225',\n", + " 'w_226',\n", + " 'w_227',\n", + " 'w_228',\n", + " 'w_229',\n", + " 'w_230',\n", + " 'w_231',\n", + " 'w_232',\n", + " 'w_233',\n", + " 'w_234',\n", + " 'w_235',\n", + " 'w_236',\n", + " 'w_237',\n", + " 'w_238',\n", + " 'w_239',\n", + " 'w_240',\n", + " 'w_241',\n", + " 'w_242',\n", + " 'w_243',\n", + " 'w_244',\n", + " 'w_245',\n", + " 'w_246',\n", + " 'w_247',\n", + " 'w_248',\n", + " 'w_249',\n", + " 'w_250',\n", + " 'w_251',\n", + " 'w_252',\n", + " 'w_253',\n", + " 'w_254',\n", + " 'w_255',\n", + " 'w_256',\n", + " 'w_257',\n", + " 'w_258',\n", + " 'w_259',\n", + " 'w_260',\n", + " 'w_261',\n", + " 'w_262',\n", + " 'w_263',\n", + " 'w_264',\n", + " 'w_265',\n", + " 'w_266',\n", + " 'w_267',\n", + " 'w_268',\n", + " 'w_269',\n", + " 'w_270',\n", + " 'w_271',\n", + " 'w_272',\n", + " 'w_273',\n", + " 'w_274',\n", + " 'w_275',\n", + " 'w_276',\n", + " 'w_277',\n", + " 'w_278',\n", + " 'w_279',\n", + " 'w_280',\n", + " 'w_281',\n", + " 'w_282',\n", + " 'w_283',\n", + " 'w_284',\n", + " 'w_285',\n", + " 'w_286',\n", + " 'w_287',\n", + " 'w_288',\n", + " 'w_289',\n", + " 'w_290',\n", + " 'w_291',\n", + " 'w_292',\n", + " 'w_293',\n", + " 'w_294',\n", + " 'w_295',\n", + " 'w_296',\n", + " 'w_297',\n", + " 'w_298',\n", + " 'w_299',\n", + " 'w_300',\n", + " 'w_301',\n", + " 'w_302',\n", + " 'w_303',\n", + " 'w_304',\n", + " 'w_305',\n", + " 'w_306',\n", + " 'w_307',\n", + " 'w_308',\n", + " 'w_309',\n", + " 'w_310',\n", + " 'w_311',\n", + " 'w_312',\n", + " 'w_313',\n", + " 'w_314',\n", + " 'w_315',\n", + " 'w_316',\n", + " 'w_317',\n", + " 'w_318',\n", + " 'w_319',\n", + " 'w_320',\n", + " 'w_321',\n", + " 'w_322',\n", + " 'w_323',\n", + " 'w_324',\n", + " 'w_325',\n", + " 'w_326',\n", + " 'w_327',\n", + " 'w_328',\n", + " 'w_329',\n", + " 'w_330',\n", + " 'w_331',\n", + " 'w_332',\n", + " 'w_333',\n", + " 'w_334',\n", + " 'w_335',\n", + " 'w_336',\n", + " 'w_337',\n", + " 'w_338',\n", + " 'w_339',\n", + " 'w_340',\n", + " 'w_341',\n", + " 'w_342',\n", + " 'w_343',\n", + " 'w_344',\n", + " 'w_345',\n", + " 'w_346',\n", + " 'w_347',\n", + " 'w_348',\n", + " 'w_349',\n", + " 'w_350',\n", + " 'w_351',\n", + " 'w_352',\n", + " 'w_353',\n", + " 'w_354',\n", + " 'w_355',\n", + " 'w_356',\n", + " 'w_357',\n", + " 'w_358',\n", + " 'w_359',\n", + " 'w_360',\n", + " 'w_361',\n", + " 'w_362',\n", + " 'w_363',\n", + " 'w_364',\n", + " 'w_365',\n", + " 'w_366',\n", + " 'w_367',\n", + " 'w_368',\n", + " 'w_369',\n", + " 'w_370',\n", + " 'w_371',\n", + " 'w_372',\n", + " 'w_373',\n", + " 'w_374',\n", + " 'w_375',\n", + " 'w_376',\n", + " 'w_377',\n", + " 'w_378',\n", + " 'w_379',\n", + " 'w_380',\n", + " 'w_381',\n", + " 'w_382',\n", + " 'w_383',\n", + " 'w_384',\n", + " 'w_385',\n", + " 'w_386',\n", + " 'w_387',\n", + " 'w_388',\n", + " 'w_389',\n", + " 'w_390',\n", + " 'w_391',\n", + " 'w_392',\n", + " 'w_393',\n", + " 'w_394',\n", + " 'w_395',\n", + " 'w_396',\n", + " 'w_397',\n", + " 'w_398',\n", + " 'w_399',\n", + " 'w_400',\n", + " 'w_401',\n", + " 'w_402',\n", + " 'w_403',\n", + " 'w_404',\n", + " 'w_405',\n", + " 'w_406',\n", + " 'w_407',\n", + " 'w_408',\n", + " 'w_409',\n", + " 'w_410',\n", + " 'w_411',\n", + " 'w_412',\n", + " 'w_413',\n", + " 'w_414',\n", + " 'w_415',\n", + " 'w_416',\n", + " 'w_417',\n", + " 'w_418',\n", + " 'w_419',\n", + " 'w_420',\n", + " 'w_421',\n", + " 'w_422',\n", + " 'w_423',\n", + " 'w_424',\n", + " 'w_425',\n", + " 'w_426',\n", + " 'w_427',\n", + " 'w_428',\n", + " 'w_429',\n", + " 'w_430',\n", + " 'w_431',\n", + " 'w_432',\n", + " 'w_433',\n", + " 'w_434',\n", + " 'w_435',\n", + " 'w_436',\n", + " 'w_437',\n", + " 'w_438',\n", + " 'w_439',\n", + " 'w_440',\n", + " 'w_441',\n", + " 'w_442',\n", + " 'w_443',\n", + " 'w_444',\n", + " 'w_445',\n", + " 'w_446',\n", + " 'w_447',\n", + " 'w_448',\n", + " 'w_449',\n", + " 'w_450',\n", + " 'w_451',\n", + " 'w_452',\n", + " 'w_453',\n", + " 'w_454',\n", + " 'w_455',\n", + " 'w_456',\n", + " 'w_457',\n", + " 'w_458',\n", + " 'w_459',\n", + " 'w_460',\n", + " 'w_461',\n", + " 'w_462',\n", + " 'w_463',\n", + " 'w_464',\n", + " 'w_465',\n", + " 'w_466',\n", + " 'w_467',\n", + " 'w_468',\n", + " 'w_469',\n", + " 'w_470',\n", + " 'w_471',\n", + " 'w_472',\n", + " 'w_473',\n", + " 'w_474',\n", + " 'w_475',\n", + " 'w_476',\n", + " 'w_477',\n", + " 'w_478',\n", + " 'w_479',\n", + " 'w_480',\n", + " 'w_481',\n", + " 'w_482',\n", + " 'w_483',\n", + " 'w_484',\n", + " 'w_485',\n", + " 'w_486',\n", + " 'w_487',\n", + " 'w_488',\n", + " 'w_489',\n", + " 'w_490',\n", + " 'w_491',\n", + " 'w_492',\n", + " 'w_493',\n", + " 'w_494',\n", + " 'w_495',\n", + " 'w_496',\n", + " 'w_497',\n", + " 'w_498',\n", + " 'w_499',\n", + " 'w_500',\n", + " 'w_501',\n", + " 'w_502',\n", + " 'w_503',\n", + " 'w_504',\n", + " 'w_505',\n", + " 'w_506',\n", + " 'w_507',\n", + " 'w_508',\n", + " 'w_509',\n", + " 'w_510',\n", + " 'w_511',\n", + " 'w_512',\n", + " 'w_513',\n", + " 'w_514',\n", + " 'w_515',\n", + " 'w_516',\n", + " 'w_517',\n", + " 'w_518',\n", + " 'w_519',\n", + " 'w_520',\n", + " 'w_521',\n", + " 'w_522',\n", + " 'w_523',\n", + " 'w_524',\n", + " 'w_525',\n", + " 'w_526',\n", + " 'w_527',\n", + " 'w_528',\n", + " 'w_529',\n", + " 'w_530',\n", + " 'w_531',\n", + " 'w_532',\n", + " 'w_533',\n", + " 'w_534',\n", + " 'w_535',\n", + " 'w_536',\n", + " 'w_537',\n", + " 'w_538',\n", + " 'w_539',\n", + " 'w_540',\n", + " 'w_541',\n", + " 'w_542',\n", + " 'w_543',\n", + " 'w_544',\n", + " 'w_545',\n", + " 'w_546',\n", + " 'w_547',\n", + " 'w_548',\n", + " 'w_549',\n", + " 'w_550',\n", + " 'w_551',\n", + " 'w_552',\n", + " 'w_553',\n", + " 'w_554',\n", + " 'w_555',\n", + " 'w_556',\n", + " 'w_557',\n", + " 'w_558',\n", + " 'w_559',\n", + " 'w_560',\n", + " 'w_561',\n", + " 'w_562',\n", + " 'w_563',\n", + " 'w_564',\n", + " 'w_565',\n", + " 'w_566',\n", + " 'w_567',\n", + " 'w_568',\n", + " 'w_569',\n", + " 'w_570',\n", + " 'w_571',\n", + " 'w_572',\n", + " 'w_573',\n", + " 'w_574',\n", + " 'w_575',\n", + " 'w_576',\n", + " 'w_577',\n", + " 'w_578',\n", + " 'w_579',\n", + " 'w_580',\n", + " 'w_581',\n", + " 'w_582',\n", + " 'w_583',\n", + " 'w_584',\n", + " 'w_585',\n", + " 'w_586',\n", + " 'w_587',\n", + " 'w_588',\n", + " 'w_589',\n", + " 'w_590',\n", + " 'w_591',\n", + " 'w_592',\n", + " 'w_593',\n", + " 'w_594',\n", + " 'w_595',\n", + " 'w_596',\n", + " 'w_597',\n", + " 'w_598',\n", + " 'w_599',\n", + " 'w_600',\n", + " 'w_601',\n", + " 'w_602',\n", + " 'w_603',\n", + " 'w_604',\n", + " 'w_605',\n", + " 'w_606',\n", + " 'w_607',\n", + " 'w_608',\n", + " 'w_609',\n", + " 'w_610',\n", + " 'w_611',\n", + " 'w_612',\n", + " 'w_613',\n", + " 'w_614',\n", + " 'w_615',\n", + " 'w_616',\n", + " 'w_617',\n", + " 'w_618',\n", + " 'w_619',\n", + " 'w_620',\n", + " 'w_621',\n", + " 'w_622',\n", + " 'w_623',\n", + " 'w_624',\n", + " 'w_625',\n", + " 'w_626',\n", + " 'w_627',\n", + " 'w_628',\n", + " 'w_629',\n", + " 'w_630',\n", + " 'w_631',\n", + " 'w_632',\n", + " 'w_633',\n", + " 'w_634',\n", + " 'w_635',\n", + " 'w_636',\n", + " 'w_637',\n", + " 'w_638',\n", + " 'w_639',\n", + " 'w_640',\n", + " 'w_641',\n", + " 'w_642',\n", + " 'w_643',\n", + " 'w_644',\n", + " 'w_645',\n", + " 'w_646',\n", + " 'w_647',\n", + " 'w_648',\n", + " 'w_649',\n", + " 'w_650',\n", + " 'w_651',\n", + " 'w_652',\n", + " 'w_653',\n", + " 'w_654',\n", + " 'w_655',\n", + " 'w_656',\n", + " 'w_657',\n", + " 'w_658',\n", + " 'w_659',\n", + " 'w_660',\n", + " 'w_661',\n", + " 'w_662',\n", + " 'w_663',\n", + " 'w_664',\n", + " 'w_665',\n", + " 'w_666',\n", + " 'w_667',\n", + " 'w_668',\n", + " 'w_669',\n", + " 'w_670',\n", + " 'w_671',\n", + " 'w_672',\n", + " 'w_673',\n", + " 'w_674',\n", + " 'w_675',\n", + " 'w_676',\n", + " 'w_677',\n", + " 'w_678',\n", + " 'w_679',\n", + " 'w_680',\n", + " 'w_681',\n", + " 'w_682',\n", + " 'w_683',\n", + " 'w_684',\n", + " 'w_685',\n", + " 'w_686',\n", + " 'w_687',\n", + " 'w_688',\n", + " 'w_689',\n", + " 'w_690',\n", + " 'w_691',\n", + " 'w_692',\n", + " 'w_693',\n", + " 'w_694',\n", + " 'w_695',\n", + " 'w_696',\n", + " 'w_697',\n", + " 'w_698',\n", + " 'w_699',\n", + " 'w_700',\n", + " 'w_701',\n", + " 'w_702',\n", + " 'w_703',\n", + " 'w_704',\n", + " 'w_705',\n", + " 'w_706',\n", + " 'w_707',\n", + " 'w_708',\n", + " 'w_709',\n", + " 'w_710',\n", + " 'w_711',\n", + " 'w_712',\n", + " 'w_713',\n", + " 'w_714',\n", + " 'w_715',\n", + " 'w_716',\n", + " 'w_717',\n", + " 'w_718',\n", + " 'w_719',\n", + " 'w_720',\n", + " 'w_721',\n", + " 'w_722',\n", + " 'w_723',\n", + " 'w_724',\n", + " 'w_725',\n", + " 'w_726',\n", + " 'w_727',\n", + " 'w_728',\n", + " 'w_729',\n", + " 'w_730',\n", + " 'w_731',\n", + " 'w_732',\n", + " 'w_733',\n", + " 'w_734',\n", + " 'w_735',\n", + " 'w_736',\n", + " 'w_737',\n", + " 'w_738',\n", + " 'w_739',\n", + " 'w_740',\n", + " 'w_741',\n", + " 'w_742',\n", + " 'w_743',\n", + " 'w_744',\n", + " 'w_745',\n", + " 'w_746',\n", + " 'w_747',\n", + " 'w_748',\n", + " 'w_749',\n", + " 'w_750',\n", + " 'w_751',\n", + " 'w_752',\n", + " 'w_753',\n", + " 'w_754',\n", + " 'w_755',\n", + " 'w_756',\n", + " 'w_757',\n", + " 'w_758',\n", + " 'w_759',\n", + " 'w_760',\n", + " 'w_761',\n", + " 'w_762',\n", + " 'w_763',\n", + " 'w_764',\n", + " 'w_765',\n", + " 'w_766',\n", + " 'w_767',\n", + " 'w_768',\n", + " 'w_769',\n", + " 'w_770',\n", + " 'w_771',\n", + " 'w_772',\n", + " 'w_773',\n", + " 'w_774',\n", + " 'w_775',\n", + " 'w_776',\n", + " 'w_777',\n", + " 'w_778',\n", + " 'w_779',\n", + " 'w_780',\n", + " 'w_781',\n", + " 'w_782',\n", + " 'w_783',\n", + " 'w_784',\n", + " 'w_785',\n", + " 'w_786',\n", + " 'w_787',\n", + " 'w_788',\n", + " 'w_789',\n", + " 'w_790',\n", + " 'w_791',\n", + " 'w_792',\n", + " 'w_793',\n", + " 'w_794',\n", + " 'w_795',\n", + " 'w_796',\n", + " 'w_797',\n", + " 'w_798',\n", + " 'w_799',\n", + " 'w_800',\n", + " 'w_801',\n", + " 'w_802',\n", + " 'w_803',\n", + " 'w_804',\n", + " 'w_805',\n", + " 'w_806',\n", + " 'w_807',\n", + " 'w_808',\n", + " 'w_809',\n", + " 'w_810',\n", + " 'w_811',\n", + " 'w_812',\n", + " 'w_813',\n", + " 'w_814',\n", + " 'w_815',\n", + " 'w_816',\n", + " 'w_817',\n", + " 'w_818',\n", + " 'w_819',\n", + " 'w_820',\n", + " 'w_821',\n", + " 'w_822',\n", + " 'w_823',\n", + " 'w_824',\n", + " 'w_825',\n", + " 'w_826',\n", + " 'w_827',\n", + " 'w_828',\n", + " 'w_829',\n", + " 'w_830',\n", + " 'w_831',\n", + " 'w_832',\n", + " 'w_833',\n", + " 'w_834',\n", + " 'w_835',\n", + " 'w_836',\n", + " 'w_837',\n", + " 'w_838',\n", + " 'w_839',\n", + " 'w_840',\n", + " 'w_841',\n", + " 'w_842',\n", + " 'w_843',\n", + " 'w_844',\n", + " 'w_845',\n", + " 'w_846',\n", + " 'w_847',\n", + " 'w_848',\n", + " 'w_849',\n", + " 'w_850',\n", + " 'w_851',\n", + " 'w_852',\n", + " 'w_853',\n", + " 'w_854',\n", + " 'w_855',\n", + " 'w_856',\n", + " 'w_857',\n", + " 'w_858',\n", + " 'w_859',\n", + " 'w_860',\n", + " 'w_861',\n", + " 'w_862',\n", + " 'w_863',\n", + " 'w_864',\n", + " 'w_865',\n", + " 'w_866',\n", + " 'w_867',\n", + " 'w_868',\n", + " 'w_869',\n", + " 'w_870',\n", + " 'w_871',\n", + " 'w_872',\n", + " 'w_873',\n", + " 'w_874',\n", + " 'w_875',\n", + " 'w_876',\n", + " 'w_877',\n", + " 'w_878',\n", + " 'w_879',\n", + " 'w_880',\n", + " 'w_881',\n", + " 'w_882',\n", + " 'w_883',\n", + " 'w_884',\n", + " 'w_885',\n", + " 'w_886',\n", + " 'w_887',\n", + " 'w_888',\n", + " 'w_889',\n", + " 'w_890',\n", + " 'w_891',\n", + " 'w_892',\n", + " 'w_893',\n", + " 'w_894',\n", + " 'w_895',\n", + " 'w_896',\n", + " 'w_897',\n", + " 'w_898',\n", + " 'w_899',\n", + " 'w_900',\n", + " 'w_901',\n", + " 'w_902',\n", + " 'w_903',\n", + " 'w_904',\n", + " 'w_905',\n", + " 'w_906',\n", + " 'w_907',\n", + " 'w_908',\n", + " 'w_909',\n", + " 'w_910',\n", + " 'w_911',\n", + " 'w_912',\n", + " 'w_913',\n", + " 'w_914',\n", + " 'w_915',\n", + " 'w_916',\n", + " 'w_917',\n", + " 'w_918',\n", + " 'w_919',\n", + " 'w_920',\n", + " 'w_921',\n", + " 'w_922',\n", + " 'w_923',\n", + " 'w_924',\n", + " 'w_925',\n", + " 'w_926',\n", + " 'w_927',\n", + " 'w_928',\n", + " 'w_929',\n", + " 'w_930',\n", + " 'w_931',\n", + " 'w_932',\n", + " 'w_933',\n", + " 'w_934',\n", + " 'w_935',\n", + " 'w_936',\n", + " 'w_937',\n", + " 'w_938',\n", + " 'w_939',\n", + " 'w_940',\n", + " 'w_941',\n", + " 'w_942',\n", + " 'w_943',\n", + " 'w_944',\n", + " 'w_945',\n", + " 'w_946',\n", + " 'w_947',\n", + " 'w_948',\n", + " 'w_949',\n", + " 'w_950',\n", + " 'w_951',\n", + " 'w_952',\n", + " 'w_953',\n", + " 'w_954',\n", + " 'w_955',\n", + " 'w_956',\n", + " 'w_957',\n", + " 'w_958',\n", + " 'w_959',\n", + " 'w_960',\n", + " 'w_961',\n", + " 'w_962',\n", + " 'w_963',\n", + " 'w_964',\n", + " 'w_965',\n", + " 'w_966',\n", + " 'w_967',\n", + " 'w_968',\n", + " 'w_969',\n", + " 'w_970',\n", + " 'w_971',\n", + " 'w_972',\n", + " 'w_973',\n", + " 'w_974',\n", + " 'w_975',\n", + " 'w_976',\n", + " 'w_977',\n", + " 'w_978',\n", + " 'w_979',\n", + " 'w_980',\n", + " 'w_981',\n", + " 'w_982',\n", + " 'w_983',\n", + " 'w_984',\n", + " 'w_985',\n", + " 'w_986',\n", + " 'w_987',\n", + " 'w_988',\n", + " 'w_989',\n", + " 'w_990',\n", + " 'w_991',\n", + " 'w_992',\n", + " 'w_993',\n", + " 'w_994',\n", + " 'w_995',\n", + " 'w_996',\n", + " 'w_997',\n", + " 'w_998',\n", + " 'w_999',\n", + " ...],\n", + " : {: 'random'},\n", + " : {}}]}]}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config_random" + ] + }, + { + "cell_type": "markdown", + "id": "cecde9cb", + "metadata": {}, + "source": [ + "\n", + "## Dataset Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "0c93b8cb", + "metadata": {}, + "outputs": [], + "source": [ + "save_path_proper = '/workspace/data/cora_generated'\n", + "save_path_random = '/workspace/data/cora_random'" + ] + }, + { + "cell_type": "markdown", + "id": "a0b3a466", + "metadata": {}, + "source": [ + "### Create Synthesizers" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "53a47bcf", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_proper = ConfigurationGraphSynthesizer(configuration=config_proper, save_path=save_path_proper, gpu=True)\n", + "synthesizer_random = ConfigurationGraphSynthesizer(configuration=config_random, save_path=save_path_random, gpu=True)" + ] + }, + { + "cell_type": "markdown", + "id": "151145bd", + "metadata": {}, + "source": [ + "### Fit Synthesizers" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "53180a5a", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_proper.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "76e26e97", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_random.fit()" + ] + }, + { + "cell_type": "markdown", + "id": "d891e20e", + "metadata": {}, + "source": [ + "### Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "7a1be377", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_generated_proper = synthesizer_proper.generate()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "f5f3cb38", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'cite',\n", + " 'count': 5428,\n", + " 'src_node_type': 'paper',\n", + " 'dst_node_type': 'paper',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'cite_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/cora_preprocessed',\n", + " : 'cite'},\n", + " : {'has_self_loop': False,\n", + " 'gpu': True,\n", + " 'verbose': False}}}],\n", + " : [{'name': 'paper',\n", + " 'count': 4096,\n", + " 'features': [{'name': 'w_0',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'},\n", + " {'name': 'w_1', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_2', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_3', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_4', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_5', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_6', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_7', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_8', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_9', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_10', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_11', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_12', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_13', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_14', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_15', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_16', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_17', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_18', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_19', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_20', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_21', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_22', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_23', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_24', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_25', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_26', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_27', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_28', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_29', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_30', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_31', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_32', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_33', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_34', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_35', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_36', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_37', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_38', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_39', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_40', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_41', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_42', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_43', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_44', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_45', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_46', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_47', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_48', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_49', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_50', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_51', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_52', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_53', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_54', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_55', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_56', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_57', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_58', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_59', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_60', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_61', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_62', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_63', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_64', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_65', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_66', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_67', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_68', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_69', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_70', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_71', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_72', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_73', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_74', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_75', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_76', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_77', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_78', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_79', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_80', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_81', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_82', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_83', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_84', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_85', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_86', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_87', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_88', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_89', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_90', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_91', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_92', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_93', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_94', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_95', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_96', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_97', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_98', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_99', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_100', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_101', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_102', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_103', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_104', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_105', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_106', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_107', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_108', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_109', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_110', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_111', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_112', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_113', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_114', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_115', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_116', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_117', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_118', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_119', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_120', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_121', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_122', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_123', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_124', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_125', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_126', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_127', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_128', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_129', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_130', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_131', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_132', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_133', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_134', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_135', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_136', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_137', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_138', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_139', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_140', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_141', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_142', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_143', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_144', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_145', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_146', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_147', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_148', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_149', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_150', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_151', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_152', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_153', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_154', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_155', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_156', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_157', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_158', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_159', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_160', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_161', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_162', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_163', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_164', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_165', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_166', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_167', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_168', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_169', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_170', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_171', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_172', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_173', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_174', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_175', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_176', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_177', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_178', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_179', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_180', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_181', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_182', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_183', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_184', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_185', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_186', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_187', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_188', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_189', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_190', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_191', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_192', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_193', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_194', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_195', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_196', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_197', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_198', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_199', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_200', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_201', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_202', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_203', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_204', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_205', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_206', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_207', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_208', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_209', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_210', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_211', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_212', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_213', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_214', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_215', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_216', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_217', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_218', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_219', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_220', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_221', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_222', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_223', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_224', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_225', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_226', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_227', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_228', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_229', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_230', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_231', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_232', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_233', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_234', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_235', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_236', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_237', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_238', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_239', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_240', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_241', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_242', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_243', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_244', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_245', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_246', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_247', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_248', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_249', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_250', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_251', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_252', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_253', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_254', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_255', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_256', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_257', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_258', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_259', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_260', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_261', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_262', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_263', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_264', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_265', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_266', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_267', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_268', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_269', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_270', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_271', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_272', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_273', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_274', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_275', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_276', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_277', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_278', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_279', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_280', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_281', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_282', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_283', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_284', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_285', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_286', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_287', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_288', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_289', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_290', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_291', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_292', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_293', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_294', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_295', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_296', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_297', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_298', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_299', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_300', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_301', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_302', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_303', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_304', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_305', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_306', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_307', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_308', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_309', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_310', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_311', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_312', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_313', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_314', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_315', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_316', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_317', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_318', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_319', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_320', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_321', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_322', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_323', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_324', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_325', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_326', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_327', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_328', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_329', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_330', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_331', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_332', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_333', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_334', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_335', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_336', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_337', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_338', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_339', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_340', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_341', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_342', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_343', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_344', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_345', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_346', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_347', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_348', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_349', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_350', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_351', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_352', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_353', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_354', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_355', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_356', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_357', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_358', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_359', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_360', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_361', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_362', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_363', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_364', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_365', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_366', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_367', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_368', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_369', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_370', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_371', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_372', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_373', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_374', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_375', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_376', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_377', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_378', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_379', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_380', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_381', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_382', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_383', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_384', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_385', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_386', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_387', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_388', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_389', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_390', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_391', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_392', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_393', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_394', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_395', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_396', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_397', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_398', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_399', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_400', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_401', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_402', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_403', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_404', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_405', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_406', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_407', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_408', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_409', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_410', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_411', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_412', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_413', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_414', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_415', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_416', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_417', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_418', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_419', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_420', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_421', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_422', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_423', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_424', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_425', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_426', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_427', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_428', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_429', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_430', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_431', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_432', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_433', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_434', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_435', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_436', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_437', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_438', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_439', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_440', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_441', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_442', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_443', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_444', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_445', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_446', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_447', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_448', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_449', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_450', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_451', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_452', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_453', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_454', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_455', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_456', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_457', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_458', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_459', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_460', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_461', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_462', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_463', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_464', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_465', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_466', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_467', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_468', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_469', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_470', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_471', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_472', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_473', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_474', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_475', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_476', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_477', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_478', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_479', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_480', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_481', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_482', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_483', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_484', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_485', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_486', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_487', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_488', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_489', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_490', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_491', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_492', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_493', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_494', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_495', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_496', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_497', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_498', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_499', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_500', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_501', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_502', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_503', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_504', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_505', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_506', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_507', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_508', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_509', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_510', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_511', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_512', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_513', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_514', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_515', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_516', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_517', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_518', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_519', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_520', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_521', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_522', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_523', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_524', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_525', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_526', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_527', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_528', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_529', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_530', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_531', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_532', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_533', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_534', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_535', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_536', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_537', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_538', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_539', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_540', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_541', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_542', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_543', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_544', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_545', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_546', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_547', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_548', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_549', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_550', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_551', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_552', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_553', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_554', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_555', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_556', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_557', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_558', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_559', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_560', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_561', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_562', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_563', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_564', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_565', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_566', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_567', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_568', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_569', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_570', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_571', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_572', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_573', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_574', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_575', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_576', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_577', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_578', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_579', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_580', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_581', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_582', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_583', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_584', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_585', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_586', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_587', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_588', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_589', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_590', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_591', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_592', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_593', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_594', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_595', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_596', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_597', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_598', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_599', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_600', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_601', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_602', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_603', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_604', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_605', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_606', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_607', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_608', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_609', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_610', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_611', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_612', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_613', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_614', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_615', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_616', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_617', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_618', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_619', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_620', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_621', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_622', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_623', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_624', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_625', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_626', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_627', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_628', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_629', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_630', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_631', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_632', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_633', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_634', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_635', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_636', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_637', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_638', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_639', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_640', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_641', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_642', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_643', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_644', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_645', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_646', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_647', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_648', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_649', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_650', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_651', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_652', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_653', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_654', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_655', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_656', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_657', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_658', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_659', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_660', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_661', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_662', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_663', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_664', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_665', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_666', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_667', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_668', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_669', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_670', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_671', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_672', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_673', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_674', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_675', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_676', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_677', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_678', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_679', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_680', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_681', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_682', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_683', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_684', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_685', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_686', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_687', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_688', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_689', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_690', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_691', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_692', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_693', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_694', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_695', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_696', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_697', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_698', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_699', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_700', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_701', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_702', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_703', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_704', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_705', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_706', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_707', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_708', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_709', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_710', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_711', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_712', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_713', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_714', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_715', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_716', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_717', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_718', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_719', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_720', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_721', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_722', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_723', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_724', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_725', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_726', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_727', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_728', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_729', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_730', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_731', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_732', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_733', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_734', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_735', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_736', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_737', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_738', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_739', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_740', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_741', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_742', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_743', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_744', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_745', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_746', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_747', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_748', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_749', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_750', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_751', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_752', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_753', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_754', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_755', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_756', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_757', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_758', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_759', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_760', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_761', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_762', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_763', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_764', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_765', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_766', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_767', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_768', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_769', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_770', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_771', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_772', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_773', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_774', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_775', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_776', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_777', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_778', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_779', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_780', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_781', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_782', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_783', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_784', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_785', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_786', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_787', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_788', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_789', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_790', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_791', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_792', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_793', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_794', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_795', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_796', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_797', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_798', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_799', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_800', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_801', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_802', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_803', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_804', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_805', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_806', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_807', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_808', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_809', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_810', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_811', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_812', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_813', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_814', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_815', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_816', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_817', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_818', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_819', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_820', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_821', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_822', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_823', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_824', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_825', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_826', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_827', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_828', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_829', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_830', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_831', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_832', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_833', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_834', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_835', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_836', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_837', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_838', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_839', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_840', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_841', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_842', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_843', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_844', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_845', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_846', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_847', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_848', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_849', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_850', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_851', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_852', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_853', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_854', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_855', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_856', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_857', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_858', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_859', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_860', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_861', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_862', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_863', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_864', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_865', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_866', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_867', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_868', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_869', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_870', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_871', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_872', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_873', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_874', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_875', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_876', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_877', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_878', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_879', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_880', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_881', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_882', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_883', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_884', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_885', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_886', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_887', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_888', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_889', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_890', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_891', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_892', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_893', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_894', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_895', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_896', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_897', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_898', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_899', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_900', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_901', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_902', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_903', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_904', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_905', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_906', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_907', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_908', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_909', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_910', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_911', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_912', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_913', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_914', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_915', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_916', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_917', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_918', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_919', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_920', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_921', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_922', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_923', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_924', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_925', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_926', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_927', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_928', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_929', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_930', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_931', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_932', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_933', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_934', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_935', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_936', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_937', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_938', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_939', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_940', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_941', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_942', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_943', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_944', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_945', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_946', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_947', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_948', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_949', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_950', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_951', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_952', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_953', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_954', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_955', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_956', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_957', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_958', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_959', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_960', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_961', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_962', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_963', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_964', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_965', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_966', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_967', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_968', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_969', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_970', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_971', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_972', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_973', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_974', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_975', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_976', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_977', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_978', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_979', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_980', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_981', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_982', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_983', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_984', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_985', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_986', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_987', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_988', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_989', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_990', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_991', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_992', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_993', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_994', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_995', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_996', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_997', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_998', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_999', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " ...],\n", + " 'features_path': 'paper.parquet',\n", + " : [{: 'kde',\n", + " : ['w_0',\n", + " 'w_1',\n", + " 'w_2',\n", + " 'w_3',\n", + " 'w_4',\n", + " 'w_5',\n", + " 'w_6',\n", + " 'w_7',\n", + " 'w_8',\n", + " 'w_9',\n", + " 'w_10',\n", + " 'w_11',\n", + " 'w_12',\n", + " 'w_13',\n", + " 'w_14',\n", + " 'w_15',\n", + " 'w_16',\n", + " 'w_17',\n", + " 'w_18',\n", + " 'w_19',\n", + " 'w_20',\n", + " 'w_21',\n", + " 'w_22',\n", + " 'w_23',\n", + " 'w_24',\n", + " 'w_25',\n", + " 'w_26',\n", + " 'w_27',\n", + " 'w_28',\n", + " 'w_29',\n", + " 'w_30',\n", + " 'w_31',\n", + " 'w_32',\n", + " 'w_33',\n", + " 'w_34',\n", + " 'w_35',\n", + " 'w_36',\n", + " 'w_37',\n", + " 'w_38',\n", + " 'w_39',\n", + " 'w_40',\n", + " 'w_41',\n", + " 'w_42',\n", + " 'w_43',\n", + " 'w_44',\n", + " 'w_45',\n", + " 'w_46',\n", + " 'w_47',\n", + " 'w_48',\n", + " 'w_49',\n", + " 'w_50',\n", + " 'w_51',\n", + " 'w_52',\n", + " 'w_53',\n", + " 'w_54',\n", + " 'w_55',\n", + " 'w_56',\n", + " 'w_57',\n", + " 'w_58',\n", + " 'w_59',\n", + " 'w_60',\n", + " 'w_61',\n", + " 'w_62',\n", + " 'w_63',\n", + " 'w_64',\n", + " 'w_65',\n", + " 'w_66',\n", + " 'w_67',\n", + " 'w_68',\n", + " 'w_69',\n", + " 'w_70',\n", + " 'w_71',\n", + " 'w_72',\n", + " 'w_73',\n", + " 'w_74',\n", + " 'w_75',\n", + " 'w_76',\n", + " 'w_77',\n", + " 'w_78',\n", + " 'w_79',\n", + " 'w_80',\n", + " 'w_81',\n", + " 'w_82',\n", + " 'w_83',\n", + " 'w_84',\n", + " 'w_85',\n", + " 'w_86',\n", + " 'w_87',\n", + " 'w_88',\n", + " 'w_89',\n", + " 'w_90',\n", + " 'w_91',\n", + " 'w_92',\n", + " 'w_93',\n", + " 'w_94',\n", + " 'w_95',\n", + " 'w_96',\n", + " 'w_97',\n", + " 'w_98',\n", + " 'w_99',\n", + " 'w_100',\n", + " 'w_101',\n", + " 'w_102',\n", + " 'w_103',\n", + " 'w_104',\n", + " 'w_105',\n", + " 'w_106',\n", + " 'w_107',\n", + " 'w_108',\n", + " 'w_109',\n", + " 'w_110',\n", + " 'w_111',\n", + " 'w_112',\n", + " 'w_113',\n", + " 'w_114',\n", + " 'w_115',\n", + " 'w_116',\n", + " 'w_117',\n", + " 'w_118',\n", + " 'w_119',\n", + " 'w_120',\n", + " 'w_121',\n", + " 'w_122',\n", + " 'w_123',\n", + " 'w_124',\n", + " 'w_125',\n", + " 'w_126',\n", + " 'w_127',\n", + " 'w_128',\n", + " 'w_129',\n", + " 'w_130',\n", + " 'w_131',\n", + " 'w_132',\n", + " 'w_133',\n", + " 'w_134',\n", + " 'w_135',\n", + " 'w_136',\n", + " 'w_137',\n", + " 'w_138',\n", + " 'w_139',\n", + " 'w_140',\n", + " 'w_141',\n", + " 'w_142',\n", + " 'w_143',\n", + " 'w_144',\n", + " 'w_145',\n", + " 'w_146',\n", + " 'w_147',\n", + " 'w_148',\n", + " 'w_149',\n", + " 'w_150',\n", + " 'w_151',\n", + " 'w_152',\n", + " 'w_153',\n", + " 'w_154',\n", + " 'w_155',\n", + " 'w_156',\n", + " 'w_157',\n", + " 'w_158',\n", + " 'w_159',\n", + " 'w_160',\n", + " 'w_161',\n", + " 'w_162',\n", + " 'w_163',\n", + " 'w_164',\n", + " 'w_165',\n", + " 'w_166',\n", + " 'w_167',\n", + " 'w_168',\n", + " 'w_169',\n", + " 'w_170',\n", + " 'w_171',\n", + " 'w_172',\n", + " 'w_173',\n", + " 'w_174',\n", + " 'w_175',\n", + " 'w_176',\n", + " 'w_177',\n", + " 'w_178',\n", + " 'w_179',\n", + " 'w_180',\n", + " 'w_181',\n", + " 'w_182',\n", + " 'w_183',\n", + " 'w_184',\n", + " 'w_185',\n", + " 'w_186',\n", + " 'w_187',\n", + " 'w_188',\n", + " 'w_189',\n", + " 'w_190',\n", + " 'w_191',\n", + " 'w_192',\n", + " 'w_193',\n", + " 'w_194',\n", + " 'w_195',\n", + " 'w_196',\n", + " 'w_197',\n", + " 'w_198',\n", + " 'w_199',\n", + " 'w_200',\n", + " 'w_201',\n", + " 'w_202',\n", + " 'w_203',\n", + " 'w_204',\n", + " 'w_205',\n", + " 'w_206',\n", + " 'w_207',\n", + " 'w_208',\n", + " 'w_209',\n", + " 'w_210',\n", + " 'w_211',\n", + " 'w_212',\n", + " 'w_213',\n", + " 'w_214',\n", + " 'w_215',\n", + " 'w_216',\n", + " 'w_217',\n", + " 'w_218',\n", + " 'w_219',\n", + " 'w_220',\n", + " 'w_221',\n", + " 'w_222',\n", + " 'w_223',\n", + " 'w_224',\n", + " 'w_225',\n", + " 'w_226',\n", + " 'w_227',\n", + " 'w_228',\n", + " 'w_229',\n", + " 'w_230',\n", + " 'w_231',\n", + " 'w_232',\n", + " 'w_233',\n", + " 'w_234',\n", + " 'w_235',\n", + " 'w_236',\n", + " 'w_237',\n", + " 'w_238',\n", + " 'w_239',\n", + " 'w_240',\n", + " 'w_241',\n", + " 'w_242',\n", + " 'w_243',\n", + " 'w_244',\n", + " 'w_245',\n", + " 'w_246',\n", + " 'w_247',\n", + " 'w_248',\n", + " 'w_249',\n", + " 'w_250',\n", + " 'w_251',\n", + " 'w_252',\n", + " 'w_253',\n", + " 'w_254',\n", + " 'w_255',\n", + " 'w_256',\n", + " 'w_257',\n", + " 'w_258',\n", + " 'w_259',\n", + " 'w_260',\n", + " 'w_261',\n", + " 'w_262',\n", + " 'w_263',\n", + " 'w_264',\n", + " 'w_265',\n", + " 'w_266',\n", + " 'w_267',\n", + " 'w_268',\n", + " 'w_269',\n", + " 'w_270',\n", + " 'w_271',\n", + " 'w_272',\n", + " 'w_273',\n", + " 'w_274',\n", + " 'w_275',\n", + " 'w_276',\n", + " 'w_277',\n", + " 'w_278',\n", + " 'w_279',\n", + " 'w_280',\n", + " 'w_281',\n", + " 'w_282',\n", + " 'w_283',\n", + " 'w_284',\n", + " 'w_285',\n", + " 'w_286',\n", + " 'w_287',\n", + " 'w_288',\n", + " 'w_289',\n", + " 'w_290',\n", + " 'w_291',\n", + " 'w_292',\n", + " 'w_293',\n", + " 'w_294',\n", + " 'w_295',\n", + " 'w_296',\n", + " 'w_297',\n", + " 'w_298',\n", + " 'w_299',\n", + " 'w_300',\n", + " 'w_301',\n", + " 'w_302',\n", + " 'w_303',\n", + " 'w_304',\n", + " 'w_305',\n", + " 'w_306',\n", + " 'w_307',\n", + " 'w_308',\n", + " 'w_309',\n", + " 'w_310',\n", + " 'w_311',\n", + " 'w_312',\n", + " 'w_313',\n", + " 'w_314',\n", + " 'w_315',\n", + " 'w_316',\n", + " 'w_317',\n", + " 'w_318',\n", + " 'w_319',\n", + " 'w_320',\n", + " 'w_321',\n", + " 'w_322',\n", + " 'w_323',\n", + " 'w_324',\n", + " 'w_325',\n", + " 'w_326',\n", + " 'w_327',\n", + " 'w_328',\n", + " 'w_329',\n", + " 'w_330',\n", + " 'w_331',\n", + " 'w_332',\n", + " 'w_333',\n", + " 'w_334',\n", + " 'w_335',\n", + " 'w_336',\n", + " 'w_337',\n", + " 'w_338',\n", + " 'w_339',\n", + " 'w_340',\n", + " 'w_341',\n", + " 'w_342',\n", + " 'w_343',\n", + " 'w_344',\n", + " 'w_345',\n", + " 'w_346',\n", + " 'w_347',\n", + " 'w_348',\n", + " 'w_349',\n", + " 'w_350',\n", + " 'w_351',\n", + " 'w_352',\n", + " 'w_353',\n", + " 'w_354',\n", + " 'w_355',\n", + " 'w_356',\n", + " 'w_357',\n", + " 'w_358',\n", + " 'w_359',\n", + " 'w_360',\n", + " 'w_361',\n", + " 'w_362',\n", + " 'w_363',\n", + " 'w_364',\n", + " 'w_365',\n", + " 'w_366',\n", + " 'w_367',\n", + " 'w_368',\n", + " 'w_369',\n", + " 'w_370',\n", + " 'w_371',\n", + " 'w_372',\n", + " 'w_373',\n", + " 'w_374',\n", + " 'w_375',\n", + " 'w_376',\n", + " 'w_377',\n", + " 'w_378',\n", + " 'w_379',\n", + " 'w_380',\n", + " 'w_381',\n", + " 'w_382',\n", + " 'w_383',\n", + " 'w_384',\n", + " 'w_385',\n", + " 'w_386',\n", + " 'w_387',\n", + " 'w_388',\n", + " 'w_389',\n", + " 'w_390',\n", + " 'w_391',\n", + " 'w_392',\n", + " 'w_393',\n", + " 'w_394',\n", + " 'w_395',\n", + " 'w_396',\n", + " 'w_397',\n", + " 'w_398',\n", + " 'w_399',\n", + " 'w_400',\n", + " 'w_401',\n", + " 'w_402',\n", + " 'w_403',\n", + " 'w_404',\n", + " 'w_405',\n", + " 'w_406',\n", + " 'w_407',\n", + " 'w_408',\n", + " 'w_409',\n", + " 'w_410',\n", + " 'w_411',\n", + " 'w_412',\n", + " 'w_413',\n", + " 'w_414',\n", + " 'w_415',\n", + " 'w_416',\n", + " 'w_417',\n", + " 'w_418',\n", + " 'w_419',\n", + " 'w_420',\n", + " 'w_421',\n", + " 'w_422',\n", + " 'w_423',\n", + " 'w_424',\n", + " 'w_425',\n", + " 'w_426',\n", + " 'w_427',\n", + " 'w_428',\n", + " 'w_429',\n", + " 'w_430',\n", + " 'w_431',\n", + " 'w_432',\n", + " 'w_433',\n", + " 'w_434',\n", + " 'w_435',\n", + " 'w_436',\n", + " 'w_437',\n", + " 'w_438',\n", + " 'w_439',\n", + " 'w_440',\n", + " 'w_441',\n", + " 'w_442',\n", + " 'w_443',\n", + " 'w_444',\n", + " 'w_445',\n", + " 'w_446',\n", + " 'w_447',\n", + " 'w_448',\n", + " 'w_449',\n", + " 'w_450',\n", + " 'w_451',\n", + " 'w_452',\n", + " 'w_453',\n", + " 'w_454',\n", + " 'w_455',\n", + " 'w_456',\n", + " 'w_457',\n", + " 'w_458',\n", + " 'w_459',\n", + " 'w_460',\n", + " 'w_461',\n", + " 'w_462',\n", + " 'w_463',\n", + " 'w_464',\n", + " 'w_465',\n", + " 'w_466',\n", + " 'w_467',\n", + " 'w_468',\n", + " 'w_469',\n", + " 'w_470',\n", + " 'w_471',\n", + " 'w_472',\n", + " 'w_473',\n", + " 'w_474',\n", + " 'w_475',\n", + " 'w_476',\n", + " 'w_477',\n", + " 'w_478',\n", + " 'w_479',\n", + " 'w_480',\n", + " 'w_481',\n", + " 'w_482',\n", + " 'w_483',\n", + " 'w_484',\n", + " 'w_485',\n", + " 'w_486',\n", + " 'w_487',\n", + " 'w_488',\n", + " 'w_489',\n", + " 'w_490',\n", + " 'w_491',\n", + " 'w_492',\n", + " 'w_493',\n", + " 'w_494',\n", + " 'w_495',\n", + " 'w_496',\n", + " 'w_497',\n", + " 'w_498',\n", + " 'w_499',\n", + " 'w_500',\n", + " 'w_501',\n", + " 'w_502',\n", + " 'w_503',\n", + " 'w_504',\n", + " 'w_505',\n", + " 'w_506',\n", + " 'w_507',\n", + " 'w_508',\n", + " 'w_509',\n", + " 'w_510',\n", + " 'w_511',\n", + " 'w_512',\n", + " 'w_513',\n", + " 'w_514',\n", + " 'w_515',\n", + " 'w_516',\n", + " 'w_517',\n", + " 'w_518',\n", + " 'w_519',\n", + " 'w_520',\n", + " 'w_521',\n", + " 'w_522',\n", + " 'w_523',\n", + " 'w_524',\n", + " 'w_525',\n", + " 'w_526',\n", + " 'w_527',\n", + " 'w_528',\n", + " 'w_529',\n", + " 'w_530',\n", + " 'w_531',\n", + " 'w_532',\n", + " 'w_533',\n", + " 'w_534',\n", + " 'w_535',\n", + " 'w_536',\n", + " 'w_537',\n", + " 'w_538',\n", + " 'w_539',\n", + " 'w_540',\n", + " 'w_541',\n", + " 'w_542',\n", + " 'w_543',\n", + " 'w_544',\n", + " 'w_545',\n", + " 'w_546',\n", + " 'w_547',\n", + " 'w_548',\n", + " 'w_549',\n", + " 'w_550',\n", + " 'w_551',\n", + " 'w_552',\n", + " 'w_553',\n", + " 'w_554',\n", + " 'w_555',\n", + " 'w_556',\n", + " 'w_557',\n", + " 'w_558',\n", + " 'w_559',\n", + " 'w_560',\n", + " 'w_561',\n", + " 'w_562',\n", + " 'w_563',\n", + " 'w_564',\n", + " 'w_565',\n", + " 'w_566',\n", + " 'w_567',\n", + " 'w_568',\n", + " 'w_569',\n", + " 'w_570',\n", + " 'w_571',\n", + " 'w_572',\n", + " 'w_573',\n", + " 'w_574',\n", + " 'w_575',\n", + " 'w_576',\n", + " 'w_577',\n", + " 'w_578',\n", + " 'w_579',\n", + " 'w_580',\n", + " 'w_581',\n", + " 'w_582',\n", + " 'w_583',\n", + " 'w_584',\n", + " 'w_585',\n", + " 'w_586',\n", + " 'w_587',\n", + " 'w_588',\n", + " 'w_589',\n", + " 'w_590',\n", + " 'w_591',\n", + " 'w_592',\n", + " 'w_593',\n", + " 'w_594',\n", + " 'w_595',\n", + " 'w_596',\n", + " 'w_597',\n", + " 'w_598',\n", + " 'w_599',\n", + " 'w_600',\n", + " 'w_601',\n", + " 'w_602',\n", + " 'w_603',\n", + " 'w_604',\n", + " 'w_605',\n", + " 'w_606',\n", + " 'w_607',\n", + " 'w_608',\n", + " 'w_609',\n", + " 'w_610',\n", + " 'w_611',\n", + " 'w_612',\n", + " 'w_613',\n", + " 'w_614',\n", + " 'w_615',\n", + " 'w_616',\n", + " 'w_617',\n", + " 'w_618',\n", + " 'w_619',\n", + " 'w_620',\n", + " 'w_621',\n", + " 'w_622',\n", + " 'w_623',\n", + " 'w_624',\n", + " 'w_625',\n", + " 'w_626',\n", + " 'w_627',\n", + " 'w_628',\n", + " 'w_629',\n", + " 'w_630',\n", + " 'w_631',\n", + " 'w_632',\n", + " 'w_633',\n", + " 'w_634',\n", + " 'w_635',\n", + " 'w_636',\n", + " 'w_637',\n", + " 'w_638',\n", + " 'w_639',\n", + " 'w_640',\n", + " 'w_641',\n", + " 'w_642',\n", + " 'w_643',\n", + " 'w_644',\n", + " 'w_645',\n", + " 'w_646',\n", + " 'w_647',\n", + " 'w_648',\n", + " 'w_649',\n", + " 'w_650',\n", + " 'w_651',\n", + " 'w_652',\n", + " 'w_653',\n", + " 'w_654',\n", + " 'w_655',\n", + " 'w_656',\n", + " 'w_657',\n", + " 'w_658',\n", + " 'w_659',\n", + " 'w_660',\n", + " 'w_661',\n", + " 'w_662',\n", + " 'w_663',\n", + " 'w_664',\n", + " 'w_665',\n", + " 'w_666',\n", + " 'w_667',\n", + " 'w_668',\n", + " 'w_669',\n", + " 'w_670',\n", + " 'w_671',\n", + " 'w_672',\n", + " 'w_673',\n", + " 'w_674',\n", + " 'w_675',\n", + " 'w_676',\n", + " 'w_677',\n", + " 'w_678',\n", + " 'w_679',\n", + " 'w_680',\n", + " 'w_681',\n", + " 'w_682',\n", + " 'w_683',\n", + " 'w_684',\n", + " 'w_685',\n", + " 'w_686',\n", + " 'w_687',\n", + " 'w_688',\n", + " 'w_689',\n", + " 'w_690',\n", + " 'w_691',\n", + " 'w_692',\n", + " 'w_693',\n", + " 'w_694',\n", + " 'w_695',\n", + " 'w_696',\n", + " 'w_697',\n", + " 'w_698',\n", + " 'w_699',\n", + " 'w_700',\n", + " 'w_701',\n", + " 'w_702',\n", + " 'w_703',\n", + " 'w_704',\n", + " 'w_705',\n", + " 'w_706',\n", + " 'w_707',\n", + " 'w_708',\n", + " 'w_709',\n", + " 'w_710',\n", + " 'w_711',\n", + " 'w_712',\n", + " 'w_713',\n", + " 'w_714',\n", + " 'w_715',\n", + " 'w_716',\n", + " 'w_717',\n", + " 'w_718',\n", + " 'w_719',\n", + " 'w_720',\n", + " 'w_721',\n", + " 'w_722',\n", + " 'w_723',\n", + " 'w_724',\n", + " 'w_725',\n", + " 'w_726',\n", + " 'w_727',\n", + " 'w_728',\n", + " 'w_729',\n", + " 'w_730',\n", + " 'w_731',\n", + " 'w_732',\n", + " 'w_733',\n", + " 'w_734',\n", + " 'w_735',\n", + " 'w_736',\n", + " 'w_737',\n", + " 'w_738',\n", + " 'w_739',\n", + " 'w_740',\n", + " 'w_741',\n", + " 'w_742',\n", + " 'w_743',\n", + " 'w_744',\n", + " 'w_745',\n", + " 'w_746',\n", + " 'w_747',\n", + " 'w_748',\n", + " 'w_749',\n", + " 'w_750',\n", + " 'w_751',\n", + " 'w_752',\n", + " 'w_753',\n", + " 'w_754',\n", + " 'w_755',\n", + " 'w_756',\n", + " 'w_757',\n", + " 'w_758',\n", + " 'w_759',\n", + " 'w_760',\n", + " 'w_761',\n", + " 'w_762',\n", + " 'w_763',\n", + " 'w_764',\n", + " 'w_765',\n", + " 'w_766',\n", + " 'w_767',\n", + " 'w_768',\n", + " 'w_769',\n", + " 'w_770',\n", + " 'w_771',\n", + " 'w_772',\n", + " 'w_773',\n", + " 'w_774',\n", + " 'w_775',\n", + " 'w_776',\n", + " 'w_777',\n", + " 'w_778',\n", + " 'w_779',\n", + " 'w_780',\n", + " 'w_781',\n", + " 'w_782',\n", + " 'w_783',\n", + " 'w_784',\n", + " 'w_785',\n", + " 'w_786',\n", + " 'w_787',\n", + " 'w_788',\n", + " 'w_789',\n", + " 'w_790',\n", + " 'w_791',\n", + " 'w_792',\n", + " 'w_793',\n", + " 'w_794',\n", + " 'w_795',\n", + " 'w_796',\n", + " 'w_797',\n", + " 'w_798',\n", + " 'w_799',\n", + " 'w_800',\n", + " 'w_801',\n", + " 'w_802',\n", + " 'w_803',\n", + " 'w_804',\n", + " 'w_805',\n", + " 'w_806',\n", + " 'w_807',\n", + " 'w_808',\n", + " 'w_809',\n", + " 'w_810',\n", + " 'w_811',\n", + " 'w_812',\n", + " 'w_813',\n", + " 'w_814',\n", + " 'w_815',\n", + " 'w_816',\n", + " 'w_817',\n", + " 'w_818',\n", + " 'w_819',\n", + " 'w_820',\n", + " 'w_821',\n", + " 'w_822',\n", + " 'w_823',\n", + " 'w_824',\n", + " 'w_825',\n", + " 'w_826',\n", + " 'w_827',\n", + " 'w_828',\n", + " 'w_829',\n", + " 'w_830',\n", + " 'w_831',\n", + " 'w_832',\n", + " 'w_833',\n", + " 'w_834',\n", + " 'w_835',\n", + " 'w_836',\n", + " 'w_837',\n", + " 'w_838',\n", + " 'w_839',\n", + " 'w_840',\n", + " 'w_841',\n", + " 'w_842',\n", + " 'w_843',\n", + " 'w_844',\n", + " 'w_845',\n", + " 'w_846',\n", + " 'w_847',\n", + " 'w_848',\n", + " 'w_849',\n", + " 'w_850',\n", + " 'w_851',\n", + " 'w_852',\n", + " 'w_853',\n", + " 'w_854',\n", + " 'w_855',\n", + " 'w_856',\n", + " 'w_857',\n", + " 'w_858',\n", + " 'w_859',\n", + " 'w_860',\n", + " 'w_861',\n", + " 'w_862',\n", + " 'w_863',\n", + " 'w_864',\n", + " 'w_865',\n", + " 'w_866',\n", + " 'w_867',\n", + " 'w_868',\n", + " 'w_869',\n", + " 'w_870',\n", + " 'w_871',\n", + " 'w_872',\n", + " 'w_873',\n", + " 'w_874',\n", + " 'w_875',\n", + " 'w_876',\n", + " 'w_877',\n", + " 'w_878',\n", + " 'w_879',\n", + " 'w_880',\n", + " 'w_881',\n", + " 'w_882',\n", + " 'w_883',\n", + " 'w_884',\n", + " 'w_885',\n", + " 'w_886',\n", + " 'w_887',\n", + " 'w_888',\n", + " 'w_889',\n", + " 'w_890',\n", + " 'w_891',\n", + " 'w_892',\n", + " 'w_893',\n", + " 'w_894',\n", + " 'w_895',\n", + " 'w_896',\n", + " 'w_897',\n", + " 'w_898',\n", + " 'w_899',\n", + " 'w_900',\n", + " 'w_901',\n", + " 'w_902',\n", + " 'w_903',\n", + " 'w_904',\n", + " 'w_905',\n", + " 'w_906',\n", + " 'w_907',\n", + " 'w_908',\n", + " 'w_909',\n", + " 'w_910',\n", + " 'w_911',\n", + " 'w_912',\n", + " 'w_913',\n", + " 'w_914',\n", + " 'w_915',\n", + " 'w_916',\n", + " 'w_917',\n", + " 'w_918',\n", + " 'w_919',\n", + " 'w_920',\n", + " 'w_921',\n", + " 'w_922',\n", + " 'w_923',\n", + " 'w_924',\n", + " 'w_925',\n", + " 'w_926',\n", + " 'w_927',\n", + " 'w_928',\n", + " 'w_929',\n", + " 'w_930',\n", + " 'w_931',\n", + " 'w_932',\n", + " 'w_933',\n", + " 'w_934',\n", + " 'w_935',\n", + " 'w_936',\n", + " 'w_937',\n", + " 'w_938',\n", + " 'w_939',\n", + " 'w_940',\n", + " 'w_941',\n", + " 'w_942',\n", + " 'w_943',\n", + " 'w_944',\n", + " 'w_945',\n", + " 'w_946',\n", + " 'w_947',\n", + " 'w_948',\n", + " 'w_949',\n", + " 'w_950',\n", + " 'w_951',\n", + " 'w_952',\n", + " 'w_953',\n", + " 'w_954',\n", + " 'w_955',\n", + " 'w_956',\n", + " 'w_957',\n", + " 'w_958',\n", + " 'w_959',\n", + " 'w_960',\n", + " 'w_961',\n", + " 'w_962',\n", + " 'w_963',\n", + " 'w_964',\n", + " 'w_965',\n", + " 'w_966',\n", + " 'w_967',\n", + " 'w_968',\n", + " 'w_969',\n", + " 'w_970',\n", + " 'w_971',\n", + " 'w_972',\n", + " 'w_973',\n", + " 'w_974',\n", + " 'w_975',\n", + " 'w_976',\n", + " 'w_977',\n", + " 'w_978',\n", + " 'w_979',\n", + " 'w_980',\n", + " 'w_981',\n", + " 'w_982',\n", + " 'w_983',\n", + " 'w_984',\n", + " 'w_985',\n", + " 'w_986',\n", + " 'w_987',\n", + " 'w_988',\n", + " 'w_989',\n", + " 'w_990',\n", + " 'w_991',\n", + " 'w_992',\n", + " 'w_993',\n", + " 'w_994',\n", + " 'w_995',\n", + " 'w_996',\n", + " 'w_997',\n", + " 'w_998',\n", + " 'w_999',\n", + " ...],\n", + " : {: 'configuration',\n", + " : '/workspace/data/cora_preprocessed',\n", + " : 'paper'},\n", + " : {'gpu': True, 'verbose': False}}]}],\n", + " : [{: 'xgboost',\n", + " : ['cite'],\n", + " : {'paper': ['label']},\n", + " : {},\n", + " : {}}],\n", + " : '/workspace/data/cora_generated'}" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_generated_proper" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "0fb50f65", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_generated_random = synthesizer_random.generate()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "433b3201", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'cite',\n", + " 'count': 5428,\n", + " 'src_node_type': 'paper',\n", + " 'dst_node_type': 'paper',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'cite_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {'has_self_loop': False,\n", + " 'gpu': True,\n", + " 'verbose': False}}}],\n", + " : [{'name': 'paper',\n", + " 'count': 4095,\n", + " 'features': [{'name': 'w_0',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'},\n", + " {'name': 'w_1', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_2', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_3', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_4', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_5', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_6', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_7', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_8', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_9', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_10', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_11', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_12', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_13', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_14', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_15', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_16', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_17', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_18', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_19', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_20', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_21', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_22', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_23', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_24', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_25', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_26', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_27', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_28', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_29', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_30', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_31', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_32', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_33', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_34', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_35', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_36', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_37', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_38', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_39', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_40', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_41', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_42', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_43', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_44', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_45', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_46', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_47', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_48', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_49', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_50', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_51', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_52', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_53', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_54', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_55', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_56', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_57', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_58', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_59', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_60', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_61', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_62', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_63', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_64', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_65', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_66', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_67', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_68', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_69', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_70', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_71', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_72', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_73', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_74', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_75', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_76', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_77', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_78', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_79', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_80', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_81', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_82', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_83', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_84', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_85', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_86', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_87', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_88', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_89', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_90', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_91', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_92', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_93', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_94', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_95', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_96', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_97', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_98', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_99', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_100', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_101', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_102', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_103', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_104', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_105', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_106', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_107', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_108', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_109', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_110', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_111', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_112', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_113', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_114', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_115', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_116', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_117', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_118', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_119', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_120', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_121', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_122', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_123', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_124', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_125', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_126', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_127', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_128', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_129', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_130', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_131', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_132', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_133', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_134', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_135', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_136', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_137', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_138', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_139', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_140', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_141', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_142', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_143', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_144', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_145', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_146', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_147', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_148', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_149', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_150', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_151', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_152', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_153', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_154', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_155', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_156', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_157', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_158', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_159', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_160', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_161', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_162', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_163', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_164', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_165', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_166', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_167', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_168', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_169', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_170', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_171', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_172', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_173', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_174', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_175', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_176', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_177', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_178', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_179', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_180', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_181', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_182', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_183', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_184', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_185', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_186', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_187', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_188', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_189', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_190', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_191', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_192', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_193', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_194', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_195', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_196', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_197', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_198', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_199', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_200', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_201', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_202', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_203', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_204', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_205', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_206', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_207', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_208', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_209', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_210', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_211', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_212', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_213', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_214', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_215', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_216', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_217', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_218', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_219', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_220', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_221', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_222', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_223', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_224', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_225', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_226', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_227', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_228', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_229', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_230', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_231', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_232', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_233', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_234', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_235', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_236', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_237', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_238', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_239', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_240', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_241', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_242', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_243', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_244', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_245', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_246', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_247', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_248', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_249', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_250', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_251', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_252', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_253', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_254', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_255', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_256', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_257', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_258', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_259', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_260', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_261', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_262', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_263', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_264', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_265', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_266', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_267', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_268', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_269', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_270', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_271', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_272', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_273', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_274', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_275', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_276', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_277', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_278', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_279', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_280', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_281', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_282', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_283', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_284', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_285', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_286', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_287', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_288', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_289', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_290', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_291', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_292', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_293', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_294', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_295', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_296', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_297', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_298', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_299', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_300', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_301', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_302', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_303', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_304', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_305', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_306', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_307', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_308', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_309', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_310', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_311', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_312', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_313', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_314', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_315', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_316', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_317', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_318', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_319', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_320', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_321', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_322', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_323', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_324', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_325', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_326', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_327', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_328', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_329', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_330', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_331', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_332', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_333', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_334', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_335', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_336', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_337', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_338', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_339', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_340', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_341', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_342', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_343', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_344', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_345', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_346', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_347', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_348', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_349', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_350', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_351', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_352', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_353', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_354', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_355', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_356', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_357', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_358', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_359', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_360', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_361', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_362', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_363', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_364', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_365', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_366', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_367', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_368', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_369', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_370', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_371', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_372', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_373', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_374', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_375', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_376', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_377', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_378', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_379', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_380', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_381', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_382', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_383', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_384', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_385', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_386', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_387', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_388', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_389', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_390', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_391', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_392', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_393', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_394', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_395', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_396', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_397', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_398', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_399', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_400', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_401', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_402', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_403', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_404', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_405', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_406', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_407', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_408', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_409', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_410', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_411', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_412', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_413', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_414', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_415', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_416', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_417', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_418', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_419', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_420', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_421', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_422', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_423', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_424', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_425', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_426', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_427', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_428', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_429', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_430', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_431', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_432', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_433', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_434', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_435', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_436', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_437', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_438', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_439', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_440', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_441', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_442', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_443', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_444', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_445', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_446', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_447', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_448', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_449', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_450', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_451', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_452', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_453', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_454', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_455', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_456', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_457', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_458', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_459', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_460', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_461', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_462', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_463', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_464', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_465', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_466', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_467', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_468', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_469', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_470', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_471', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_472', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_473', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_474', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_475', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_476', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_477', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_478', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_479', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_480', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_481', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_482', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_483', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_484', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_485', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_486', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_487', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_488', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_489', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_490', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_491', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_492', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_493', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_494', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_495', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_496', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_497', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_498', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_499', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_500', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_501', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_502', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_503', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_504', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_505', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_506', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_507', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_508', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_509', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_510', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_511', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_512', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_513', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_514', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_515', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_516', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_517', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_518', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_519', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_520', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_521', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_522', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_523', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_524', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_525', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_526', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_527', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_528', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_529', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_530', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_531', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_532', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_533', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_534', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_535', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_536', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_537', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_538', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_539', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_540', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_541', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_542', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_543', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_544', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_545', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_546', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_547', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_548', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_549', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_550', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_551', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_552', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_553', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_554', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_555', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_556', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_557', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_558', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_559', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_560', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_561', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_562', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_563', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_564', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_565', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_566', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_567', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_568', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_569', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_570', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_571', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_572', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_573', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_574', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_575', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_576', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_577', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_578', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_579', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_580', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_581', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_582', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_583', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_584', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_585', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_586', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_587', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_588', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_589', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_590', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_591', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_592', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_593', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_594', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_595', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_596', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_597', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_598', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_599', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_600', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_601', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_602', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_603', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_604', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_605', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_606', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_607', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_608', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_609', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_610', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_611', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_612', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_613', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_614', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_615', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_616', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_617', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_618', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_619', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_620', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_621', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_622', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_623', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_624', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_625', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_626', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_627', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_628', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_629', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_630', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_631', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_632', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_633', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_634', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_635', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_636', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_637', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_638', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_639', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_640', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_641', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_642', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_643', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_644', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_645', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_646', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_647', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_648', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_649', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_650', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_651', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_652', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_653', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_654', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_655', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_656', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_657', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_658', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_659', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_660', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_661', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_662', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_663', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_664', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_665', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_666', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_667', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_668', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_669', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_670', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_671', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_672', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_673', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_674', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_675', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_676', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_677', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_678', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_679', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_680', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_681', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_682', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_683', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_684', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_685', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_686', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_687', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_688', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_689', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_690', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_691', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_692', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_693', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_694', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_695', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_696', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_697', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_698', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_699', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_700', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_701', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_702', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_703', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_704', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_705', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_706', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_707', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_708', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_709', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_710', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_711', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_712', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_713', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_714', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_715', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_716', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_717', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_718', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_719', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_720', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_721', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_722', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_723', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_724', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_725', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_726', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_727', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_728', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_729', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_730', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_731', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_732', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_733', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_734', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_735', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_736', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_737', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_738', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_739', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_740', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_741', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_742', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_743', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_744', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_745', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_746', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_747', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_748', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_749', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_750', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_751', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_752', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_753', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_754', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_755', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_756', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_757', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_758', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_759', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_760', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_761', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_762', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_763', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_764', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_765', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_766', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_767', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_768', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_769', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_770', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_771', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_772', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_773', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_774', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_775', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_776', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_777', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_778', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_779', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_780', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_781', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_782', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_783', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_784', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_785', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_786', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_787', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_788', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_789', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_790', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_791', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_792', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_793', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_794', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_795', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_796', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_797', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_798', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_799', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_800', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_801', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_802', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_803', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_804', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_805', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_806', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_807', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_808', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_809', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_810', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_811', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_812', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_813', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_814', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_815', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_816', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_817', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_818', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_819', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_820', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_821', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_822', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_823', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_824', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_825', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_826', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_827', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_828', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_829', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_830', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_831', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_832', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_833', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_834', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_835', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_836', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_837', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_838', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_839', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_840', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_841', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_842', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_843', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_844', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_845', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_846', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_847', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_848', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_849', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_850', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_851', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_852', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_853', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_854', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_855', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_856', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_857', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_858', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_859', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_860', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_861', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_862', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_863', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_864', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_865', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_866', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_867', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_868', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_869', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_870', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_871', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_872', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_873', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_874', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_875', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_876', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_877', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_878', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_879', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_880', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_881', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_882', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_883', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_884', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_885', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_886', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_887', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_888', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_889', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_890', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_891', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_892', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_893', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_894', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_895', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_896', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_897', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_898', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_899', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_900', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_901', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_902', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_903', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_904', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_905', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_906', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_907', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_908', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_909', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_910', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_911', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_912', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_913', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_914', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_915', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_916', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_917', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_918', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_919', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_920', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_921', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_922', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_923', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_924', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_925', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_926', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_927', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_928', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_929', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_930', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_931', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_932', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_933', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_934', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_935', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_936', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_937', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_938', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_939', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_940', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_941', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_942', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_943', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_944', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_945', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_946', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_947', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_948', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_949', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_950', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_951', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_952', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_953', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_954', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_955', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_956', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_957', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_958', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_959', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_960', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_961', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_962', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_963', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_964', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_965', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_966', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_967', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_968', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_969', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_970', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_971', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_972', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_973', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_974', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_975', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_976', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_977', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_978', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_979', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_980', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_981', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_982', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_983', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_984', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_985', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_986', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_987', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_988', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_989', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_990', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_991', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_992', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_993', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_994', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_995', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_996', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_997', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_998', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " {'name': 'w_999', 'dtype': 'int64', 'feature_type': 'categorical'},\n", + " ...],\n", + " 'features_path': 'paper.parquet',\n", + " : [{: 'random',\n", + " : ['w_0',\n", + " 'w_1',\n", + " 'w_2',\n", + " 'w_3',\n", + " 'w_4',\n", + " 'w_5',\n", + " 'w_6',\n", + " 'w_7',\n", + " 'w_8',\n", + " 'w_9',\n", + " 'w_10',\n", + " 'w_11',\n", + " 'w_12',\n", + " 'w_13',\n", + " 'w_14',\n", + " 'w_15',\n", + " 'w_16',\n", + " 'w_17',\n", + " 'w_18',\n", + " 'w_19',\n", + " 'w_20',\n", + " 'w_21',\n", + " 'w_22',\n", + " 'w_23',\n", + " 'w_24',\n", + " 'w_25',\n", + " 'w_26',\n", + " 'w_27',\n", + " 'w_28',\n", + " 'w_29',\n", + " 'w_30',\n", + " 'w_31',\n", + " 'w_32',\n", + " 'w_33',\n", + " 'w_34',\n", + " 'w_35',\n", + " 'w_36',\n", + " 'w_37',\n", + " 'w_38',\n", + " 'w_39',\n", + " 'w_40',\n", + " 'w_41',\n", + " 'w_42',\n", + " 'w_43',\n", + " 'w_44',\n", + " 'w_45',\n", + " 'w_46',\n", + " 'w_47',\n", + " 'w_48',\n", + " 'w_49',\n", + " 'w_50',\n", + " 'w_51',\n", + " 'w_52',\n", + " 'w_53',\n", + " 'w_54',\n", + " 'w_55',\n", + " 'w_56',\n", + " 'w_57',\n", + " 'w_58',\n", + " 'w_59',\n", + " 'w_60',\n", + " 'w_61',\n", + " 'w_62',\n", + " 'w_63',\n", + " 'w_64',\n", + " 'w_65',\n", + " 'w_66',\n", + " 'w_67',\n", + " 'w_68',\n", + " 'w_69',\n", + " 'w_70',\n", + " 'w_71',\n", + " 'w_72',\n", + " 'w_73',\n", + " 'w_74',\n", + " 'w_75',\n", + " 'w_76',\n", + " 'w_77',\n", + " 'w_78',\n", + " 'w_79',\n", + " 'w_80',\n", + " 'w_81',\n", + " 'w_82',\n", + " 'w_83',\n", + " 'w_84',\n", + " 'w_85',\n", + " 'w_86',\n", + " 'w_87',\n", + " 'w_88',\n", + " 'w_89',\n", + " 'w_90',\n", + " 'w_91',\n", + " 'w_92',\n", + " 'w_93',\n", + " 'w_94',\n", + " 'w_95',\n", + " 'w_96',\n", + " 'w_97',\n", + " 'w_98',\n", + " 'w_99',\n", + " 'w_100',\n", + " 'w_101',\n", + " 'w_102',\n", + " 'w_103',\n", + " 'w_104',\n", + " 'w_105',\n", + " 'w_106',\n", + " 'w_107',\n", + " 'w_108',\n", + " 'w_109',\n", + " 'w_110',\n", + " 'w_111',\n", + " 'w_112',\n", + " 'w_113',\n", + " 'w_114',\n", + " 'w_115',\n", + " 'w_116',\n", + " 'w_117',\n", + " 'w_118',\n", + " 'w_119',\n", + " 'w_120',\n", + " 'w_121',\n", + " 'w_122',\n", + " 'w_123',\n", + " 'w_124',\n", + " 'w_125',\n", + " 'w_126',\n", + " 'w_127',\n", + " 'w_128',\n", + " 'w_129',\n", + " 'w_130',\n", + " 'w_131',\n", + " 'w_132',\n", + " 'w_133',\n", + " 'w_134',\n", + " 'w_135',\n", + " 'w_136',\n", + " 'w_137',\n", + " 'w_138',\n", + " 'w_139',\n", + " 'w_140',\n", + " 'w_141',\n", + " 'w_142',\n", + " 'w_143',\n", + " 'w_144',\n", + " 'w_145',\n", + " 'w_146',\n", + " 'w_147',\n", + " 'w_148',\n", + " 'w_149',\n", + " 'w_150',\n", + " 'w_151',\n", + " 'w_152',\n", + " 'w_153',\n", + " 'w_154',\n", + " 'w_155',\n", + " 'w_156',\n", + " 'w_157',\n", + " 'w_158',\n", + " 'w_159',\n", + " 'w_160',\n", + " 'w_161',\n", + " 'w_162',\n", + " 'w_163',\n", + " 'w_164',\n", + " 'w_165',\n", + " 'w_166',\n", + " 'w_167',\n", + " 'w_168',\n", + " 'w_169',\n", + " 'w_170',\n", + " 'w_171',\n", + " 'w_172',\n", + " 'w_173',\n", + " 'w_174',\n", + " 'w_175',\n", + " 'w_176',\n", + " 'w_177',\n", + " 'w_178',\n", + " 'w_179',\n", + " 'w_180',\n", + " 'w_181',\n", + " 'w_182',\n", + " 'w_183',\n", + " 'w_184',\n", + " 'w_185',\n", + " 'w_186',\n", + " 'w_187',\n", + " 'w_188',\n", + " 'w_189',\n", + " 'w_190',\n", + " 'w_191',\n", + " 'w_192',\n", + " 'w_193',\n", + " 'w_194',\n", + " 'w_195',\n", + " 'w_196',\n", + " 'w_197',\n", + " 'w_198',\n", + " 'w_199',\n", + " 'w_200',\n", + " 'w_201',\n", + " 'w_202',\n", + " 'w_203',\n", + " 'w_204',\n", + " 'w_205',\n", + " 'w_206',\n", + " 'w_207',\n", + " 'w_208',\n", + " 'w_209',\n", + " 'w_210',\n", + " 'w_211',\n", + " 'w_212',\n", + " 'w_213',\n", + " 'w_214',\n", + " 'w_215',\n", + " 'w_216',\n", + " 'w_217',\n", + " 'w_218',\n", + " 'w_219',\n", + " 'w_220',\n", + " 'w_221',\n", + " 'w_222',\n", + " 'w_223',\n", + " 'w_224',\n", + " 'w_225',\n", + " 'w_226',\n", + " 'w_227',\n", + " 'w_228',\n", + " 'w_229',\n", + " 'w_230',\n", + " 'w_231',\n", + " 'w_232',\n", + " 'w_233',\n", + " 'w_234',\n", + " 'w_235',\n", + " 'w_236',\n", + " 'w_237',\n", + " 'w_238',\n", + " 'w_239',\n", + " 'w_240',\n", + " 'w_241',\n", + " 'w_242',\n", + " 'w_243',\n", + " 'w_244',\n", + " 'w_245',\n", + " 'w_246',\n", + " 'w_247',\n", + " 'w_248',\n", + " 'w_249',\n", + " 'w_250',\n", + " 'w_251',\n", + " 'w_252',\n", + " 'w_253',\n", + " 'w_254',\n", + " 'w_255',\n", + " 'w_256',\n", + " 'w_257',\n", + " 'w_258',\n", + " 'w_259',\n", + " 'w_260',\n", + " 'w_261',\n", + " 'w_262',\n", + " 'w_263',\n", + " 'w_264',\n", + " 'w_265',\n", + " 'w_266',\n", + " 'w_267',\n", + " 'w_268',\n", + " 'w_269',\n", + " 'w_270',\n", + " 'w_271',\n", + " 'w_272',\n", + " 'w_273',\n", + " 'w_274',\n", + " 'w_275',\n", + " 'w_276',\n", + " 'w_277',\n", + " 'w_278',\n", + " 'w_279',\n", + " 'w_280',\n", + " 'w_281',\n", + " 'w_282',\n", + " 'w_283',\n", + " 'w_284',\n", + " 'w_285',\n", + " 'w_286',\n", + " 'w_287',\n", + " 'w_288',\n", + " 'w_289',\n", + " 'w_290',\n", + " 'w_291',\n", + " 'w_292',\n", + " 'w_293',\n", + " 'w_294',\n", + " 'w_295',\n", + " 'w_296',\n", + " 'w_297',\n", + " 'w_298',\n", + " 'w_299',\n", + " 'w_300',\n", + " 'w_301',\n", + " 'w_302',\n", + " 'w_303',\n", + " 'w_304',\n", + " 'w_305',\n", + " 'w_306',\n", + " 'w_307',\n", + " 'w_308',\n", + " 'w_309',\n", + " 'w_310',\n", + " 'w_311',\n", + " 'w_312',\n", + " 'w_313',\n", + " 'w_314',\n", + " 'w_315',\n", + " 'w_316',\n", + " 'w_317',\n", + " 'w_318',\n", + " 'w_319',\n", + " 'w_320',\n", + " 'w_321',\n", + " 'w_322',\n", + " 'w_323',\n", + " 'w_324',\n", + " 'w_325',\n", + " 'w_326',\n", + " 'w_327',\n", + " 'w_328',\n", + " 'w_329',\n", + " 'w_330',\n", + " 'w_331',\n", + " 'w_332',\n", + " 'w_333',\n", + " 'w_334',\n", + " 'w_335',\n", + " 'w_336',\n", + " 'w_337',\n", + " 'w_338',\n", + " 'w_339',\n", + " 'w_340',\n", + " 'w_341',\n", + " 'w_342',\n", + " 'w_343',\n", + " 'w_344',\n", + " 'w_345',\n", + " 'w_346',\n", + " 'w_347',\n", + " 'w_348',\n", + " 'w_349',\n", + " 'w_350',\n", + " 'w_351',\n", + " 'w_352',\n", + " 'w_353',\n", + " 'w_354',\n", + " 'w_355',\n", + " 'w_356',\n", + " 'w_357',\n", + " 'w_358',\n", + " 'w_359',\n", + " 'w_360',\n", + " 'w_361',\n", + " 'w_362',\n", + " 'w_363',\n", + " 'w_364',\n", + " 'w_365',\n", + " 'w_366',\n", + " 'w_367',\n", + " 'w_368',\n", + " 'w_369',\n", + " 'w_370',\n", + " 'w_371',\n", + " 'w_372',\n", + " 'w_373',\n", + " 'w_374',\n", + " 'w_375',\n", + " 'w_376',\n", + " 'w_377',\n", + " 'w_378',\n", + " 'w_379',\n", + " 'w_380',\n", + " 'w_381',\n", + " 'w_382',\n", + " 'w_383',\n", + " 'w_384',\n", + " 'w_385',\n", + " 'w_386',\n", + " 'w_387',\n", + " 'w_388',\n", + " 'w_389',\n", + " 'w_390',\n", + " 'w_391',\n", + " 'w_392',\n", + " 'w_393',\n", + " 'w_394',\n", + " 'w_395',\n", + " 'w_396',\n", + " 'w_397',\n", + " 'w_398',\n", + " 'w_399',\n", + " 'w_400',\n", + " 'w_401',\n", + " 'w_402',\n", + " 'w_403',\n", + " 'w_404',\n", + " 'w_405',\n", + " 'w_406',\n", + " 'w_407',\n", + " 'w_408',\n", + " 'w_409',\n", + " 'w_410',\n", + " 'w_411',\n", + " 'w_412',\n", + " 'w_413',\n", + " 'w_414',\n", + " 'w_415',\n", + " 'w_416',\n", + " 'w_417',\n", + " 'w_418',\n", + " 'w_419',\n", + " 'w_420',\n", + " 'w_421',\n", + " 'w_422',\n", + " 'w_423',\n", + " 'w_424',\n", + " 'w_425',\n", + " 'w_426',\n", + " 'w_427',\n", + " 'w_428',\n", + " 'w_429',\n", + " 'w_430',\n", + " 'w_431',\n", + " 'w_432',\n", + " 'w_433',\n", + " 'w_434',\n", + " 'w_435',\n", + " 'w_436',\n", + " 'w_437',\n", + " 'w_438',\n", + " 'w_439',\n", + " 'w_440',\n", + " 'w_441',\n", + " 'w_442',\n", + " 'w_443',\n", + " 'w_444',\n", + " 'w_445',\n", + " 'w_446',\n", + " 'w_447',\n", + " 'w_448',\n", + " 'w_449',\n", + " 'w_450',\n", + " 'w_451',\n", + " 'w_452',\n", + " 'w_453',\n", + " 'w_454',\n", + " 'w_455',\n", + " 'w_456',\n", + " 'w_457',\n", + " 'w_458',\n", + " 'w_459',\n", + " 'w_460',\n", + " 'w_461',\n", + " 'w_462',\n", + " 'w_463',\n", + " 'w_464',\n", + " 'w_465',\n", + " 'w_466',\n", + " 'w_467',\n", + " 'w_468',\n", + " 'w_469',\n", + " 'w_470',\n", + " 'w_471',\n", + " 'w_472',\n", + " 'w_473',\n", + " 'w_474',\n", + " 'w_475',\n", + " 'w_476',\n", + " 'w_477',\n", + " 'w_478',\n", + " 'w_479',\n", + " 'w_480',\n", + " 'w_481',\n", + " 'w_482',\n", + " 'w_483',\n", + " 'w_484',\n", + " 'w_485',\n", + " 'w_486',\n", + " 'w_487',\n", + " 'w_488',\n", + " 'w_489',\n", + " 'w_490',\n", + " 'w_491',\n", + " 'w_492',\n", + " 'w_493',\n", + " 'w_494',\n", + " 'w_495',\n", + " 'w_496',\n", + " 'w_497',\n", + " 'w_498',\n", + " 'w_499',\n", + " 'w_500',\n", + " 'w_501',\n", + " 'w_502',\n", + " 'w_503',\n", + " 'w_504',\n", + " 'w_505',\n", + " 'w_506',\n", + " 'w_507',\n", + " 'w_508',\n", + " 'w_509',\n", + " 'w_510',\n", + " 'w_511',\n", + " 'w_512',\n", + " 'w_513',\n", + " 'w_514',\n", + " 'w_515',\n", + " 'w_516',\n", + " 'w_517',\n", + " 'w_518',\n", + " 'w_519',\n", + " 'w_520',\n", + " 'w_521',\n", + " 'w_522',\n", + " 'w_523',\n", + " 'w_524',\n", + " 'w_525',\n", + " 'w_526',\n", + " 'w_527',\n", + " 'w_528',\n", + " 'w_529',\n", + " 'w_530',\n", + " 'w_531',\n", + " 'w_532',\n", + " 'w_533',\n", + " 'w_534',\n", + " 'w_535',\n", + " 'w_536',\n", + " 'w_537',\n", + " 'w_538',\n", + " 'w_539',\n", + " 'w_540',\n", + " 'w_541',\n", + " 'w_542',\n", + " 'w_543',\n", + " 'w_544',\n", + " 'w_545',\n", + " 'w_546',\n", + " 'w_547',\n", + " 'w_548',\n", + " 'w_549',\n", + " 'w_550',\n", + " 'w_551',\n", + " 'w_552',\n", + " 'w_553',\n", + " 'w_554',\n", + " 'w_555',\n", + " 'w_556',\n", + " 'w_557',\n", + " 'w_558',\n", + " 'w_559',\n", + " 'w_560',\n", + " 'w_561',\n", + " 'w_562',\n", + " 'w_563',\n", + " 'w_564',\n", + " 'w_565',\n", + " 'w_566',\n", + " 'w_567',\n", + " 'w_568',\n", + " 'w_569',\n", + " 'w_570',\n", + " 'w_571',\n", + " 'w_572',\n", + " 'w_573',\n", + " 'w_574',\n", + " 'w_575',\n", + " 'w_576',\n", + " 'w_577',\n", + " 'w_578',\n", + " 'w_579',\n", + " 'w_580',\n", + " 'w_581',\n", + " 'w_582',\n", + " 'w_583',\n", + " 'w_584',\n", + " 'w_585',\n", + " 'w_586',\n", + " 'w_587',\n", + " 'w_588',\n", + " 'w_589',\n", + " 'w_590',\n", + " 'w_591',\n", + " 'w_592',\n", + " 'w_593',\n", + " 'w_594',\n", + " 'w_595',\n", + " 'w_596',\n", + " 'w_597',\n", + " 'w_598',\n", + " 'w_599',\n", + " 'w_600',\n", + " 'w_601',\n", + " 'w_602',\n", + " 'w_603',\n", + " 'w_604',\n", + " 'w_605',\n", + " 'w_606',\n", + " 'w_607',\n", + " 'w_608',\n", + " 'w_609',\n", + " 'w_610',\n", + " 'w_611',\n", + " 'w_612',\n", + " 'w_613',\n", + " 'w_614',\n", + " 'w_615',\n", + " 'w_616',\n", + " 'w_617',\n", + " 'w_618',\n", + " 'w_619',\n", + " 'w_620',\n", + " 'w_621',\n", + " 'w_622',\n", + " 'w_623',\n", + " 'w_624',\n", + " 'w_625',\n", + " 'w_626',\n", + " 'w_627',\n", + " 'w_628',\n", + " 'w_629',\n", + " 'w_630',\n", + " 'w_631',\n", + " 'w_632',\n", + " 'w_633',\n", + " 'w_634',\n", + " 'w_635',\n", + " 'w_636',\n", + " 'w_637',\n", + " 'w_638',\n", + " 'w_639',\n", + " 'w_640',\n", + " 'w_641',\n", + " 'w_642',\n", + " 'w_643',\n", + " 'w_644',\n", + " 'w_645',\n", + " 'w_646',\n", + " 'w_647',\n", + " 'w_648',\n", + " 'w_649',\n", + " 'w_650',\n", + " 'w_651',\n", + " 'w_652',\n", + " 'w_653',\n", + " 'w_654',\n", + " 'w_655',\n", + " 'w_656',\n", + " 'w_657',\n", + " 'w_658',\n", + " 'w_659',\n", + " 'w_660',\n", + " 'w_661',\n", + " 'w_662',\n", + " 'w_663',\n", + " 'w_664',\n", + " 'w_665',\n", + " 'w_666',\n", + " 'w_667',\n", + " 'w_668',\n", + " 'w_669',\n", + " 'w_670',\n", + " 'w_671',\n", + " 'w_672',\n", + " 'w_673',\n", + " 'w_674',\n", + " 'w_675',\n", + " 'w_676',\n", + " 'w_677',\n", + " 'w_678',\n", + " 'w_679',\n", + " 'w_680',\n", + " 'w_681',\n", + " 'w_682',\n", + " 'w_683',\n", + " 'w_684',\n", + " 'w_685',\n", + " 'w_686',\n", + " 'w_687',\n", + " 'w_688',\n", + " 'w_689',\n", + " 'w_690',\n", + " 'w_691',\n", + " 'w_692',\n", + " 'w_693',\n", + " 'w_694',\n", + " 'w_695',\n", + " 'w_696',\n", + " 'w_697',\n", + " 'w_698',\n", + " 'w_699',\n", + " 'w_700',\n", + " 'w_701',\n", + " 'w_702',\n", + " 'w_703',\n", + " 'w_704',\n", + " 'w_705',\n", + " 'w_706',\n", + " 'w_707',\n", + " 'w_708',\n", + " 'w_709',\n", + " 'w_710',\n", + " 'w_711',\n", + " 'w_712',\n", + " 'w_713',\n", + " 'w_714',\n", + " 'w_715',\n", + " 'w_716',\n", + " 'w_717',\n", + " 'w_718',\n", + " 'w_719',\n", + " 'w_720',\n", + " 'w_721',\n", + " 'w_722',\n", + " 'w_723',\n", + " 'w_724',\n", + " 'w_725',\n", + " 'w_726',\n", + " 'w_727',\n", + " 'w_728',\n", + " 'w_729',\n", + " 'w_730',\n", + " 'w_731',\n", + " 'w_732',\n", + " 'w_733',\n", + " 'w_734',\n", + " 'w_735',\n", + " 'w_736',\n", + " 'w_737',\n", + " 'w_738',\n", + " 'w_739',\n", + " 'w_740',\n", + " 'w_741',\n", + " 'w_742',\n", + " 'w_743',\n", + " 'w_744',\n", + " 'w_745',\n", + " 'w_746',\n", + " 'w_747',\n", + " 'w_748',\n", + " 'w_749',\n", + " 'w_750',\n", + " 'w_751',\n", + " 'w_752',\n", + " 'w_753',\n", + " 'w_754',\n", + " 'w_755',\n", + " 'w_756',\n", + " 'w_757',\n", + " 'w_758',\n", + " 'w_759',\n", + " 'w_760',\n", + " 'w_761',\n", + " 'w_762',\n", + " 'w_763',\n", + " 'w_764',\n", + " 'w_765',\n", + " 'w_766',\n", + " 'w_767',\n", + " 'w_768',\n", + " 'w_769',\n", + " 'w_770',\n", + " 'w_771',\n", + " 'w_772',\n", + " 'w_773',\n", + " 'w_774',\n", + " 'w_775',\n", + " 'w_776',\n", + " 'w_777',\n", + " 'w_778',\n", + " 'w_779',\n", + " 'w_780',\n", + " 'w_781',\n", + " 'w_782',\n", + " 'w_783',\n", + " 'w_784',\n", + " 'w_785',\n", + " 'w_786',\n", + " 'w_787',\n", + " 'w_788',\n", + " 'w_789',\n", + " 'w_790',\n", + " 'w_791',\n", + " 'w_792',\n", + " 'w_793',\n", + " 'w_794',\n", + " 'w_795',\n", + " 'w_796',\n", + " 'w_797',\n", + " 'w_798',\n", + " 'w_799',\n", + " 'w_800',\n", + " 'w_801',\n", + " 'w_802',\n", + " 'w_803',\n", + " 'w_804',\n", + " 'w_805',\n", + " 'w_806',\n", + " 'w_807',\n", + " 'w_808',\n", + " 'w_809',\n", + " 'w_810',\n", + " 'w_811',\n", + " 'w_812',\n", + " 'w_813',\n", + " 'w_814',\n", + " 'w_815',\n", + " 'w_816',\n", + " 'w_817',\n", + " 'w_818',\n", + " 'w_819',\n", + " 'w_820',\n", + " 'w_821',\n", + " 'w_822',\n", + " 'w_823',\n", + " 'w_824',\n", + " 'w_825',\n", + " 'w_826',\n", + " 'w_827',\n", + " 'w_828',\n", + " 'w_829',\n", + " 'w_830',\n", + " 'w_831',\n", + " 'w_832',\n", + " 'w_833',\n", + " 'w_834',\n", + " 'w_835',\n", + " 'w_836',\n", + " 'w_837',\n", + " 'w_838',\n", + " 'w_839',\n", + " 'w_840',\n", + " 'w_841',\n", + " 'w_842',\n", + " 'w_843',\n", + " 'w_844',\n", + " 'w_845',\n", + " 'w_846',\n", + " 'w_847',\n", + " 'w_848',\n", + " 'w_849',\n", + " 'w_850',\n", + " 'w_851',\n", + " 'w_852',\n", + " 'w_853',\n", + " 'w_854',\n", + " 'w_855',\n", + " 'w_856',\n", + " 'w_857',\n", + " 'w_858',\n", + " 'w_859',\n", + " 'w_860',\n", + " 'w_861',\n", + " 'w_862',\n", + " 'w_863',\n", + " 'w_864',\n", + " 'w_865',\n", + " 'w_866',\n", + " 'w_867',\n", + " 'w_868',\n", + " 'w_869',\n", + " 'w_870',\n", + " 'w_871',\n", + " 'w_872',\n", + " 'w_873',\n", + " 'w_874',\n", + " 'w_875',\n", + " 'w_876',\n", + " 'w_877',\n", + " 'w_878',\n", + " 'w_879',\n", + " 'w_880',\n", + " 'w_881',\n", + " 'w_882',\n", + " 'w_883',\n", + " 'w_884',\n", + " 'w_885',\n", + " 'w_886',\n", + " 'w_887',\n", + " 'w_888',\n", + " 'w_889',\n", + " 'w_890',\n", + " 'w_891',\n", + " 'w_892',\n", + " 'w_893',\n", + " 'w_894',\n", + " 'w_895',\n", + " 'w_896',\n", + " 'w_897',\n", + " 'w_898',\n", + " 'w_899',\n", + " 'w_900',\n", + " 'w_901',\n", + " 'w_902',\n", + " 'w_903',\n", + " 'w_904',\n", + " 'w_905',\n", + " 'w_906',\n", + " 'w_907',\n", + " 'w_908',\n", + " 'w_909',\n", + " 'w_910',\n", + " 'w_911',\n", + " 'w_912',\n", + " 'w_913',\n", + " 'w_914',\n", + " 'w_915',\n", + " 'w_916',\n", + " 'w_917',\n", + " 'w_918',\n", + " 'w_919',\n", + " 'w_920',\n", + " 'w_921',\n", + " 'w_922',\n", + " 'w_923',\n", + " 'w_924',\n", + " 'w_925',\n", + " 'w_926',\n", + " 'w_927',\n", + " 'w_928',\n", + " 'w_929',\n", + " 'w_930',\n", + " 'w_931',\n", + " 'w_932',\n", + " 'w_933',\n", + " 'w_934',\n", + " 'w_935',\n", + " 'w_936',\n", + " 'w_937',\n", + " 'w_938',\n", + " 'w_939',\n", + " 'w_940',\n", + " 'w_941',\n", + " 'w_942',\n", + " 'w_943',\n", + " 'w_944',\n", + " 'w_945',\n", + " 'w_946',\n", + " 'w_947',\n", + " 'w_948',\n", + " 'w_949',\n", + " 'w_950',\n", + " 'w_951',\n", + " 'w_952',\n", + " 'w_953',\n", + " 'w_954',\n", + " 'w_955',\n", + " 'w_956',\n", + " 'w_957',\n", + " 'w_958',\n", + " 'w_959',\n", + " 'w_960',\n", + " 'w_961',\n", + " 'w_962',\n", + " 'w_963',\n", + " 'w_964',\n", + " 'w_965',\n", + " 'w_966',\n", + " 'w_967',\n", + " 'w_968',\n", + " 'w_969',\n", + " 'w_970',\n", + " 'w_971',\n", + " 'w_972',\n", + " 'w_973',\n", + " 'w_974',\n", + " 'w_975',\n", + " 'w_976',\n", + " 'w_977',\n", + " 'w_978',\n", + " 'w_979',\n", + " 'w_980',\n", + " 'w_981',\n", + " 'w_982',\n", + " 'w_983',\n", + " 'w_984',\n", + " 'w_985',\n", + " 'w_986',\n", + " 'w_987',\n", + " 'w_988',\n", + " 'w_989',\n", + " 'w_990',\n", + " 'w_991',\n", + " 'w_992',\n", + " 'w_993',\n", + " 'w_994',\n", + " 'w_995',\n", + " 'w_996',\n", + " 'w_997',\n", + " 'w_998',\n", + " 'w_999',\n", + " ...],\n", + " : {: 'random'},\n", + " : {'gpu': True, 'verbose': False}}]}],\n", + " : '/workspace/data/cora_random'}" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_generated_random" + ] + }, + { + "cell_type": "markdown", + "id": "52498035", + "metadata": {}, + "source": [ + "\n", + "## Tabular Data Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "4b2eebc8", + "metadata": {}, + "outputs": [], + "source": [ + "original_tabular_data, categorical_features = feature_spec_original.get_tabular_data(MetaData.NODES, 'paper', return_cat_feats=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "5aff1998", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "proper_tabular_data = feature_spec_generated_proper.get_tabular_data(MetaData.NODES, 'paper')" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "cd5320e5", + "metadata": {}, + "outputs": [], + "source": [ + "random_tabular_data = feature_spec_generated_random.get_tabular_data(MetaData.NODES, 'paper')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "b013d2e3", + "metadata": {}, + "outputs": [], + "source": [ + "tab_eval = TabularMetrics(original_tabular_data, \n", + " proper_tabular_data, \n", + " categorical_columns=categorical_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "3f1026ef", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tab_eval.plot_pca()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "ae27d10f", + "metadata": {}, + "outputs": [], + "source": [ + "tab_eval = TabularMetrics(original_tabular_data, \n", + " random_tabular_data, \n", + " categorical_columns=categorical_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "c91f7433", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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7W0fysvL8csvv2DhwoWYN28edztfW4OQUEI54YQEuSFDhqBv37546623YDKZEB8fjyFDhuDDDz/ExYsXPba/cuUK9/8SicQlnA2ozhNjc8ZratSoUfjtt9/wxx9/uLzep59+6rKdRCIBAJfXtlgseO+99zyeMzw8nDfcjO85fv/9d+zevbtW+04IIYQEM75r9rvvvuuSSuZu7ty5ePbZZzF79my8//773O333Xcfzp8/j//9738ejzEajaiqqvL6nH369EGzZs3wwQcfwGKxcLevXr3aY0Ag0Gs1W9k9kMcDwFtvveV1/wgJBTQTTogA/Pvf/8a9996L1atX4/HHH8eyZcuQnp6Obt264ZFHHkG7du1w+fJl7N69G+fOnePWAR8zZgwWLVqEyZMnY+DAgTh06BA+/fRT3pyuQDz33HP45JNPcOedd+Kf//wnt0RZmzZtcPDgQW67gQMHIiYmBpmZmZgxYwZEIhE++eQTj4ssAPTu3Ruff/45nnnmGdx6662IiIjA2LFjMWbMGHzzzTcYP348Ro8ejaKiInzwwQfo3LkzKisra/dGEkIIIUFqzJgx+OSTT6BWq9G5c2fs3r0bW7du9VvD5b///S/0ej2efPJJREZG4sEHH8Q//vEPfPHFF3j88cexfft2pKWlwW6349ixY/jiiy/w008/8ealA9WRdi+++CIee+wxDBs2DH//+99RVFSEVatWebQfAr1WK5VKdO7cGZ9//jluueUWxMbGomvXrujatSsGDRqEV199FVarFa1atcLPP//MGzlHSEhpsrrshBAXzkuOuLPb7Uz79u2Z9u3bMzabjWEYhjl58iTz0EMPMS1atGBkMhnTqlUrZsyYMcxXX33FPc5kMjH/+te/mISEBEapVDJpaWnM7t27mcGDB7ssMRLoEmUMwzAHDx5kBg8ezISFhTGtWrViFi9ezKxYscJjibK8vDymf//+jFKpZFq2bMk899xzzE8//cQAYLZv385tV1lZyTzwwANMdHQ0A4BbrszhcDAvvfQS06ZNG0ahUDCpqanMpk2bmMzMTN4lzQghhJBg5us6zzDVS3tNnjyZiYuLYyIiIpgRI0Ywx44dY9q0acNkZmb6fB673c5MnDiRkUqlzPr16xmGqV5q7JVXXmG6dOnCKBQKJiYmhunduzezcOFCRq/X+93f9957j0lOTmYUCgXT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bbfh119/xZEjR/DYY49hxowZOHnyZLCHRYQYTV0z1q1bh9raWixatCjYQ+5QROI+gwgtImldbCsuXbqEJ598Elu2bIFCoQj2cCKOqGAPoC15+umnUVBQ4POY7t278/+v1Wqh1Wpx6623omfPnkhLS8OPP/4YcqmOzT3v8vJyjBgxAkOHDnURQgklmnvO4YpWq4VEIvFQqrx69SqSk5ODNCoikMydOxe7du3CDz/8gC5dugR7OAFHJpNBp9MBAG6//Xb8/PPPeP311/H2228HeWREKNHUNWPfvn04fPgw5HK5y2sDBw7EAw88gM2bNyM5OVlwzgXAz7vejnF+nXsuJSXF5Zj+/fs3+/wCTVvuMyLx+rUltO574m1dTE5OBsMw0Ov1LtFc99+Su7J8U3+PsbGxUCqVgTilduGXX35BZWUlBgwYwD9ns9nwww8/YP369fjqq6/o+gWQsDLCExISkJCQ0KL32u12AI6WJKFGc8778uXLGDFiBG6//XZs2rQJYnFoJkO05l6HEzKZDLfffjv27t2LiRMnAnD8lvfu3Yu5c+cGd3BEm8KyLB5//HFs374d3333HTIyMoI9pKBgt9tDcp4mgktT14y1a9di1apV/OPy8nKMGTMGH374IQYPHgwAGDJkCJ577jk0NjbyOjJ79uzBbbfdhri4OP6YvXv3urT62bNnD+/kz8jIQHJyMvbu3csbjUajkc/46Gi05T4jEq9fW0Lr/k38rYu33347pFIp9u7di8mTJwMAzpw5g7KyMv63NGTIELzwwguorKxEYmIiAMdvLTY2li99GjJkiEeLPOffY6gycuRIHD9+3OW5Bx98EFlZWViwYAHS0tLo+gWS4OrCBYcff/yRXbduHVtYWMheuHCB3bt3Lzt06FC2R48erNlsDvbwAsZvv/3G6nQ6duTIkexvv/3GXrlyhf8Xzly8eJEtLCxkly9fzsbExLCFhYVsYWEhW1tbG+yhtQkffPABK5fL2ffee489efIk+8gjj7AajcZFqTLcqK2t5e8jAPZvf/sbW1hYyF68eDHYQwsYjz32GKtWq9nvvvvO5W/XZDIFe2gBY+HChez333/PlpaWskVFRezChQtZkUjEfv3118EeGhEhlJaWeqij6/V6Nikpif3jH//IFhcXsx988AGrUqnYt99+mz/m4MGDbFRUFPvKK6+wp06dYpctW8ZKpVL2+PHj/DEvvvgiq9Fo2J07d7JFRUXshAkT2IyMDLahoaE9T7FNaco+g65f64nEdV+IpqyLjz76KJuens7u27ePPXr0KDtkyBB2yJAh/OtWq5Xt06cPO3r0aPbXX39lv/zySzYhIYFdtGgRf8z58+dZlUrFPvPMM+ypU6fYN954g5VIJOyXX37ZrufbHjiro7MsXb9AEpFGeFFRETtixAi2c+fOrFwuZ7t168Y++uij7G+//RbsoQWUTZs2sQAE/4UzM2bMEDznb7/9NthDazPWrVvHpqenszKZjB00aBD7448/BntIAeXbb78VvKczZswI9tAChre/3U2bNgV7aAFj5syZbNeuXVmZTMYmJCSwI0eOJAOcaFeEjHCWZdn//Oc/bF5eHiuXy9lbbrmFffHFFz3e+69//Yu99dZbWZlMxvbu3Zv9/PPPXV632+3skiVL2KSkJFYul7MjR45kz5w5E8jTCThN3WfQ9Ws9kbbuC9GUdbGhoYGdPXs2GxcXx6pUKnbSpEkewacLFy6w99xzD6tUKlmtVss+/fTTbGNjo8sx3377Ldu/f39WJpOx3bt3D9u1190Ip+sXOEQsG4JKZARBEARBEARBEAQRgoRmQTBBEARBEARBEARBhCBkhBMEQRAEQRAEQRBEO0FGOEEQBEEQBEEQBEG0E2SEEwRBEARBEARBEEQ7QUY4QRAEQRAEQRAEQbQTZIQTBEEQBEEQBEEQRDtBRjhBEARBEARBEARBtBNkhBMEQRAEQRAEQRBEO0FGOEEQBEEQBEEQBEG0E2SEEwRBEARBEARBEEQ7QUY4QRAEQRAEQRAEQbQT/z/UX8IJe3drLQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tab_eval.plot_pca()" + ] + }, + { + "cell_type": "markdown", + "id": "0aa7f7aa", + "metadata": {}, + "source": [ + "\n", + "## Structute Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "f51797c5", + "metadata": {}, + "outputs": [], + "source": [ + "original_graph_structure = feature_spec_original.get_structural_data('cite')\n", + "proper_graph_structure = feature_spec_generated_proper.get_structural_data('cite')\n", + "random_graph_structure = feature_spec_generated_random.get_structural_data('cite')" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "1ce7d2f7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DEGREE SIMILLARITY SCORE\n", + "ORIG vs PROPER: 0.5999224835698596\n", + "ORIG vs RANDOM: 0.5943246117058348\n" + ] + } + ], + "source": [ + "orig_proper = get_dd_simmilarity_score(original_graph_structure, proper_graph_structure, cdf_points=1000)\n", + "orig_random = get_dd_simmilarity_score(original_graph_structure, random_graph_structure, cdf_points=1000)\n", + "\n", + "print(\"DEGREE SIMILLARITY SCORE\")\n", + "print(\"ORIG vs PROPER:\", orig_proper)\n", + "print(\"ORIG vs RANDOM:\", orig_random)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "dacb63a1", + "metadata": {}, + "outputs": [], + "source": [ + "original_snap_graph = Graph.instantiate_from_feature_spec(feature_spec_original, 'cite', graph_name='original')\n", + "proper_snap_graph = Graph.instantiate_from_feature_spec(feature_spec_generated_proper, 'cite', graph_name='properly_generated')\n", + "random_graph_structure = Graph.instantiate_from_feature_spec(feature_spec_generated_random, 'cite', graph_name='randomly_generated')\n", + "all_graphs = [original_snap_graph, proper_snap_graph, random_graph_structure]" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "5b53330e", + "metadata": {}, + "outputs": [], + "source": [ + "graph_analyser = AnalysisModule()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "0fd3e48f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
CategoryStatisticoriginalproperly_generatedrandomly_generated
0Global statsNodes270840964095
1Global statsEdges527754285428
2Global statsDensity0.00140.00060.0006
3Global statsAverage degree1.951.331.33
4Global statsZero deg nodes0837636
5Global statsZero in deg nodes0837636
6Global statsZero out deg nodes0837636
7Global statsSelf loops000
8Global statsBidirectional edges527754285428
9Global statsUnique undirected edges527754285428
10Global statsUnique directed edges105541085610856
11ConnectivityIs connectedFalseFalseFalse
12ConnectivityNumber of connected components78879662
13ConnectivityPercent of nodes in largest component91.7777.2283.1
14TransitivityClustering coefficient0.2289970.0011140.001
15Path stats90% effective diameter8.337.738.18
16Path statsApprox. full diameter181615
17Path statsAverage shortest path length6.286.356.81
\n", + "
" + ], + "text/plain": [ + " Category Statistic original \\\n", + "0 Global stats Nodes 2708 \n", + "1 Global stats Edges 5277 \n", + "2 Global stats Density 0.0014 \n", + "3 Global stats Average degree 1.95 \n", + "4 Global stats Zero deg nodes 0 \n", + "5 Global stats Zero in deg nodes 0 \n", + "6 Global stats Zero out deg nodes 0 \n", + "7 Global stats Self loops 0 \n", + "8 Global stats Bidirectional edges 5277 \n", + "9 Global stats Unique undirected edges 5277 \n", + "10 Global stats Unique directed edges 10554 \n", + "11 Connectivity Is connected False \n", + "12 Connectivity Number of connected components 78 \n", + "13 Connectivity Percent of nodes in largest component 91.77 \n", + "14 Transitivity Clustering coefficient 0.228997 \n", + "15 Path stats 90% effective diameter 8.33 \n", + "16 Path stats Approx. full diameter 18 \n", + "17 Path stats Average shortest path length 6.28 \n", + "\n", + " properly_generated randomly_generated \n", + "0 4096 4095 \n", + "1 5428 5428 \n", + "2 0.0006 0.0006 \n", + "3 1.33 1.33 \n", + "4 837 636 \n", + "5 837 636 \n", + "6 837 636 \n", + "7 0 0 \n", + "8 5428 5428 \n", + "9 5428 5428 \n", + "10 10856 10856 \n", + "11 False False \n", + "12 879 662 \n", + "13 77.22 83.1 \n", + "14 0.001114 0.001 \n", + "15 7.73 8.18 \n", + "16 16 15 \n", + "17 6.35 6.81 " + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = graph_analyser.compare_graph_stats(*all_graphs)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "d292ab53", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABb0AAAIoCAYAAABNtEarAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAD33klEQVR4nOzdd3gU5drH8e/upldISKOGKgQUDBAE6S2AgmBBRQVB8RWxIKCARwVsgAqHo0ZUVEDRox5RrBRBEESahqYgSkdJoyVASNud948lS5YkJGCSTfl9ritXMjPPPHPPbhgm9z5zPybDMAxERERERERERERERCoBs6sDEBEREREREREREREpKUp6i4iIiIiIiIiIiEiloaS3iIiIiIiIiIiIiFQaSnqLiIiIiIiIiIiISKWhpLeIiIiIiIiIiIiIVBpKeouIiIiIiIiIiIhIpaGkt4iIiIiIiIiIiIhUGkp6i4iIiIiIiIiIiEiloaS3iIiIiIiIiIiIiFQaSnqLSKUQGRnJ3Xff7eowHKZMmYLJZHJ1GC5jMpmYMmWKY3n+/PmYTCYOHDhQ6se+++67iYyMdCwfOHAAk8nEyy+/XOrHBr33IiIiIlJx6N5VRCorJb1F5LLkJjF//vlnV4cilVR6ejpTpkxh9erVrg4ln/Icm4iIiIiUjaL+JuratSstWrQo46jKzuuvv878+fNdHYaISIGU9BYRkVJ31113cfbsWerVq1fsfdLT05k6deolJ5bnzp3L7t27LzHCS3Ox2J588knOnj1bqscXEREREXE1Jb1FpDxT0ltEpBLJyMjAZrO5Oox8LBYLXl5epfro5JkzZwBwd3fH09Oz1I5TFDc3N7y8vFx2fBEREREREZGqTklvESlVW7ZsoW/fvgQEBODn50ePHj3YsGFDvnbbt2+nS5cueHt7U7t2bZ577jnmzZv3j+pA79u3j1tuuYWgoCB8fHy45ppr+Oabb/K1O3jwIAMGDMDX15fQ0FAeffRRli1bhslkKtYo4x9//JG2bdvi5eVFw4YNefPNNwttu3DhQlq3bo23tzdBQUHcdtttHD58OF+7uLg4GjRogLe3NzExMaxdu5auXbvStWtXR5vVq1djMpn46KOPePLJJ6lVqxY+Pj6kpaUBsHHjRvr06UNgYCA+Pj506dKFdevW5TvW33//zYgRIwgLC8PT05PmzZvz7rvvFnneAJmZmTz66KOEhITg7+/PgAED+Ouvv/K1K6im988//0xsbCw1atTA29ub+vXrM2LECMBehzskJASAqVOnYjKZnOqE33333fj5+bF371769euHv78/d9xxh2Nb3preef373/+mXr16eHt706VLF3799Ven7Re+xrny9llUbAXVRczJyeHZZ5+lYcOGeHp6EhkZyRNPPEFmZqZTu8jISK6//np+/PFHYmJi8PLyokGDBrz33nsFno+IiIiIVCyXel+4fPlyWrVqhZeXF1FRUXz22WdFHiPvnDZF3f9eboyRkZH89ttv/PDDD4774YLuo0VEXMXN1QGISOX122+/0alTJwICAnj88cdxd3fnzTffpGvXrvzwww+0a9cOsCddu3XrhslkYtKkSfj6+vL222//o9G6SUlJdOjQgfT0dB5++GGCg4NZsGABAwYM4NNPP2XQoEGAfXRw9+7dSUhI4JFHHiE8PJwPP/yQVatWFes4O3bsoHfv3oSEhDBlyhRycnKYPHkyYWFh+do+//zzPPXUUwwePJh7772XlJQUXn31VTp37syWLVuoVq0aAHPmzOHBBx+kU6dOPProoxw4cICBAwdSvXp1ateuna/fZ599Fg8PD8aPH09mZiYeHh58//339O3bl9atWzN58mTMZjPz5s2je/furF27lpiYGMfrdM0112AymXjwwQcJCQlhyZIl3HPPPaSlpTFmzJiLnv+9997LwoULGTJkCB06dOD777/nuuuuK/J1S05OdrxuEydOpFq1ahw4cMBxEx8SEsKcOXMYNWoUgwYN4sYbbwTgqquucvSRk5NDbGwsHTt25OWXX8bHx+eix3zvvfc4deoUo0ePJiMjg//85z90796dHTt2FPh+FaY4sV3o3nvvZcGCBdx8882MGzeOjRs3Mm3aNHbt2sXnn3/u1HbPnj3cfPPN3HPPPQwbNox3332Xu+++m9atW9O8efNixykiIiIiZSM1NZWjR4/mW5+dnZ1v3aXcF/7555/ceuut3H///QwbNox58+Zxyy23sHTpUnr16lVkXJd7/1ucGGfPns1DDz2En58f//rXvwAu6Z5aRKTUGSIil2HevHkGYGzevLnQNgMHDjQ8PDyMvXv3OtYdOXLE8Pf3Nzp37uxY99BDDxkmk8nYsmWLY92xY8eMoKAgAzD2799fZDz16tUzhg0b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rzgWL17M33//7VjetGkTGzdudJwH2D8w+P33353Ofdu2baxbt86pr0uJrV+/fkD+12XWrFkAXHfddZd0HiIiIiJSMV3qfeGRI0f4/PPPHctpaWm89957tGrVqsjSJlC8+99/EqOvr2+J3auLiJQ0jfQWkX/k3XffZenSpfnWP/LIIzz33HN89913dOzYkQceeAA3NzfefPNNMjMzefHFFx1tH3/8cRYuXEivXr146KGH8PX15e2336Zu3bocP378skYQTJw4kf/+97/07duXhx9+mKCgIBYsWMD+/ftZtGiRoyzG//3f//Haa69x++2388gjjxAREcEHH3yAl5cXUPTohalTp7J06VI6derEAw88QE5ODq+++irNmzdn+/btjnYNGzbkueeeY9KkSRw4cICBAwfi7+/P/v37+fzzz7nvvvsYP348Hh4eTJkyhYceeoju3bszePBgDhw4wPz58wusPV4Qs9nM22+/Td++fWnevDnDhw+nVq1a/P3336xatYqAgAC++uorAKZPn86qVato164dI0eOJCoqiuPHjxMfH8+KFSs4fvx4ocdp1aoVt99+O6+//jqpqal06NCBlStXFmuU/IIFC3j99dcZNGgQDRs25NSpU8ydO5eAgADHjba3tzdRUVF8/PHHNGnShKCgIFq0aEGLFi2K7L8gjRo1omPHjowaNYrMzExmz55NcHAwjz/+uKPNiBEjmDVrFrGxsdxzzz0kJyfzxhtv0Lx5c8fEq5caW8uWLRk2bBhvvfUWJ0+epEuXLmzatIkFCxYwcOBApxH9IiIiIlJ5Xep9YZMmTbjnnnvYvHkzYWFhvPvuuyQlJTFv3rxiHa8497//JMbWrVszZ84cnnvuORo1akRoaCjdu3e/vBdHRKSkGSIil2HevHkGUOjX4cOHDcMwjPj4eCM2Ntbw8/MzfHx8jG7duhk//fRTvv62bNlidOrUyfD09DRq165tTJs2zXjllVcMwEhMTCwynnr16hnDhg1zWrd3717j5ptvNqpVq2Z4eXkZMTExxtdff51v33379hnXXXed4e3tbYSEhBjjxo0zFi1aZADGhg0bijz2Dz/8YLRu3drw8PAwGjRoYLzxxhvG5MmTjYIusYsWLTI6duxo+Pr6Gr6+vkbTpk2N0aNHG7t373Zq98orrxj16tUzPD09jZiYGGPdunVG69atjT59+jjarFq1ygCM//3vfwXGtWXLFuPGG280goODDU9PT6NevXrG4MGDjZUrVzq1S0pKMkaPHm3UqVPHcHd3N8LDw40ePXoYb731VpHnfvbsWePhhx82goODDV9fX6N///7G4cOHDcCYPHmyo13u78v+/fsNw7D/Xtx+++1G3bp1DU9PTyM0NNS4/vrrjZ9//tmp/59++snx2ubtc9iwYYavr2+BMQ0bNsyoV6+eY3n//v0GYLz00kvGzJkzjTp16hienp5Gp06djG3btuXbf+HChUaDBg0MDw8Po1WrVsayZcvy9Xmx2Ap677Ozs42pU6ca9evXN9zd3Y06deoYkyZNMjIyMpza1atXz7juuuvyxdSlSxejS5cuBZ6viIiIiLhG7j3u5s2bC9zepUsXo3nz5k7rLvW+cNmyZcZVV11leHp6Gk2bNi303j+vS7n//Sf3romJicZ1111n+Pv7G4DuV0WkXDEZhmbGEpHyacyYMbz55pucPn260Mn9Ssvs2bN59NFH+euvv6hVq1aZHrsgNpuNkJAQbrzxxmKVXhERERERkYorMjKSFi1a8PXXX1/yvgcOHKB+/fq89NJLjB8/vhSiExEp/1TTW0TKhbNnzzotHzt2jPfff5+OHTuWesL7wmNnZGTw5ptv0rhxY5ckvDMyMvLVu37vvfc4fvw4Xbt2LfN4REREREREREQqEtX0FpFyoX379nTt2pVmzZqRlJTEO++8Q1paGk899VSpH/vGG2+kbt26tGrVitTUVBYuXMjvv/+ebyLNsrJhwwYeffRRbrnlFoKDg4mPj+edd96hRYsW3HLLLS6JSURERERERESkolDSW0TKhX79+vHpp5/y1ltvYTKZiI6O5p133qFz586lfuzY2FjefvttPvjgA6xWK1FRUXz00UfceuutpX7sgkRGRlKnTh1eeeUVjh8/TlBQEEOHDmX69Ol4eHi4JCYRERERERERkYpCNb1FREREREREREREpNJQTW8RERERERERERERqTSU9BYRERERERERERGRSqPK1/S22WwcOXIEf39/TCaTq8MRERERkRJiGAanTp2iZs2amM0a61FV6P5eREREpPIq7j1+lU96HzlyhDp16rg6DBEREREpJYcPH6Z27dquDkPKiO7vRURERCq/ou7xq3zS29/fH7C/UAEBAS6ORkRERERKSlpaGnXq1HHc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wi+0lKIUEalclPQWERGpylzwNM2hQ4cYO3Ys//d//0d8fDyvvvoqM2fOLLT9uHHjaNu2Lc8++yy33nor69ev57XXXuP11193ardu3TpefPFFBg4cyHfffcf//vc/vvnmGwB69uxJ+/btGThwIC+++CJNmjThyJEjfPPNNwwaNKjAx9Qv5t5773UkhC5MKF3MQw89xLRp02jUqBFNmzbl1Vdf5cSJE46Rhv7+/owfP55HH30Um81Gx44dSU1NZd26dQQEBDBs2LBiHefpp5/m+uuvp27dutx8882YzWa2bdvGr7/+ynPPPVfofo0bN+a9995j2bJl1K9fn/fff5/NmzdTv359R5vIyEiWLVvG7t27CQ4OJjAwkDvuuIOXXnqJG264gWeeeYbatWtz8OBBPvvsMx5//HFq167NI488wvTp02ncuDFNmzZl1qxZnDx5stivnUi5YLZAnxnwyVDAhHPi+1zZkT7TS60cgK6fun7q+lkxBeRk2n8wDMhToiiXyTAIs1qJ7jIFrhlVYBsREbk0SnqLiIhUZS54mmbo0KGcPXuWmJgYLBYLjzzyCPfdd1+h7aOjo/nkk094+umnefbZZ4mIiOCZZ57h7rvvdmo3btw4fv75Z6ZOnUpAQACzZs0iNjYWsD++/u233/Kvf/2L4cOHk5KSQnh4OJ07dyYsrJjlCvJo3LgxHTp04Pjx4051VosyYcIEEhMTGTp0KBaLhfvuu4/Y2FinEZfPPvssISEhTJs2jX379lGtWjWio6N54oknin2c2NhYvv76a5555hlmzJiBu7s7TZs25d57773ofv/3f//Hli1buPXWWzGZTNx+++088MADLFmyxNFm5MiRrF69mjZt2nD69GlWrVpF165dWbNmDRMmTODGG2/k1KlT1KpVix49ejhGLo4bN46EhASGDRuG2WxmxIgRDBo0iNTU1GKfl0i5EDUABr8HSydAWp6SKAE17QnvqAGldmhdP3X91PWz4rAZNswmM/z1C13++IGb00/xqb8fJsPAyJPUNp2rzT7h2Aks4Vcq4S0iUkJMRhWf/SK35l9qamqhj5OJXI4cWw5zd8wlPime6LBoRl45EjezPmcSkZKRkZHB/v37qV+/vlON0fKua9eutGrVyjFBWkmJjIxkzJgxjBkzpkT7LYxhGDRu3JgHHniAsWPHXnY/NpuNZs2aMXjw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i5kzZxISEsL999/PiBEjHK/52rVrGTp0KK+88gqdOnVi79693HfffQBMnjzZ6bWYPn06s2fPxs3NDZvNRu3atfnf//5HcHAwP/30E/fddx8REREMHjyY8ePHs2vXLtLS0pg3bx4AQUFBZGdnExsbS/v27Vm7di1ubm4899xz9OnTh+3bt+Ph4VGs91CkNKVnF5yMBbCYLXhaPLHarEzfNN3pEeRcueumb5pOtzrdHKVOCuvXx92nwPUXo+tn4XT91PXTYeeX8MlQuPDfadoRWDnl3IIJmg+y/40W3oKjZ4/y1Lqn+PHvHwH4cs+XtAxpWZZRlwvloXa2YRicTM9m+c7EYtZa/o4sq5UeTcOIuyPasf3G138qdN9OjWtwe4w9EWsymdibfLrAEhUFnXv3pqEcOXmWzQeKHrn8UI9GNIsIwNPNfC4ZaU9CerpZnEYsA3zzcKci+8v1aK8mBa632gy+/z2FxNSMAj8sMGGvy31Hu3oFnlt139J5eig3SVpUXK5IklrMJib3j2LUwnhMOF81cl+hyf2jyvzfQXmNq7zHdiGTUcU/As6d6CY1NZWAgICid/gH/rPiT2av+MNR42lMzyY80rNxqR5TREQqp4yMDPbv30/9+vXx8rr80Uc5thzm7phLfFI80WHRjLxyJG7m0vtMvGvXrqSlpREfX/hkK59++in3338/R48eBewjFYcPH86ePXto2LAhAK+//jrPPPMMiYn2On41a9bk0Ucf5bHHHrOfV04O9evXp3Xr1ixevJgzZ85QvXp15s+fz5AhQwD74+aRkZGMGTOGxx57jNWrV9OtWzdWrFhBjx49AJg+fTqTJk1i7969NGjQAID777+fAwcOsHTpUsc55Z2IrV+/fkRGRjqSTg8//DA7duxg1apVRb4+4eHhjB8/nvHjxwP20XsNGjTg6quvZvHixWRmZhIUFMSKFSto3/78E0T33nsv6enpfPjhhwWex7fffst1113H2bNn8fLyomfPnvTo0YNJkyY5+li4cCGPP/44R44cAex/BI4ZM4Z///vfF435wQcfJDEx0TFasqCatAsXLuS5555j165d52elz8qiWrVqLF68mN69exf5HhbmYv8WyvI+T8qPi73vF/t9uXLBlYX22alWJ17v+TqbEzczYtmIImN4N/Zd2obbE7edP+rMicz8yZEdw3YU53QcdP28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9GgNGDBAzZo109SpUxUdHa3ExERJUlhYmLy8vFS1alWFhYWpatWqF3ytbdq00fjx49WkSRMNHDhQHTp0KOgBvnTpUm3atEnvvfee2rdvr06dOumtt97Sd999p6SkpIJjnD59Wm+99Zaio6PVrVs3zZo1S++//77S0tKUlZWlzMxM9e7dW40bN1aLFi00aNAgRUREXNbXBgAoegOAB7r55puVmpqqffv26euvv1aPHj00YsQI9e7dW3l5eWX2vFfSDxAAAAAoL6ZOnar58+dr69atl32Mli1bymr9vawSGhqq1q1bFyzbbDbVqFFDR44cKbRf586dCx57eXmpQ4cOBTk2btyoZcuWqWrVqgV/mjdvLim///Z57du3v2i2rKwsHT58WNdcc02h9ddcc81lveY2bdoUWq5Tp07B69q6davq16+v+vXrF2yPiopScHBwoeeKiIhQ3bp1C5Y7d+4sp9Op7du3KyQkRIMHD1bPnj3Vp08fvfTSS0pNTS11TgA4j6I3AHggX19fhYWFqW7duoqJidE//vEPffbZZ/r66681b948SfkffXzggQdUq1YtBQYG6vrrr9fGjRsLHefZZ59V7dq1Va1aNT3wwAMaM2ZMof6E53sRPvfccwoPDy+YJXLw4EH1799fwcHBCgkJ0a233qp9+/YVOvbrr7+uFi1ayM/PT82bN9crr7xSlqcEAAAAcJlu3bqpZ8+eGjt2bJFtVqtVhmEUWpebm1tknLe3d6Hl85/U/PO60nxa89SpU+rTp49SUlIK/dm5c6e6detWMK5KlSolPqYrXOnrKok333xTq1evVpcuXbRgwQI1bdpUP/74o0ufA0DlQdEbAMqJ66+/Xm3bttXHH38sSfr73/+uI0eO6Ouvv9b69esVExOjG264QRkZGZKkd999V88995ymTp2q9evXKyIiQrNnzy5y3KVLl2r79u1avHixvvzyS+Xm5qpnz56qVq2avv/+e61cuVJVq1bVzTffXDAT/N1339W4ceP03HPPaevWrXr++ef1zDPPaP78+e47IQAAAMAVmDJlir744gutXr260PpatWopLS2tUOE7JSXFZc/7x0JuXl6e1q9frxYtWkiSYmJi9PPPPysyMlJXXXVVoT+lKXQHBgYqPDxcK1euLLR+5cqVioqKcs0LOadFixY6ePCgDh48WLBuy5YtOnHiRKHn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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from matplotlib.pyplot import set_loglevel\n", + "set_loglevel('warning')\n", + "_ = graph_analyser.compare_graph_plots(*all_graphs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11b4bf61", + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_epinions_demo.ipynb b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_epinions_demo.ipynb new file mode 100644 index 000000000..1e35013a9 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_epinions_demo.ipynb @@ -0,0 +1,1177 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "518a6f7d", + "metadata": {}, + "source": [ + "# Copyright 2023 NVIDIA Corporation. All Rights Reserved.\n", + "#\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# http://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License.\n", + "# ==============================================================================" + ] + }, + { + "cell_type": "markdown", + "id": "d749a17a", + "metadata": {}, + "source": [ + "# End to end graph generation demo (Epinions)" + ] + }, + { + "cell_type": "markdown", + "id": "dd9cca8f", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "In this notebook, we have walked through the complete process of generating a synthetic dataset based on a Epinions dataset. The Epinions dataset is trust network dataset. For each user, it contains his profile, his ratings and his trust relations.\n", + "\n", + "Content:\n", + "\n", + "1. [Prepare the original dataset](#1)\n", + "1. [Preprare SynGen Configuration](#2)\n", + "1. [Dataset Generation](#3)\n", + "1. [Tabular data evaluation](#4)\n", + "1. [Structure evaluation](#5)" + ] + }, + { + "cell_type": "markdown", + "id": "22f9f4a1", + "metadata": {}, + "source": [ + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "dfd4207b", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n", + "DGL backend not selected or invalid. Assuming PyTorch for now.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Setting the default backend to \"pytorch\". You can change it in the ~/.dgl/config.json file or export the DGLBACKEND environment variable. Valid options are: pytorch, mxnet, tensorflow (all lowercase)\n" + ] + } + ], + "source": [ + "# preprocessing\n", + "from syngen.preprocessing.datasets import EpinionsPreprocessing\n", + "\n", + "# config\n", + "from syngen.configuration import SynGenConfiguration\n", + "\n", + "# generation\n", + "from syngen.synthesizer import ConfigurationGraphSynthesizer\n", + "\n", + "# evaluation\n", + "from syngen.analyzer.tabular import TabularMetrics\n", + "from syngen.analyzer.graph import Graph\n", + "from syngen.analyzer.graph.stats import get_dd_simmilarity_score\n", + "from syngen.analyzer.graph.analyser import AnalysisModule\n", + "\n", + "# utils\n", + "import copy\n", + "from syngen.utils.types import MetaData" + ] + }, + { + "cell_type": "markdown", + "id": "761fcf6f", + "metadata": {}, + "source": [ + "\n", + "## Prepare original dataset" + ] + }, + { + "cell_type": "markdown", + "id": "f6258865", + "metadata": {}, + "source": [ + "SynGen requires the data to be in SynGen dataset format or simply SynGen format, so firstly, we transform the raw Cora dataset into SynGen format. If you don't download Epinions before, you may pass `download=True` as `EpinionsPreprocessing` class supports automatic downloading." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "db86a579", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = '/workspace/data/epinions'\n", + "preprocessed_path = '/workspace/data/epinions_preprocessed'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4720512b", + "metadata": {}, + "outputs": [], + "source": [ + "preprocessing = EpinionsPreprocessing(source_path=data_path, destination_path=preprocessed_path, download=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "52973a7a", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_original = preprocessing.transform(use_cache=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cc3bdea7", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'nodes': [{'name': 'user',\n", + " 'count': 120491,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'item', 'count': 755759, 'features': [], 'features_path': None}],\n", + " 'edges': [{'name': 'user-item',\n", + " 'count': 13668320,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [{'name': 'rating',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-item.parquet',\n", + " 'structure_path': 'user-item_edge_list.parquet'},\n", + " {'name': 'user-user',\n", + " 'count': 717667,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'user-user_edge_list.parquet'}],\n", + " : '/workspace/data/epinions_preprocessed'}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_original" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f5a0b99a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'user-item'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_original[MetaData.EDGES][0][MetaData.NAME]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d1e1a6fd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'user-user'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_original[MetaData.EDGES][1][MetaData.NAME]" + ] + }, + { + "cell_type": "markdown", + "id": "2576ab76", + "metadata": {}, + "source": [ + "\n", + "## Preprare SynGen Configuration" + ] + }, + { + "cell_type": "markdown", + "id": "b527f148", + "metadata": {}, + "source": [ + "SynGen generation process is driven by the configuration that is the superset of the SynGen format metadata file. Let us create two configurations: a proper one that will mimic Cora dataset tabular and structural features and a random one." + ] + }, + { + "cell_type": "markdown", + "id": "c20c25ab", + "metadata": {}, + "source": [ + "### Proper Synthetic " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "befd3ed9", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_synthetic = feature_spec_original.copy()\n", + "\n", + "feature_spec_synthetic[MetaData.EDGES][0][MetaData.TABULAR_GENERATORS] = [\n", + " {\n", + " MetaData.TYPE: \"kde\",\n", + " MetaData.FEATURES_LIST: -1, # copies all tabular features\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'configuration',\n", + " MetaData.PATH: preprocessed_path,\n", + " MetaData.NAME: \"user-item\",\n", + " },\n", + " MetaData.PARAMS: {}\n", + " }\n", + "]\n", + "\n", + "feature_spec_synthetic[MetaData.EDGES][0][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'cfg', # the same a 'configuration'\n", + " MetaData.PATH: preprocessed_path,\n", + " MetaData.NAME: \"user-item\",\n", + " },\n", + " MetaData.PARAMS: {}\n", + "}\n", + "\n", + "feature_spec_synthetic[MetaData.EDGES][1][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'cfg',\n", + " MetaData.PATH: preprocessed_path,\n", + " MetaData.NAME: \"user-user\",\n", + " },\n", + " MetaData.PARAMS: {\n", + " \"has_self_loop\": False,\n", + " }\n", + "}\n", + "\n", + "# aligns 'rating' edge feature based on the 'user-item' and 'user-user' edges\n", + "feature_spec_synthetic[MetaData.ALIGNERS] = [\n", + " {\n", + " MetaData.TYPE: \"xgboost\",\n", + " MetaData.GRAPHS: [\"user-item\", \"user-user\"],\n", + " MetaData.NODES: {},\n", + " MetaData.EDGES: {\"user-item\": ['rating']},\n", + " MetaData.PARAMS: {},\n", + " }\n", + "]\n", + "\n", + "config_proper = SynGenConfiguration(feature_spec_synthetic)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "fccffa12", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-item',\n", + " 'count': 13668320,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [{'name': 'rating',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-item.parquet',\n", + " 'structure_path': 'user-item_edge_list.parquet',\n", + " : [{: 'kde',\n", + " : ['rating'],\n", + " : {: 'configuration',\n", + " : '/workspace/data/epinions_preprocessed',\n", + " : 'user-item'},\n", + " : {}}],\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/epinions_preprocessed',\n", + " : 'user-item'},\n", + " : {}}},\n", + " {'name': 'user-user',\n", + " 'count': 717667,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'user-user_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/epinions_preprocessed',\n", + " : 'user-user'},\n", + " : {'has_self_loop': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 120491,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'item', 'count': 755759, 'features': [], 'features_path': None}],\n", + " : [{: 'xgboost',\n", + " : ['user-item', 'user-user'],\n", + " : {},\n", + " : {'user-item': ['rating']},\n", + " : {}}]}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config_proper" + ] + }, + { + "cell_type": "markdown", + "id": "307b5d17", + "metadata": {}, + "source": [ + "### Random " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "a7b04866", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_random = feature_spec_original.copy() \n", + "\n", + "feature_spec_random[MetaData.EDGES][0][MetaData.TABULAR_GENERATORS] = [\n", + " {\n", + " MetaData.TYPE: \"random\",\n", + " MetaData.FEATURES_LIST: -1, # copies all tabular features\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'random',\n", + " },\n", + " MetaData.PARAMS: {\n", + " }\n", + " }\n", + "]\n", + "\n", + "feature_spec_random[MetaData.EDGES][0][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'rnd', # the save as 'random' \n", + " },\n", + " MetaData.PARAMS: {}\n", + "}\n", + "\n", + "feature_spec_random[MetaData.EDGES][1][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'rnd',\n", + " },\n", + " MetaData.PARAMS: {\n", + " \"has_self_loop\": False,\n", + " }\n", + "}\n", + "\n", + "config_random = SynGenConfiguration(feature_spec_random)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "71cdf511", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-item',\n", + " 'count': 13668320,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [{'name': 'rating',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-item.parquet',\n", + " 'structure_path': 'user-item_edge_list.parquet',\n", + " : [{: 'random',\n", + " : ['rating'],\n", + " : {: 'random'},\n", + " : {}}],\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {}}},\n", + " {'name': 'user-user',\n", + " 'count': 717667,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'user-user_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {'has_self_loop': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 120491,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'item', 'count': 755759, 'features': [], 'features_path': None}]}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config_random" + ] + }, + { + "cell_type": "markdown", + "id": "2a013a71", + "metadata": {}, + "source": [ + "\n", + "## Dataset Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "6ea8a896", + "metadata": {}, + "outputs": [], + "source": [ + "save_path_proper = '/workspace/data/epinions_generated'\n", + "save_path_random = '/workspace/data/epinions_random'" + ] + }, + { + "cell_type": "markdown", + "id": "5c50fe04", + "metadata": {}, + "source": [ + "### Create Synthesizers" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "28438b3c", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_proper = ConfigurationGraphSynthesizer(configuration=config_proper, save_path=save_path_proper, gpu=True)\n", + "synthesizer_random = ConfigurationGraphSynthesizer(configuration=config_random, save_path=save_path_random, gpu=True)" + ] + }, + { + "cell_type": "markdown", + "id": "9645c2b3", + "metadata": {}, + "source": [ + "### Fit Synthesizers" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "56881790", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_proper.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "e5ad4fee", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_random.fit()" + ] + }, + { + "cell_type": "markdown", + "id": "ad02cdd6", + "metadata": {}, + "source": [ + "### Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "bf3a8b16", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_generated_proper = synthesizer_proper.generate()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "cb307813", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-item',\n", + " 'count': 13668320,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [{'name': 'rating',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-item.parquet',\n", + " 'structure_path': 'user-item_edge_list.parquet',\n", + " : [{: 'kde',\n", + " : ['rating'],\n", + " : {: 'configuration',\n", + " : '/workspace/data/epinions_preprocessed',\n", + " : 'user-item'},\n", + " : {'gpu': True, 'verbose': False}}],\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/epinions_preprocessed',\n", + " : 'user-item'},\n", + " : {'gpu': True, 'verbose': False}}},\n", + " {'name': 'user-user',\n", + " 'count': 717667,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'user-user_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/epinions_preprocessed',\n", + " : 'user-user'},\n", + " : {'has_self_loop': False,\n", + " 'gpu': True,\n", + " 'verbose': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 120491,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'item', 'count': 1048561, 'features': [], 'features_path': None}],\n", + " : [{: 'xgboost',\n", + " : ['user-item', 'user-user'],\n", + " : {},\n", + " : {'user-item': ['rating']},\n", + " : {}}],\n", + " : '/workspace/data/epinions_generated'}" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_generated_proper" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "c1ceff15", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_generated_random = synthesizer_random.generate()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "16a2b861", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-item',\n", + " 'count': 13668320,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [{'name': 'rating',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-item.parquet',\n", + " 'structure_path': 'user-item_edge_list.parquet',\n", + " : [{: 'random',\n", + " : ['rating'],\n", + " : {: 'random'},\n", + " : {'gpu': True, 'verbose': False}}],\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {'gpu': True, 'verbose': False}}},\n", + " {'name': 'user-user',\n", + " 'count': 717667,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'item',\n", + " 'directed': False,\n", + " 'features': [],\n", + " 'features_path': None,\n", + " 'structure_path': 'user-user_edge_list.parquet',\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {'has_self_loop': False,\n", + " 'gpu': True,\n", + " 'verbose': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 120491,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'item', 'count': 1048576, 'features': [], 'features_path': None}],\n", + " : '/workspace/data/epinions_random'}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_generated_random" + ] + }, + { + "cell_type": "markdown", + "id": "ab6f2e3e", + "metadata": {}, + "source": [ + "\n", + "## Tabular Data Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "e0ddfbfe", + "metadata": {}, + "outputs": [], + "source": [ + "original_tabular_data, categorical_features = feature_spec_original.get_tabular_data(MetaData.EDGES, 'user-item', return_cat_feats=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "e4585040", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "proper_tabular_data = feature_spec_generated_proper.get_tabular_data(MetaData.EDGES, 'user-item')" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "df6a33ad", + "metadata": {}, + "outputs": [], + "source": [ + "random_tabular_data = feature_spec_generated_random.get_tabular_data(MetaData.EDGES, 'user-item')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "07c8d19b", + "metadata": {}, + "outputs": [], + "source": [ + "tab_eval = TabularMetrics(original_tabular_data, \n", + " proper_tabular_data, \n", + " categorical_columns=categorical_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "29599ab5", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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CK2amSIi2BtWpg1njRkiooaCxZWW3SkoQeS525DJgDUv9kDf9jZSRyIiIj0Xf/Uukm/nw8ZcgW0hPrC1NJE6EhFRo8Rp67TM1sIE3017GnFXczDCXfrFIYmIiAZ2tMVG/16wszRBa5smUschImq0WFzpgFNzMzg1N5M6BhERkcbgznZSRyAiavQ4LJCIiIiIiEgLWFwRERERERFpAYsrIiIiIiIiLWBxRUREREREpAUsroiIiIiIiLSAxRUREREREZEWsLgiIiIiIiLSAhZXREREREREWsDiioiIiIiISAtYXBEREREREWkBiysiIiIiIiItYHFFRERERESkBSyuiIiIiIiItIDFFRERERERkRYYSR2gPhJCAADy8vIkTvKAUqlEUVER8vLyIJfLpY5T59h+tp/t15/2P/y9+/D3MP2lvl2bpKJvPxPaxv6rHfZf7TTU/qvOtYnFVQXy8/MBAE5OThInISLST/n5+bCyspI6Rr3CaxMRkbSqcm2SCb49+Ai1Wo1bt27BwsICMplM6jjIy8uDk5MTrl+/DktLS6nj1Dm2n+1n+/Wn/UII5Ofnw9HREQYGHLn+d/Xt2iQVffuZ0Db2X+2w/2qnofZfda5N/OSqAgYGBmjVqpXUMR5haWnZoF6I2sb2s/1sv360n59YVay+Xpukok8/E7rA/qsd9l/tNMT+q+q1iW8LEhERERERaQGLKyIiIiIiIi1gcdUAGBsbY+nSpTA2NpY6iiTYfraf7dff9hP9E38maof9Vzvsv9rRh/7jhBZERERERERawE+uiIiIiIiItIDFFRERERERkRawuCIiIiIiItICFldERERERERawOKqjh06dAgjR46Eo6MjZDIZ9u7d+9hjp06dCplMhjVr1jzxnCqVCkuWLIGrqytMTU3Rtm1bLF++HPVxrpLK2h8YGAiZTFbua9iwYZWed+3atWjdujVMTEzg4+ODmJgYHbWgdnTR/hUrVsDLywsWFhawtbXFmDFjkJycrMNW1I6uXgMPffjhh5DJZJgzZ452g2uJrtp/8+ZNvPLKK7C2toapqSnc3NwQFxeno1YQaYcuronvvvvuIz9DnTp10m7wekLfr6m1pYv+4+uvvPPnz2PUqFGwsrJCkyZN4OXlhWvXrj3xvN9++y06deoEExMTuLm54ddff9VRC3SDxVUdKywshIeHB9auXfvE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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tab_eval.plot_mean_std()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "3c4c2fd9", + "metadata": {}, + "outputs": [], + "source": [ + "tab_eval = TabularMetrics(original_tabular_data, \n", + " random_tabular_data, \n", + " categorical_columns=categorical_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "3490b1ca", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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CK2amSIi2BtWpg1njRkiooaCxZWW3SkoQeS525DJgDUv9kDf9jZSRyIiIj0Xf/Uukm/nw8ZcgW0hPrC1NJE6EhFRo8Rp67TM1sIE3017GnFXczDCXfrFIYmIiAZ2tMVG/16wszRBa5smUschImq0WFzpgFNzMzg1N5M6BhERkcbgznZSRyAiavQ4LJCIiIiIiEgLWFwRERERERFpAYsrIiIiIiIiLWBxRUREREREpAUsroiIiIiIiLSAxRUREREREZEWsLgiIiIiIiLSAhZXREREREREWsDiioiIiIiISAtYXBEREREREWkBiysiIiIiIiItYHFFRERERESkBSyuiIiIiIiItIDFFRERERERkRYYSR2gPhJCAADy8vIkTvKAUqlEUVER8vLyIJfLpY5T59h+tp/t15/2P/y9+/D3MP2lvl2bpKJvPxPaxv6rHfZf7TTU/qvOtYnFVQXy8/MBAE5OThInISLST/n5+bCyspI6Rr3CaxMRkbSqcm2SCb49+Ai1Wo1bt27BwsICMplM6jjIy8uDk5MTrl+/DktLS6nj1Dm2n+1n+/Wn/UII5Ofnw9HREQYGHLn+d/Xt2iQVffuZ0Db2X+2w/2qnofZfda5N/OSqAgYGBmjVqpXUMR5haWnZoF6I2sb2s/1sv360n59YVay+Xpukok8/E7rA/qsd9l/tNMT+q+q1iW8LEhERERERaQGLKyIiIiIiIi1gcdUAGBsbY+nSpTA2NpY6iiTYfraf7dff9hP9E38maof9Vzvsv9rRh/7jhBZERERERERawE+uiIiIiIiItIDFFRERERERkRawuCIiIiIiItICFldERERERERawOKqjh06dAgjR46Eo6MjZDIZ9u7d+9hjp06dCplMhjVr1jzxnCqVCkuWLIGrqytMTU3Rtm1bLF++HPVxrpLK2h8YGAiZTFbua9iwYZWed+3atWjdujVMTEzg4+ODmJgYHbWgdnTR/hUrVsDLywsWFhawtbXFmDFjkJycrMNW1I6uXgMPffjhh5DJZJgzZ452g2uJrtp/8+ZNvPLKK7C2toapqSnc3NwQFxeno1YQaYcuronvvvvuIz9DnTp10m7wekLfr6m1pYv+4+uvvPPnz2PUqFGwsrJCkyZN4OXlhWvXrj3xvN9++y06deoEExMTuLm54ddff9VRC3SDxVUdKywshIeHB9auXfvE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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tab_eval.plot_mean_std()" + ] + }, + { + "cell_type": "markdown", + "id": "87c5a098", + "metadata": {}, + "source": [ + "\n", + "## Structute Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "81ec74d0", + "metadata": {}, + "outputs": [], + "source": [ + "original_graph_structure = feature_spec_original.get_structural_data('user-item')\n", + "proper_graph_structure = feature_spec_generated_proper.get_structural_data('user-item')\n", + "random_graph_structure = feature_spec_generated_random.get_structural_data('user-item')" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "6d98d9f9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DEGREE SIMILLARITY SCORE\n", + "ORIG vs PROPER: 0.9485071808645863\n", + "ORIG vs RANDOM: 0.9600055099479101\n" + ] + } + ], + "source": [ + "orig_proper = get_dd_simmilarity_score(original_graph_structure, proper_graph_structure, cdf_points=1000)\n", + "orig_random = get_dd_simmilarity_score(original_graph_structure, random_graph_structure, cdf_points=1000)\n", + "\n", + "print(\"DEGREE SIMILLARITY SCORE\")\n", + "print(\"ORIG vs PROPER:\", orig_proper)\n", + "print(\"ORIG vs RANDOM:\", orig_random)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "72027d10", + "metadata": {}, + "outputs": [], + "source": [ + "original_snap_graph = Graph.instantiate_from_feature_spec(feature_spec_original, 'user-item', graph_name='original')\n", + "proper_snap_graph = Graph.instantiate_from_feature_spec(feature_spec_generated_proper, 'user-item', graph_name='properly_generated')\n", + "random_graph_structure = Graph.instantiate_from_feature_spec(feature_spec_generated_random, 'user-item', graph_name='randomly_generated')\n", + "all_graphs = [original_snap_graph, proper_snap_graph, random_graph_structure]" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "882cde3f", + "metadata": {}, + "outputs": [], + "source": [ + "graph_analyser = AnalysisModule()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "0c4828e2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
CategoryStatisticoriginalproperly_generatedrandomly_generated
0Global statsNodes87625011690521169067
1Global statsEdges136679901366716113668210
2Global statsDensity0.00.00.0
3Global statsAverage degree15.611.6911.69
4Global statsZero deg nodes120490241368123235
5Global statsZero in deg nodes120490241368123235
6Global statsZero out deg nodes120490241368123235
7Global statsSelf loops39558
8Global statsBidirectional edges136679511366710613668202
9Global statsUnique undirected edges136679511366710613668202
10Global statsUnique directed edges273359022733421227336404
11ConnectivityIs connectedFalseFalseFalse
12ConnectivityNumber of connected components120491241369123236
13ConnectivityPercent of nodes in largest component86.2579.3589.46
14TransitivityClustering coefficient0.0369350.0006110.000637
15Path stats90% effective diameter3.594.113.89
16Path statsApprox. full diameter666
17Path statsAverage shortest path length3.13.913.83
\n", + "
" + ], + "text/plain": [ + " Category Statistic original \\\n", + "0 Global stats Nodes 876250 \n", + "1 Global stats Edges 13667990 \n", + "2 Global stats Density 0.0 \n", + "3 Global stats Average degree 15.6 \n", + "4 Global stats Zero deg nodes 120490 \n", + "5 Global stats Zero in deg nodes 120490 \n", + "6 Global stats Zero out deg nodes 120490 \n", + "7 Global stats Self loops 39 \n", + "8 Global stats Bidirectional edges 13667951 \n", + "9 Global stats Unique undirected edges 13667951 \n", + "10 Global stats Unique directed edges 27335902 \n", + "11 Connectivity Is connected False \n", + "12 Connectivity Number of connected components 120491 \n", + "13 Connectivity Percent of nodes in largest component 86.25 \n", + "14 Transitivity Clustering coefficient 0.036935 \n", + "15 Path stats 90% effective diameter 3.59 \n", + "16 Path stats Approx. full diameter 6 \n", + "17 Path stats Average shortest path length 3.1 \n", + "\n", + " properly_generated randomly_generated \n", + "0 1169052 1169067 \n", + "1 13667161 13668210 \n", + "2 0.0 0.0 \n", + "3 11.69 11.69 \n", + "4 241368 123235 \n", + "5 241368 123235 \n", + "6 241368 123235 \n", + "7 55 8 \n", + "8 13667106 13668202 \n", + "9 13667106 13668202 \n", + "10 27334212 27336404 \n", + "11 False False \n", + "12 241369 123236 \n", + "13 79.35 89.46 \n", + "14 0.000611 0.000637 \n", + "15 4.11 3.89 \n", + "16 6 6 \n", + "17 3.91 3.83 " + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = graph_analyser.compare_graph_stats(*all_graphs)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "00c890ed", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABb0AAAIoCAYAAABNtEarAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdeVxU9f7H8dfMsCugKKCpiPueBC5pmmh21UpTKy3rZmnWT6lU9KZ1b4stV8s0y0jTbmpl1/blZmlpmuauqFmmua+ACwoCss2c3x8jIyMgqMCwvJ89eMj5nu8553POwOnwme98vibDMAxERERERERERERERCoAs6sDEBEREREREREREREpLkp6i4iIiIiIiIiIiEiFoaS3iIiIiIiIiIiIiFQYSnqLiIiIiIiIiIiISIWhpLeIiIiIiIiIiIiIVBhKeouIiIiIiIiIiIhIhaGkt4iIiIiIiIiIiIhUGEp6i4iIiIiIiIiIiEiFoaS3iIiIiIiIiIiIiFQYSnqLSIUQGhrKQw895OowHF544QVMJpOrw3AZk8nECy+84FieP38+JpOJgwcPlvixH3roIUJDQx3LBw8exGQy8frrr5f4sUGvvYiIiIiUL3p+FZGKSElvEbkqOUnMzZs3uzoUqaDS0tJ44YUXWLlypatDyaMsxyYiIiIipaewv4siIyNp3bp1KUdVet555x3mz5/v6jBERPJQ0ltERErc3//+d86fP0/9+vWLvE1aWhqTJk264sTy3Llz2b179xVGeGUuF9u//vUvzp8/X6LHFxEREREpC5T0FpGySklvEZEKJD09HZvN5uow8rBYLHh5eZXoxyZTU1MBcHd3x9PTs8SOUxg3Nze8vLxcdnwRERERERGRyk5JbxEpUVu3bqVPnz74+flRtWpVbrnlFtavX5+n32+//Ua3bt3w9vambt26vPzyy8ybN++a6kDv37+fe+65h4CAAHx8fLjxxhtZvHhxnn6HDh2iX79+VKlShaCgIMaOHcvSpUsxmUxFGmX866+/0r59e7y8vGjUqBHvvvtugX0/+ugjIiIi8Pb2JiAggHvvvZcjR47k6RcTE0PDhg3x9vamQ4cOrF69msjISCIjIx19Vq5ciclkYtGiRfzrX/+iTp06+Pj4kJycDMCGDRvo3bs3/v7++Pj40K1bN9asWZPnWMeOHWPYsGEEBwfj6elJq1ateP/99ws9b4CMjAzGjh1LYGAgvr6+9OvXj6NHj+bpl19N782bN9OrVy9q1qyJt7c3DRo0YNiwYYC9DndgYCAAkyZNwmQyOdUJf+ihh6hatSr79u3jtttuw9fXl/vvv9+xLndN79zeeOMN6tevj7e3N926deP33393Wn/pNc6Re5+FxZZfTcTs7GxeeuklGjVqhKenJ6GhoTzzzDNkZGQ49QsNDeWOO+7g119/pUOHDnh5edGwYUM++OCDfM9HRERERMqfK302/PHHHwkLC8PLy4uWLVvy5ZdfFnqM3PPaFPYMfLUxhoaG8scff/DLL784nonze5YWEXEFN1cHICIV1x9//EHXrl3x8/Pjqaeewt3dnXfffZfIyEh++eUXOnbsCNiTrt27d8dkMvH0009TpUoV3nvvvWsarZuQkEDnzp1JS0vjySefpEaNGixYsIB+/frx+eefM2DAAMA+OrhHjx7ExcUxevRoatWqxccff8yKFSuKdJwdO3bwt7/9jcDAQF544QWys7N5/vnnCQ4OztP3lVde4dlnn2XQoEE88sgjnDx5kpkzZ3LzzTezdetWqlWrBsCsWbN4/PHH6dq1K2PHjuXgwYP079+f6tWrU7du3Tz7femll/Dw8GD8+PFkZGTg4eHBzz//TJ8+fYiIiOD555/HbDYzb948evTowerVq+nQoYPjOt14442YTCYef/xxAgMD+eGHHxg+fDjJycmMGTPmsuf/yCOP8NFHHzFkyBA6d+7Mzz//zO23317odTtx4oTjuk2cOJFq1apx8OBBxwN8YGAgs2bNYuTIkQwYMICBAwcCcP311zv2kZ2dTa9evejSpQuvv/46Pj4+lz3mBx98wLlz54iKiiI9PZ0333yTHj16sGPHjnxfr4IUJbZLPfLIIyxYsIC7776bcePGsWHDBiZPnsyff/7JV1995dR379693H333QwfPpyhQ4fy/vvv89BDDxEREUGrVq2KHKeIiIiIlJ6kpCROnTqVpz0rKytP25U8G+7Zs4fBgwfzf//3fwwdOpR58+Zxzz33sGTJEm699dZC47raZ+CixDhjxgyeeOIJqlatyj//+U+AK3quFhEpUYaIyFWYN2+eARibNm0qsE///v0NDw8PY9++fY6248ePG76+vsbNN9/saHviiScMk8lkbN261dF2+vRpIyAgwACMAwcOFBpP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K6+4vN2yUNWqVTV9+nS1aNFCLVq00Ny5c+VwODR9+nS1atVKzZo104wZM3To0CEtX75ckjRmzBhNmjRJ/fr1U8OGDdWvXz+9+OKL+vDDD915OAAAAIBb1qpVKw0YMEDvvfeey/LOnTvr5MmTevPNN7V3714lJydr4cKFpbbf5ORkzZs3Tzt27FBSUpLOnDmjxx9/XJKUlJSkzMxMPfroo0pNTdXevXv17bffasiQIbLb7cXaz8svv6w33nhDc+fO1c6dOzVq1Cilp6fr+eefL7XHIkndunVzHssNGzYoJSVFAwcO1D333KO4uDjndgEBARo0aJA2bdqkH374Qc8995z69++v8PBw7d+/X6NHj9aaNWt08OBBfffdd9q9e7fzjwEAUFwUvQGgAjFNU4ZhaNOmTcrJyVGNGjVc+v3t37/f2etv586dSkhIcLn/1belyyf7fn5+ztubNm3Snj17FBQU5Bw3NDRUeXl52rt3r3Jzc7V3714NHTrUZd+vvfaaS59BAAAAoLwbN27cNW06mjVrpg8++EDJyclq3bq1UlJSNHLkyFLb58SJEzVx4kS1bt1aq1at0ldffaWwsDBJcl6dbbfbdf/996tVq1Z64YUXVK1aNZf+4UXx3HPPacSIEXrppZfUqlUrLVq0SF999ZUaN25cao9FutzqZMGCBapevbo6deqkbt26qVGjRpo7d67Ldrfffrv69eun3/3ud7r//vsVExPjbJFYpUoV7dixQw8++KCaNGmiYcOGKSkpSU899VSpZgXgPQzz6kZVAABLDR48WGfPntX8+fOvWRcTE6P69evr7rvv1pQpU5xXXl+pWrVqCgsLU/Xq1fXuu+9q4MCBznUjRozQ0qVLnW/PvN6+hg8frg0bNmj27NnXjF2zZk3l5eUpPDxcf//739W+fXuX9TabTQ0bNrylxw0AAADAM40dO1bz588v1TYxAHAzvlYHAAAUzdKlS7Vlyxa9+OKLioyM1PHjx+Xr66uoqKjrbh8dHa3U1FSXondqaupv7qdt27aaO3euatWqpeDg4GvWh4SEKCIiQvv27dOAAQNu+fEAAAAAAACUBYreAFAO5efn6/jx47Lb7crIyNCiRYs0YcIE9ejRQwMHDpSPj486dOigPn366M0331STJk109OhRffPNN+rbt6/i4uL07LPP6sknn1RcXJzzE9A3b96sRo0a3XTfAwYM0FtvvaXevXtr3LhxioyM1MGDB/Wvf/1Lf/7znxUZGalXX31Vzz33nEJCQvTAAw8oPz9f69ev15kzZzRixAg3HSUAAAAAAIBr0dMbAMqhRYsWqU6dOoqKitIDDzygZcuW6b333tOCBQtks9lkGIb+85//qFOnTs4PqnzkkUd08OBB1a5dW9Ll4vXo0aM1cuRItW3bVvv379fgwYMVEBBw031XqVJFK1euVP369dWvXz81a9ZMQ4cOVV5envPK7yeeeELTp0/XjBkz1KpVK91zzz2aOXMmrU0AAAAAXGPs2LG0NgHgVvT0BgAvct999yk8PFyfffaZ1VEAAAAAAADKBO1NAMBDnT9/XtOmTVNiYqJsNpv+8Y9/6Pvvv9fixYutjgYAAAAAAFBmuNIbADzUhQsX1LNnT23cuFF5eXmKjo7W//zP/6hfv35WRwMAAAAAACgzFL0BAAAAAAAAAB6DD7IEAAAAAAAAAHgMit4AAAAAAAAAAI9B0RsAAAAAAAAA4DEoegMAAAAAAAAAPAZFbwAAAAAAAACAx6DoDQAAAAAAAADwGBS9AQAAAAAAAAAeg6I3AAAAAAAAAMBjUPQGAAAAAAAAAHiM/x/8cLIrE7AYJAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from matplotlib.pyplot import set_loglevel\n", + "set_loglevel('warning')\n", + "_ = graph_analyser.compare_graph_plots(*all_graphs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "25159f07", + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_ieee_demo.ipynb b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_ieee_demo.ipynb new file mode 100644 index 000000000..cdbbb3982 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/basic_examples/e2e_ieee_demo.ipynb @@ -0,0 +1,1547 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "8bf707e3", + "metadata": {}, + "source": [ + "# Copyright 2023 NVIDIA Corporation. All Rights Reserved.\n", + "#\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# http://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License.\n", + "# ==============================================================================" + ] + }, + { + "cell_type": "markdown", + "id": "9f8713aa", + "metadata": {}, + "source": [ + "# End to end graph generation demo (IEEE)" + ] + }, + { + "cell_type": "markdown", + "id": "8e8ba128", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "In this notebook, we have walked through the complete process of generating a synthetic dataset based on an IEEE dataset. The IEEE dataset includes information about e-commerce transactions, so it can be iterpret as bipartite graph (user / product) with edge features (transaction info).\n", + "\n", + "Content:\n", + "\n", + "1. [Prepare the original dataset](#1)\n", + "1. [Preprare SynGen Configuration](#2)\n", + "1. [Dataset Generation](#3)\n", + "1. [Tabular data evaluation](#4)\n", + "1. [Structure evaluation](#5)" + ] + }, + { + "cell_type": "markdown", + "id": "5be34106", + "metadata": {}, + "source": [ + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "11a97dc6", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n" + ] + } + ], + "source": [ + "# preprocessing\n", + "from syngen.preprocessing.datasets import IEEEPreprocessing\n", + "\n", + "# config\n", + "from syngen.configuration import SynGenConfiguration\n", + "\n", + "# generation\n", + "from syngen.synthesizer import ConfigurationGraphSynthesizer\n", + "\n", + "# evaluation\n", + "from syngen.analyzer.tabular import TabularMetrics\n", + "from syngen.analyzer.graph import Graph\n", + "from syngen.analyzer.graph.stats import get_dd_simmilarity_score\n", + "from syngen.analyzer.graph.analyser import AnalysisModule\n", + "\n", + "# utils\n", + "import copy\n", + "from syngen.utils.types import MetaData" + ] + }, + { + "cell_type": "markdown", + "id": "265e1651", + "metadata": {}, + "source": [ + "\n", + "## Prepare original dataset" + ] + }, + { + "cell_type": "markdown", + "id": "6730d3ff", + "metadata": {}, + "source": [ + "SynGen requires the data to be in SynGen dataset format or simply SynGen format, so firstly, we transform the raw Cora dataset into SynGen format. If you don't download IEEE before please follow the instruction in the `scripts/get_datasets.sh`" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "9566fbfe", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = '/workspace/data/ieee-fraud'\n", + "preprocessed_path = '/workspace/data/ieee_preprocessed'" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e8d95372", + "metadata": {}, + "outputs": [], + "source": [ + "preprocessing = IEEEPreprocessing(source_path=data_path, destination_path=preprocessed_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2d8fa083", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_original = preprocessing.transform(use_cache=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6f125c8c", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'nodes': [{'name': 'user',\n", + " 'count': 17090,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'product', 'count': 197, 'features': [], 'features_path': None}],\n", + " 'edges': [{'name': 'user-product',\n", + " 'count': 52008,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'product',\n", + " 'directed': False,\n", + " 'features': [{'name': 'TransactionDT',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'TransactionAmt',\n", + " 'dtype': 'float64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'C1', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C2', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C3', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C4', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C5', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C6', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C7', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C8', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C9', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C10', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C11', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C12', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C14', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V279', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V280', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V284', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V285', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V286', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V287', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V290', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V291', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V292', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V293', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V294', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V295', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V297', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V298', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V299', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V302', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V303', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V304', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V305', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V306', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V307', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V308', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V309', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V310', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V311', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V312', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V316', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V317', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V318', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V319', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V320', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V321', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'isFraud', 'dtype': 'int64', 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-product.parquet',\n", + " 'structure_path': 'user-product_edge_list.parquet'}],\n", + " : '/workspace/data/ieee_preprocessed'}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_original" + ] + }, + { + "cell_type": "markdown", + "id": "5e73d5ff", + "metadata": {}, + "source": [ + "\n", + "## Preprare SynGen Configuration" + ] + }, + { + "cell_type": "markdown", + "id": "ba90c49c", + "metadata": {}, + "source": [ + "SynGen generation process is driven by the configuration that is the superset of the SynGen format metadata file. Let us create two configurations: a proper one that will mimic Cora dataset tabular and structural features and a random one." + ] + }, + { + "cell_type": "markdown", + "id": "95081787", + "metadata": {}, + "source": [ + "### Proper Synthetic " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "8f66de61", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_synthetic = feature_spec_original.copy()\n", + "\n", + "feature_spec_synthetic[MetaData.EDGES][0][MetaData.TABULAR_GENERATORS] = [\n", + " {\n", + " MetaData.TYPE: \"kde\",\n", + " MetaData.FEATURES_LIST: -1, # copies all tabular features\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'configuration',\n", + " MetaData.PATH: preprocessed_path,\n", + " MetaData.NAME: \"user-product\",\n", + " },\n", + " MetaData.PARAMS: {\n", + " }\n", + " }\n", + "]\n", + "\n", + "feature_spec_synthetic[MetaData.EDGES][0][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'cfg', # the same a 'configuration'\n", + " MetaData.PATH: preprocessed_path,\n", + " MetaData.NAME: \"user-product\",\n", + " },\n", + " MetaData.PARAMS: {\n", + " \"has_self_loop\": False,\n", + " }\n", + "}\n", + "\n", + "# aligns 'TransactionAmt' edge feature based on the 'user-product' edges\n", + "feature_spec_synthetic[MetaData.ALIGNERS] = [\n", + " {\n", + " MetaData.TYPE: \"xgboost\",\n", + " MetaData.GRAPHS: ['user-product'],\n", + " MetaData.NODES: {},\n", + " MetaData.EDGES: {\"user-product\": [\"TransactionAmt\"]},\n", + " MetaData.PARAMS: {},\n", + " }\n", + "]\n", + "\n", + "config_proper = SynGenConfiguration(feature_spec_synthetic)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4e96fa89", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-product',\n", + " 'count': 52008,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'product',\n", + " 'directed': False,\n", + " 'features': [{'name': 'TransactionDT',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'TransactionAmt',\n", + " 'dtype': 'float64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'C1', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C2', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C3', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C4', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C5', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C6', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C7', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C8', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C9', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C10', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C11', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C12', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C14', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V279', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V280', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V284', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V285', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V286', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V287', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V290', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V291', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V292', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V293', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V294', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V295', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V297', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V298', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V299', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V302', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V303', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V304', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V305', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V306', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V307', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V308', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V309', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V310', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V311', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V312', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V316', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V317', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V318', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V319', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V320', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V321', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'isFraud', 'dtype': 'int64', 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-product.parquet',\n", + " 'structure_path': 'user-product_edge_list.parquet',\n", + " : [{: 'kde',\n", + " : ['TransactionDT',\n", + " 'TransactionAmt',\n", + " 'C1',\n", + " 'C2',\n", + " 'C3',\n", + " 'C4',\n", + " 'C5',\n", + " 'C6',\n", + " 'C7',\n", + " 'C8',\n", + " 'C9',\n", + " 'C10',\n", + " 'C11',\n", + " 'C12',\n", + " 'C14',\n", + " 'V279',\n", + " 'V280',\n", + " 'V284',\n", + " 'V285',\n", + " 'V286',\n", + " 'V287',\n", + " 'V290',\n", + " 'V291',\n", + " 'V292',\n", + " 'V293',\n", + " 'V294',\n", + " 'V295',\n", + " 'V297',\n", + " 'V298',\n", + " 'V299',\n", + " 'V302',\n", + " 'V303',\n", + " 'V304',\n", + " 'V305',\n", + " 'V306',\n", + " 'V307',\n", + " 'V308',\n", + " 'V309',\n", + " 'V310',\n", + " 'V311',\n", + " 'V312',\n", + " 'V316',\n", + " 'V317',\n", + " 'V318',\n", + " 'V319',\n", + " 'V320',\n", + " 'V321',\n", + " 'isFraud'],\n", + " : {: 'configuration',\n", + " : '/workspace/data/ieee_preprocessed',\n", + " : 'user-product'},\n", + " : {}}],\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/ieee_preprocessed',\n", + " : 'user-product'},\n", + " : {'has_self_loop': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 17090,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'product', 'count': 197, 'features': [], 'features_path': None}],\n", + " : [{: 'xgboost',\n", + " : ['user-product'],\n", + " : {},\n", + " : {'user-product': ['TransactionAmt']},\n", + " : {}}]}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config_proper" + ] + }, + { + "cell_type": "markdown", + "id": "24d7aef4", + "metadata": {}, + "source": [ + "### Random " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "f4c4b214", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_random = feature_spec_original.copy() \n", + "\n", + "feature_spec_random[MetaData.EDGES][0][MetaData.TABULAR_GENERATORS] = [\n", + " {\n", + " MetaData.TYPE: \"random\",\n", + " MetaData.FEATURES_LIST: -1, # copies all tabular features\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'random',\n", + " },\n", + " MetaData.PARAMS: {\n", + " }\n", + " }\n", + "]\n", + "\n", + "feature_spec_random[MetaData.EDGES][0][MetaData.STRUCTURE_GENERATOR] = {\n", + " MetaData.TYPE: \"RMAT\",\n", + " MetaData.DATA_SOURCE: {\n", + " MetaData.TYPE: 'rnd', # the save as 'random' \n", + " },\n", + " MetaData.PARAMS: {\n", + " \"has_self_loop\": False,\n", + " }\n", + "}\n", + "\n", + "config_random = SynGenConfiguration(feature_spec_random)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "221dacea", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-product',\n", + " 'count': 52008,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'product',\n", + " 'directed': False,\n", + " 'features': [{'name': 'TransactionDT',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'TransactionAmt',\n", + " 'dtype': 'float64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'C1', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C2', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C3', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C4', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C5', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C6', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C7', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C8', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C9', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C10', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C11', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C12', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C14', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V279', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V280', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V284', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V285', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V286', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V287', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V290', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V291', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V292', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V293', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V294', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V295', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V297', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V298', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V299', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V302', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V303', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V304', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V305', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V306', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V307', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V308', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V309', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V310', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V311', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V312', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V316', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V317', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V318', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V319', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V320', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V321', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'isFraud', 'dtype': 'int64', 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-product.parquet',\n", + " 'structure_path': 'user-product_edge_list.parquet',\n", + " : [{: 'random',\n", + " : ['TransactionDT',\n", + " 'TransactionAmt',\n", + " 'C1',\n", + " 'C2',\n", + " 'C3',\n", + " 'C4',\n", + " 'C5',\n", + " 'C6',\n", + " 'C7',\n", + " 'C8',\n", + " 'C9',\n", + " 'C10',\n", + " 'C11',\n", + " 'C12',\n", + " 'C14',\n", + " 'V279',\n", + " 'V280',\n", + " 'V284',\n", + " 'V285',\n", + " 'V286',\n", + " 'V287',\n", + " 'V290',\n", + " 'V291',\n", + " 'V292',\n", + " 'V293',\n", + " 'V294',\n", + " 'V295',\n", + " 'V297',\n", + " 'V298',\n", + " 'V299',\n", + " 'V302',\n", + " 'V303',\n", + " 'V304',\n", + " 'V305',\n", + " 'V306',\n", + " 'V307',\n", + " 'V308',\n", + " 'V309',\n", + " 'V310',\n", + " 'V311',\n", + " 'V312',\n", + " 'V316',\n", + " 'V317',\n", + " 'V318',\n", + " 'V319',\n", + " 'V320',\n", + " 'V321',\n", + " 'isFraud'],\n", + " : {: 'random'},\n", + " : {}}],\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {'has_self_loop': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 17090,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'product', 'count': 197, 'features': [], 'features_path': None}]}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config_random" + ] + }, + { + "cell_type": "markdown", + "id": "bf3664c9", + "metadata": {}, + "source": [ + "\n", + "## Dataset Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "e492fec0", + "metadata": {}, + "outputs": [], + "source": [ + "save_path_proper = '/workspace/data/ieee_generated'\n", + "save_path_random = '/workspace/data/ieee_random'" + ] + }, + { + "cell_type": "markdown", + "id": "25f9da8e", + "metadata": {}, + "source": [ + "### Create Synthesizers" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "8cc867ca", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_proper = ConfigurationGraphSynthesizer(configuration=config_proper, save_path=save_path_proper, gpu=True)\n", + "synthesizer_random = ConfigurationGraphSynthesizer(configuration=config_random, save_path=save_path_random, gpu=True)" + ] + }, + { + "cell_type": "markdown", + "id": "ef319ad2", + "metadata": {}, + "source": [ + "### Fit Synthesizers" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "46f356c9", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_proper.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "34fa9194", + "metadata": {}, + "outputs": [], + "source": [ + "synthesizer_random.fit()" + ] + }, + { + "cell_type": "markdown", + "id": "f7a396a0", + "metadata": {}, + "source": [ + "### Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "63be2229", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_generated_proper = synthesizer_proper.generate()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "771052fe", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-product',\n", + " 'count': 52008,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'product',\n", + " 'directed': False,\n", + " 'features': [{'name': 'TransactionDT',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'TransactionAmt',\n", + " 'dtype': 'float64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'C1', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C2', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C3', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C4', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C5', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C6', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C7', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C8', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C9', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C10', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C11', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C12', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C14', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V279', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V280', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V284', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V285', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V286', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V287', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V290', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V291', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V292', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V293', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V294', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V295', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V297', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V298', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V299', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V302', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V303', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V304', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V305', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V306', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V307', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V308', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V309', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V310', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V311', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V312', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V316', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V317', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V318', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V319', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V320', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V321', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'isFraud', 'dtype': 'int64', 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-product.parquet',\n", + " 'structure_path': 'user-product_edge_list.parquet',\n", + " : [{: 'kde',\n", + " : ['TransactionDT',\n", + " 'TransactionAmt',\n", + " 'C1',\n", + " 'C2',\n", + " 'C3',\n", + " 'C4',\n", + " 'C5',\n", + " 'C6',\n", + " 'C7',\n", + " 'C8',\n", + " 'C9',\n", + " 'C10',\n", + " 'C11',\n", + " 'C12',\n", + " 'C14',\n", + " 'V279',\n", + " 'V280',\n", + " 'V284',\n", + " 'V285',\n", + " 'V286',\n", + " 'V287',\n", + " 'V290',\n", + " 'V291',\n", + " 'V292',\n", + " 'V293',\n", + " 'V294',\n", + " 'V295',\n", + " 'V297',\n", + " 'V298',\n", + " 'V299',\n", + " 'V302',\n", + " 'V303',\n", + " 'V304',\n", + " 'V305',\n", + " 'V306',\n", + " 'V307',\n", + " 'V308',\n", + " 'V309',\n", + " 'V310',\n", + " 'V311',\n", + " 'V312',\n", + " 'V316',\n", + " 'V317',\n", + " 'V318',\n", + " 'V319',\n", + " 'V320',\n", + " 'V321',\n", + " 'isFraud'],\n", + " : {: 'configuration',\n", + " : '/workspace/data/ieee_preprocessed',\n", + " : 'user-product'},\n", + " : {'gpu': True, 'verbose': False}}],\n", + " : {: 'RMAT',\n", + " : {: 'cfg',\n", + " : '/workspace/data/ieee_preprocessed',\n", + " : 'user-product'},\n", + " : {'has_self_loop': False,\n", + " 'gpu': True,\n", + " 'verbose': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 17090,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'product', 'count': 256, 'features': [], 'features_path': None}],\n", + " : [{: 'xgboost',\n", + " : ['user-product'],\n", + " : {},\n", + " : {'user-product': ['TransactionAmt']},\n", + " : {}}],\n", + " : '/workspace/data/ieee_generated'}" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_generated_proper" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "1e0803a7", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_generated_random = synthesizer_random.generate()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "5fbc0566", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{: [{'name': 'user-product',\n", + " 'count': 52008,\n", + " 'src_node_type': 'user',\n", + " 'dst_node_type': 'product',\n", + " 'directed': False,\n", + " 'features': [{'name': 'TransactionDT',\n", + " 'dtype': 'int64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'TransactionAmt',\n", + " 'dtype': 'float64',\n", + " 'feature_type': 'continuous'},\n", + " {'name': 'C1', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C2', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C3', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C4', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C5', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C6', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C7', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C8', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C9', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C10', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C11', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C12', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'C14', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V279', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V280', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V284', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V285', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V286', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V287', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V290', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V291', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V292', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V293', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V294', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V295', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V297', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V298', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V299', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V302', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V303', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V304', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V305', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V306', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V307', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V308', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V309', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V310', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V311', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V312', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V316', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V317', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V318', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V319', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V320', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'V321', 'dtype': 'float64', 'feature_type': 'continuous'},\n", + " {'name': 'isFraud', 'dtype': 'int64', 'feature_type': 'categorical'}],\n", + " 'features_path': 'user-product.parquet',\n", + " 'structure_path': 'user-product_edge_list.parquet',\n", + " : [{: 'random',\n", + " : ['TransactionDT',\n", + " 'TransactionAmt',\n", + " 'C1',\n", + " 'C2',\n", + " 'C3',\n", + " 'C4',\n", + " 'C5',\n", + " 'C6',\n", + " 'C7',\n", + " 'C8',\n", + " 'C9',\n", + " 'C10',\n", + " 'C11',\n", + " 'C12',\n", + " 'C14',\n", + " 'V279',\n", + " 'V280',\n", + " 'V284',\n", + " 'V285',\n", + " 'V286',\n", + " 'V287',\n", + " 'V290',\n", + " 'V291',\n", + " 'V292',\n", + " 'V293',\n", + " 'V294',\n", + " 'V295',\n", + " 'V297',\n", + " 'V298',\n", + " 'V299',\n", + " 'V302',\n", + " 'V303',\n", + " 'V304',\n", + " 'V305',\n", + " 'V306',\n", + " 'V307',\n", + " 'V308',\n", + " 'V309',\n", + " 'V310',\n", + " 'V311',\n", + " 'V312',\n", + " 'V316',\n", + " 'V317',\n", + " 'V318',\n", + " 'V319',\n", + " 'V320',\n", + " 'V321',\n", + " 'isFraud'],\n", + " : {: 'random'},\n", + " : {'gpu': True, 'verbose': False}}],\n", + " : {: 'RMAT',\n", + " : {: 'rnd'},\n", + " : {'has_self_loop': False,\n", + " 'gpu': True,\n", + " 'verbose': False}}}],\n", + " : [{'name': 'user',\n", + " 'count': 17090,\n", + " 'features': [],\n", + " 'features_path': None},\n", + " {'name': 'product', 'count': 256, 'features': [], 'features_path': None}],\n", + " : '/workspace/data/ieee_random'}" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "feature_spec_generated_random" + ] + }, + { + "cell_type": "markdown", + "id": "e225ac7e", + "metadata": {}, + "source": [ + "\n", + "## Tabular Data Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "1d487b64", + "metadata": {}, + "outputs": [], + "source": [ + "original_tabular_data, categorical_features = feature_spec_original.get_tabular_data(MetaData.EDGES, 'user-product', return_cat_feats=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "c7afb31c", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "proper_tabular_data = feature_spec_generated_proper.get_tabular_data(MetaData.EDGES, 'user-product')" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "9064457c", + "metadata": {}, + "outputs": [], + "source": [ + "random_tabular_data = feature_spec_generated_random.get_tabular_data(MetaData.EDGES, 'user-product')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "82d9a2de", + "metadata": {}, + "outputs": [], + "source": [ + "tab_eval = TabularMetrics(original_tabular_data, \n", + " proper_tabular_data, \n", + " categorical_columns=categorical_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "4773eb5e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABjUAABsFCAYAAABo8KaqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd5wTdf7H8fck2cICS196damCFAEFBekiKoJYkWavZy+Ih+UUUX9nL3d6IoLlVPQsJ0VAQU7BgigKWEDBpborCCss7KbM748ly5bsbpJNdjLJ6/l43Mkmk+98JmXeST6Z+RqmaZoCAAAAAAAAAACIcQ6rCwAAAAAAAAAAAAgGTQ0AAAAAAAAAAGALNDUAAAAAAAAAAIAt0NQAAAAAAAAAAAC2QFMDAAAAAAAAAADYAk0NAAAAAAAAAABgCzQ1AAAAAAAAAACALdDUAAAAAAAAAAAAtkBTAwAAAAAAAAAA2AJNDQAAgDi3ZMkSXXjhherQoYPS09OVkpKipk2bavjw4Xr00UeVk5NjdYlRcffdd8swDN19993Vts42bdrIMAxt2bKl2tYZqp07d2rq1Knq0aOHateureTkZDVr1kw9e/bUpZdeqhdffFFer9fqMlGB2bNnq3fv3qpZs6YMw4j55xwAAAAQSS6rCwAAAEB0/P777zr//PO1dOlSSYVfuA8ePFg1a9bUrl27tHLlSi1dulR33nmnli5dquOOO87iimPblClTNGfOHM2ePVtTpkyxupywrFy5Uqeeeqr27t2rWrVqqW/fvmrcuLH279+v7777Ts8//7yef/55nXXWWapVq5bV5SKA+fPn66KLLlJqaqqGDRumBg0aSJIlj1ebNm3066+/avPmzWrTpk21rx8AAACJiaYGAABAHNq3b59OPPFE/fjjj+rUqZOee+45DRgwoMQy+fn5mjNnju666y7t3LnTokrjy4cffii3263mzZtbXUoZ+fn5Ouecc7R3716NHz9e//jHP5Senl5imR9++EEvvPCCnE6nRVWiMvPmzZMkPfHEE7r00kstrgYAAACofjQ1AAAA4tBf/vIX/fjjj2rTpo0+/fRT1a9fv8wyKSkpuuyyy3TGGWdo79691V9kHDrqqKOsLqFcn3zyibZv3y6Xy6XnnntONWvWLLNMp06d9NBDD1lQHYKVlZUlSWrfvr3FlQAAAADWYE4NAACAOPPLL7/o1VdflSQ98sgjARsaxTVu3FgdO3Ys+nvKlCkyDEMvvvhiwOVffPFFGYZR5hRMxS/ft2+fbrzxRrVp00apqalq3769HnzwQfl8PknS9u3bdfnll6tly5ZKSUlRx44d9eSTTwZcX2XzVFRWb2lut1svv/yyLrjgAnXq1Enp6emqUaOGOnbsqGuvvVY7duwosfyWLVtkGIbmzJkjSbrwwguL5jEoPWdH6Vq9Xq9atGghwzD02WeflVvTzTffLMMwdMMNN5S57sMPP9SZZ56ppk2bKjk5WRkZGRo7dqxWrVoV1Pb6/fbbb5IKT1MUqKFRkXAfg+KX//jjjzr33HOVkZGhmjVrqk+fPnr33XeLlv388881evRoNWrUSDVq1FC/fv304YcfBlzfxo0bddFFF6lt27ZKSUlRrVq11Lp1a5166qmaPXt20Nu1fPlyGYahQYMGKS8vT9OmTVNmZqZSU1PVrFkzXXzxxdq+fXu5t//jjz901113Fc1PkpaWpm7duum+++5TXl5emeWLz/OSlZWliy++WC1btlRSUlKlpzTz35fLli2TJA0ePLjoOVj6tjt27NCNN96ozp07Ky0tTbVr11afPn301FNPyePxlBk7JydHTzzxhEaNGqW2bduqRo0aSk9PV+/evfXggw/q0KFDJZb3v9Z//fVXSVLbtm1LvCaWL19eYrnyts3/2ip96qril3u9Xj3yyCPq2bOnatWqJcMwSiz7008/6fLLL9dRRx2l1NRU1alTRwMHDtTLL79c4f0JAAAA++JIDQAAgDjz/vvvy+v1qm7duho9enS1r3/v3r3q16+fdu/erQEDBujPP//U//73P02dOlXbtm3T9ddfrxNPPFFJSUnq37+/cnJytGLFCl177bXKy8vTbbfdFtX6fvvtN02cOFF16tRR586ddcwxx+jAgQP65ptv9OSTT+q1117TypUrlZmZKamwCTB58mR98skn+vnnn3XCCScUXSdJPXr0KHddTqdTkyZN0syZM/Xiiy/q+OOPL7OMx+Mp+gL2oosuKnHdzTffrIcfflgOh0O9e/fWgAEDlJWVpXfffVf//e9/9a9//UsXXnhhUNvdqlUrSYWPz4svvlit84KsWbNG11xzjVq0aKGhQ4fq119/1apVqzR27Fi98cYbcrlcOuecc9S1a1cNHTpUP/zwgz777DONHDlSy5Yt04knnlg01rp163TCCScoNzdXHTt21GmnnSan06lt27ZpxYoV2r59e9D3iV9BQYGGDh2qb7/9VoMGDVKvXr30ySef6IUXXtCCBQu0YsWKMkdGbNiwQSNHjtTWrVvVtGnTouf0F198oenTp+utt97S8uXLVadOnTLr27hxo3r27Knk5GSdcMIJMk1TDRs2rLBG/32waNEi/fbbbzr55JPVpEmTEtdJ0ooVKzRmzBj98ccfatOmjYYPH678/Hx98cUX+stf/qL//ve/ev/995WUlFR0mw8++EDXXXedmjdvrszMTB1//PHKycnR559/rqlTp+rdd9/VsmXLlJKSIknKzMzU5MmT9eabb+rAgQMaN25ciTk9/HVVlWmaOvPMM7Vo0SINGDBAnTt31vr164uunzdvniZNmqRDhw6pU6dOGjVqlPbt26fPP/9cEydO1EcffaQXXnghIrUAAAAghpgAAACIKxMnTjQlmUOGDAnr9pMnTzYlmbNnzw54/ezZs01J5uTJkwNeLsk8/fTTzQMHDhRd99VXX5kul8t0OBxmly5dzCuuuMJ0u91F17/zzjumJDM9Pb3E7UzTNFu3bm1KMjdv3hxSvXfddZcpybzrrrtKXJ6bm2u+++67Zn5+fonLCwoKzNtvv92UZI4aNSrk+6W8Wn/66SdTklm3bl3z4MGDZW7z7rvvmpLMY489tsTlzz33nCnJzMzMNNeuXVviuo8//tisXbu2mZycbP7000/l1lOc1+s1e/bsWfQY9enTx7zjjjvMt99+29y6dWuFtw33MfBfLsm87777TJ/PV3TdE088YUoyW7RoYdarV8+cO3duidtef/31piRz2LBhJS6/8MILi8YrLS8vz/z4448r3Jbili1bVlRfZmam+euvvxZdd/DgQXPcuHGmJPP4448vs56jjjrKlGT+9a9/LfFcOnDggHn++eebkswLL7ywxO38z0lJ5oQJE8xDhw4FXavfSSedZEoyly1bVua6nTt3mg0aNDANwzCfeeYZ0+v1Fl33+++/m0OGDDElmffcc0+J223YsMFctWpVmfH27NljjhgxwpRkPvTQQ2Wur+x5Ud6+wm/z5s2mJLN169YBL/c/P3788ccyt/3222/NlJQUMzU11XzrrbdKXLdlyxazW7dupiRzzpw5AdcNAAAA++L0UwAAAHEmJydHkpSRkWHJ+mvVqqXnn39eaWlpRZf16tVLo0aNks/n0/79+/Xoo4/K5Tpy0PAZZ5yhbt26KTc3V6tXr45qfbVr19bo0aOVnJxc4vKkpCTdf//9atasmRYtWqQ///wzIutr3769BgwYoL179+rtt98uc73/dEnFjy7w+XxFp7V67bXXdMwxx5S4zcCBAzV9+nQVFBTo2WefDaoOh8Oh+fPn65RTTpEkffnll5oxY4bGjh2rli1bqmPHjnrwwQd18ODBcDazQn379tW0adNKnDroyiuvVP369bVt2zYNGzZMEydOLHGbv/71r5IKjzxwu91Fl/tPozVq1Kgy66lRo4YGDhwYVo1///vfi45mkaTU1FQ988wzSktL02effaaVK1cWXTdnzhz9/PPPOu2003TvvfeWeC6lpaXpueeeU0ZGhl566SX98ccfZdZVv359PfXUU0VHPkTKY489pt27d+vqq6/WlVdeKYfjyMe9Bg0aaO7cuUpKStJTTz0l0zSLruvcuXPAo4jq1atXdFo4/wTl1e3+++9Xhw4dylw+Y8YM5efn67777tOZZ55Z4rrWrVtr1qxZkgonVAcAAEB8oakBAACAiDr22GMDNlT8p+8ZPHiwUlNTy72+9JwW0bJ27Vo98sgj+stf/qKLLrpIU6ZM0ZQpU+TxeOTz+bRp06aIrcvfsCg950ROTo7mz5+vlJQUjR8/vujyr7/+Wjt27NBRRx2lY489NuCYgwYNkqQSX7ZXpmnTplqwYIHWrVun+++/X6effrqaN28uqXBugqlTp6pfv34Rnzj+lFNOKTMXgsvlUtu2bSUFblA0aNBA9evXV0FBgXbv3l10ed++fSUVNkU++OCDMvM9hKO8U7VlZGRo5MiRklQ0T4QkzZ8/X5J07rnnBhyvVq1a6t27tzwej7788ssy1w8bNizgaamqqrK6mjdvrvbt2ysnJ0cbN24scZ3X69WHH36oe++9V1dddZUuvPBCTZkyRTNmzJAk/fjjjxGvNxjjxo0rc5nP59PChQsllb+tvXv3Vq1atfT1119H5DkCAACA2MGcGgAAAHGmUaNGkqTs7GxL1l/81+7F+c+5X971tWvXlqSofwF54MABTZw4MeBRE8Xl5uZGbJ3nnHOOrr32Wi1dulTbtm1TixYtJEkvv/yy3G63zj33XNWrV69o+V9++UWS9PPPP5dpBpTmPzInFEcffbSOPvroor+///57PfPMM3r66ae1du1a3XHHHXr66adDHrc8VXlO7Nmzp8Rz4pZbbtEnn3yipUuXauTIkUpKSlL37t01cOBAnXfeeerTp0/I9fknQg/E33jZtm1b0WX+x2fixIlljjApLdDjU3pi7Ejx1zVgwIBKl83JySk6AmLjxo0aO3ZsifkqSovk6yFYGRkZJY748tu9e3dRPS1btqx0nN27dxc17wAAAGB/NDUAAADizLHHHquXXnpJa9askdfrldPpjOj4Pp+vwuuLn/ImnOtDVVk9pd1+++16++231alTJz3wwAPq06ePGjZsWHQKof79+2vVqlUlTs9TVTVr1tQ555yjF154QXPnztW0adMkHTlyo/TE1v5tatKkiU4++eQKx65sgulgdO7cWU8++aQcDoeeeOIJvfPOOyE1NarzOZGWlqYlS5boyy+/1KJFi7Ry5UqtXLlSq1ev1iOPPKKrrroqog0Zv+LPB//2jhw5Uo0bN67wdq1bty5zWY0aNSJbXKm6zjrrLNWsWbPCZRs0aFD077POOkvr16/XaaedpltvvVVdunRRenq6kpKSVFBQEPHTZJWutzzl3U/Fbzd58uRK1xOt+gEAAGANmhoAAABx5rTTTtONN96ovXv36r333tPYsWNDur3/y/3y5pT49ddfq1xjKCJdzxtvvCFJev3118vMVSGpzGl5IuXCCy/UCy+8oBdffFHTpk3TmjVr9O2336pFixYaPnx4iWX9vz5v0KBBmVNWRdOIESP0xBNP6Pfffy9xeaw9JySpT58+RUdleDwevfPOO5o0aZKeeeYZnXXWWRo8eHDQY23ZsqXS6/xH10iFj88PP/ygiy++WGeddVZY9UdDy5YttXHjRt12223q3bt3ULf54Ycf9O233yojI0Nvv/12iblupKq9HqL1vGnYsKFq1KihgwcP6u9//3tEGnsAAACwD+bUAAAAiDNHHXWUzj//fEnSTTfdpD179lS4fHZ2donz5ftP0/L999+XWdY0zaJz2VeXiurZtWuX1qxZE9J4/vsj0C/oP/jggzJf6Pv5v6D1eDwhrc/vxBNPVIcOHbRx40Z9+umnRROET548ucyRCv6jRzZs2FDhKYFCEcyRJ1lZWZJKfoEvRf4xiDSXy6Wzzjqr6KiWb775JqTb7927V//973/LXJ6Tk6NFixZJOjKHiaSiydb9DbJYEU5d/tdDs2bNyjQ0pMJTpJWnsteE/3nzww8/BLzePwdIqJxOZ1EjMNYeAwAAAEQfTQ0AAIA49OSTTyozM1ObN2/WiSeeqE8++aTMMgUFBXrhhRfUs2fPEl9WDxs2TJL00ksvacOGDUWXu91u3XbbbQEnPo4mfz0PPvhgiQmsc3JyNGnSJO3fvz+k8Tp37iyp8D4q7scff9QVV1xR7u38X/RXpcngP83UP//5T7366quSpClTppRZLikpSXfddZdM09TYsWMDPn5er1cfffSRPvvss6DW/d///ldjxozRkiVL5PV6y1y/fPly3X333ZKk8847r8R1kX4MquKZZ54JOGn1rl27tHr1akmBG1aVuemmm0rMm5Gfn6+rr75aBw4cUN++fXXCCScUXXfZZZepdevWmjdvnm677baARyLs2rVL//rXv0KuoypuueUW1a1bV4888ogefvhhFRQUlFlm8+bNJRoVHTp0kNPp1HfffVdiMnSp8Dnz6KOPlru+yl4Tffv2VXp6ujZs2KCXXnqpxHXz5s3TE088EeymlXHXXXcpOTlZt9xyi+bMmRPwVFbr1q3Tf/7zn7DXAQAAgNhEUwMAACAO1atXT59++qkGDRqk77//XgMGDFC7du00ZswYjR8/XkOHDlWDBg108cUXa//+/WrWrFnRbU844QSdccYZ2r9/v3r37q0RI0bojDPOULt27fTss8/quuuuq9Ztufrqq9W6dWutWbNGHTt21JgxYzR8+HC1b99eu3bt0pgxY0Ia76677pJhGJo+fbqOOeYYnX/++Ro6dKi6deumdu3aqX///gFvN2bMmKI5J4YPH66LLrpIl1xyid57772g1z1p0iQ5nU69/PLL2rNnjwYOHKjMzMyAy15zzTW65ZZbtHHjRg0YMEBdu3bVmDFjdP7552vw4MFq2LChhg4dGvRRCT6fT++++65GjBihBg0aaMiQIRo/frzOOOMMde7cWYMHD1Z2draGDRumO+64o8RtI/0YVMVzzz2nTp06qV27dho9erQmTJigk08+We3atdO2bds0ZMgQjR49OqQx+/Xrp/r166tjx446/fTTde6556pdu3aaN2+eMjIyNHfu3BLL16xZU/Pnz1ebNm300EMPqVWrVjrppJN0wQUXaOzYsTr66KPVrFkzTZ8+PZKbXqkWLVro3XffVb16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P9tEOS6NCR9joh2XqCrSc3Q8VD7f1RZnQ9+Ltcrnl1atWgU7fI0xZsSIEWbOnDmNei+WAt/nZNnvPp/PHHHEEeb77783hx56aLDTJhn2e6i8ngz7fceOHSYzM9Pk5+cnXexomOb6GSV7rmmsZM5VjZFsea6hkjk/Jgt3vO8USWRTpkzRddddpxNPPLHK66+99prOOeccffvtt3GKDEBzN3DgQP3222/xDgO1WLNmjbp06SK3259KLctSz549lZubq/79+weny83NVa9evYJ/9+7dW7m5uQkVoyQtX75ce++9t1wul8455xxdeumlTRJjJOK5D+sjkfbhQw89pOOOO67G66H25YYNG+T1eoPHSVMJF6Mk7dy5UyNGjJDP59OkSZN00003yeVyNWl8Z599tubOnStJmjVrVo33E+G4rCtGKbGOS1RVn3N0PNUWZ3Z2doPei/X2Bc4vW7duVXl5uTp37hx8L/Bdbeh7sVL9+5ws+/3+++/XgQceqH322Sf4WrLtd2OMRo4cqWnTpiXFfl++fLnatWunu+66Sx9++KHS09N12223qU2bNgkfOxomWfJFYyTDdy/akjFXNUay5rmGSvb8mAwoatRi+/btNQoaknTSSSfppptuikNEAJqTn3/+Oex7hYWFTRgJWrq9995ba9euVXZ2ttauXauJEyeqQ4cO+sMf/hDv0JJGIu3Du+66S8uWLdNHH33U5OuOVG0xdunSRevWrVNOTo62bdumU045Rffdd5+uvfbaJo3xueeekyQ9++yzuu6668IWDeKprhgT6bgEmkrl80syPUOm+vf5b3/7W5wjqtuCBQv0+uuvJ+243p999pl69uyp8vJy3XzzzZo8eXJS7Hev16vVq1dryJAhmjZtmn744QeNHTtWM2fOjHdoACKUrLmqMZIxzzVUsufHZMGDwmvRoUMHPf/883IcJ/ia4zh69tln1b59+zhGBqA5GD58uCZNmqTjjjuuxr+tW7fGOzzUoUePHsFfuEuSMUa5ubnq2bNnlel69uyp1atXB/9etWpVjWniHWNWVpays7MlSd27d9dpp52mzz//vElijEQ892GkEmUf3nvvvXrjjTf03nvvKSMjo8b7ofZl5V86JUKMqampysnJkSS1a9dO5557blyPx8mTJ2vu3Lk1zsuJdFyGizFRjkuEFuk5Ot5qi7Oh78VK9fNL+/bt5Xa7tXHjxuA0ge9qQ9+LtcD3uXv37gm/3z///HOtWrVKAwYMUO/evfX111/rwgsv1CuvvJIU+z2wXI/Hoz//+c/6/PPPk+J479mzp2zb1hlnnCFJ2muvvdSnTx+tXr064WNHw7SEzygZvnvR0hxyVWMkU55rqGTPj0mjCYe6SjpLly41hx9+uMnOzjaDBw82gwcPNtnZ2Wb06NFmyZIl8Q4PQJLr3bu3WbduXcj3unfv3sTRoCEOPfTQKg8o22effWpMs3z58hoPE37kkUcSKsb169cbn89njDGmoKDAHHDAAebpp59ushiNqf15FfHehwG1xZgI+/C+++4ze++9t9m2bVvYaQoKCkzHjh2rPCj8qquuaqoQI4px06ZNwYfelZSUmJNOOsnccsstTRWi+f3336ucm998803TrVu34EMdA+J5XEYaYyIcl6hdJOfoeKh+vqstzoa+F23hzi+TJ0+u8mDNrl27Bs8xDX0vmmr7PifDfq+s8pjhib7fd+zYUeXBtffdd585+OCDg9uR6Pt97NixZubMmcYYY1asWGHat29v1q5dmxSxo2Ga42eUjLmmsZI1VzVGc8pzDZVM+TGZUNSIQF5enpk3b56ZN2+eycvLi3c4AJqJP/3pT+bzzz8P+V7lh88icS1evNiMGjXKDBgwwOyzzz7m559/NsYYc95555m33norON0TTzxh+vbta/r27WvOPffcJr34iCTGRx55xAwZMsTsueeeZsiQIebWW2+t0TkaKxdeeKHp1q2bcblcJicnx/Tr169GfMbEdx9GEmM896ExxqxZs8ZIMn379jXDhg0zw4YNMyNHjjTGGHPLLbeYRx99NDjtW2+9ZQYNGmT69etnjjvuOLN9+/aEivH11183u+++e3BfXn755aakpKRJYjTGmFWrVpkRI0aYoUOHmj333NMcccQRwQZ3ohyXkcYY7+MSdQt3jo6XcOe72uJs6HvRVNv5ZePGjWbs2LGmf//+ZsiQIebjjz8OztfQ96Kptu9zou/36ip32iT6fl++fLkZPny42WOPPczQoUPNsccea1auXGmMSY79vnz5cnPYYYcFj5vXXnstaWJHwzSnzyhZc01jJXOuaozmlOcaKpnyYzKxjDEmvveKAAAAAAAAAAAA1I1nagAAAAAAAAAAgKRAUQMAAAAAAAAAACQFihoAAAAAAAAAACApUNQAAAAAAAAAAABJgaIGmq1Vq1bJsixNmTIl3qHExYwZM2RZlmbMmBHvUAAAAAAAAAAgKihqACHcdtttsiwr7L9JkybFO0QAAAAAAAAAaHHc8Q4AiJVu3brp119/VXZ2doOXceKJJ2ro0KE1Xh88eHBjQgMAAAjps88+0z/+8Q/NmzdPGzZs0JtvvlmvH1Pcdtttuv3222u8npGRoZ07d0YxUgAAAACID4oaaLY8Hk+jiw8nnXSSTj311ChFBABA9M2YMUPnnHOOpk+f3mKHXGxOdu7cqWHDhuncc8/VCSecUO/5r776al188cVVXjviiCM0YsSIaIUIIIGREwAAQEvA8FNotkI9U2PDhg264oorNGDAAKWnp6tNmzbabbfddPHFFys/P7/e6zjssMNkWZZKSkp08803q1+/fvJ4PLrtttskSb/99puuvfZa7b333mrfvr3S0tI0cOBAXX/99dqxY0eN5fXu3Vu9e/eudV3Vbdu2TRdffLE6deqkjIwMjRgxQm+++Wa9twUAmlJtQ/yF+teSJeozoqZMmVLlM3K73Wrbtq2GDBmiM844Q6+99prKyspqnaeufy3xuVBHHnmk7rzzTh1//PEh3y8tLdXVV1+tbt26qVWrVtpvv/30ySefBN9v3bq1OnfuHPy3adMmLVq0SOedd14TbQFQf+SEyCVqTqhs9erVcrlcsixL//jHP5pknYHhgyufDwGgOZs3b57OO+88DRgwQK1atVJ6err69euns846S3PmzAlOl5eXp6lTp+qkk05Snz59yKVoNrhTAy1GUVGRDjzwQK1atUrjxo3T8ccfr7KyMq1cuVLPP/+8rr766gYPVXXiiSfqp59+0oQJE9SmTRv16dNHkvTGG2/o6aef1ujRo3XYYYfJcRx9/fXXuvvuu/Xpp5/qs88+k8fjadQ2HXbYYfrll1+0//7769BDD9WaNWt0yimnaNy4cQ1eLgDE2q233lrjtQcffFD5+fkh30N4xx9/vEaNGqUuXbrEZf3nnXeeunfvLmOMCgoKtHTpUr3zzjt68cUXtdtuu+nll1/WnnvuKUmaNGlSjeL9J598ok8//VTHHXechg8fXuW96n9Duvzyy7Vo0SK9/PLL6tq1q958801NmDBBv/zyiwYMGFBj+qeeekoDBw7UwQcfHIdogciQE6In3jlBkp555hk5jiPLsvTMM8/ommuuiVssANDcOI6jq6++Wg888IDcbrcOP/xwHXvssfJ4PFqxYoVmzpypf//737rjjjt0yy23aNGiRbrxxhtlWZYGDBigjIwMFRUVxXszgEajqIEW46OPPtLKlSv15z//WQ888ECV93bs2BGyuPDaa69p8eLFNV6//vrrlZaWFvx7/fr1+vnnn9WuXbsq05111lm68sorlZKSUuX1O+64Q7feeqteeeUVnXHGGQ3epnvuuUe//PKLLrjgAj3xxBNV1jthwoQGLxcAYi1wR1tlM2bMUH5+fsj3EF52dnajnh/VWOeff75GjRpV5bXCwkLdeuuteuCBBzRu3DjNnz9fXbt21aRJk2o8H+K2227Tp59+qkmTJiX0L48TQW5urqZPn67c3Fx17dpVkn+4qffff1/Tp0/XXXfdVWX6kpISvfDCC7r++uvjES4QMXJC9MQ7JziOoxkzZqhDhw46+uijNWPGDH355Zc64IAD4hYTADQnN998sx544AENHz5cr732mvr161fl/eLiYv3f//2ftm7dKknabbfd9Omnn2qvvfZSZmamBg8erCVLlsQjdCCqGH4KLU56enqN11q3bq3U1NQar7/++uu6/fbba/wrKSmpMt3tt99eo6Ah+R9WXr2gIfl/ZSlJH374YUM3Q5L03HPPKSUlRXfccUeV18ePH68jjjiiUcsGgERQeZiNX3/9Vccff7zat28vy7K0atUqSdKbb76p0047Tf3791dGRoays7N18MEH6/XXX691ecuWLdPxxx+vtm3bqlWrVhozZox++umnGvMsXbpU55xzjvr06aPU1FS1a9dOw4YN05///GcZY4LTzZs3T5dffrmGDh2q7Oxspaena4899tC0adNUXl4ecvvy8vJ01VVXadCgQUpPT1e7du2033776d5775Xk79QL3P337LPPVhl+JTDExowZM8IO1fS///1PRx11lNq1a6e0tDQNHjxYt956a8hfZ1mWpcMOO0ybNm3S5MmT1aFDB6Wnp2vUqFH1Hs4jMzNT999/v6ZMmaJNmzbpzjvvrNf8CO2XX36Rz+fTwIED1bp16+C/Tz/9VMuXL68x/ZtvvqnCwkJNnjw5DtEC0UdOSPycMGfOHOXm5urUU08NDnv39NNPh5y2cqzvvPOO9ttvP2VkZKhbt2665ZZb5DhOcFuHDRum9PR09ezZs8aQVocddphuv/12SdLo0aOD+yTcsL4AkKyWLVume+65R+3bt9f7779fo6Ah+fu8rrnmmuB5sVOnTjrkkEOUmZnZ1OECMcWdGmgxDjnkEHXp0kXTpk3TTz/9pKOPPlqHHnqodtttt7DjCb700ksRPSh85MiRIV83xmj69OmaMWOGFixYoPz8/ODFueS/w6OhCgoKtHLlSg0ZMkSdO3eu8f7BBx+sjz76qMHLB4BEsmzZMo0aNUp77LGHpkyZoq1btwaLxjfccINSUlJ00EEHqUuXLtq8ebPefvttnXTSSXr44Yf1xz/+scbyVq1apVGjRmn33XfXueeeq+XLl+utt97S6NGj9euvv6pTp06S/OfpkSNHaufOnTrqqKN0yimnaOfOnVq6dKn+9a9/6d5775Xb7b+cevLJJ/XOO+/okEMO0cSJE1VUVKRPPvlEN9xwg7777rsaHWpLlizR6NGjtWHDBh100EGaNGmSdu7cqYULF+quu+7S1VdfreHDh+uKK67QQw89pGHDhlW5y6GuzppXX31Vp512mlJTU3XKKacoJydHs2fP1h133KEPPvhAn3zySZW7DiVp+/btOuigg5Sdna2zzjpLeXl5+s9//qPx48dr3rx5Gjp0aL0+t1tuuUUzZszQK6+8on/+85+M39tIO3bskMvl0rx58+Ryuaq817p16xrTP/XUUzr66KODxzPQXJATEjcnBAoYZ599tkaMGKG+ffvqlVde0UMPPRTyPCX5C1GzZ8/WpEmTdOCBB2rmzJm68847ZYxRdna27rzzTh133HE67LDD9Prrr+vaa69Vp06ddPbZZ0tS8C6/Tz/9VJMnTw7uizZt2tS6TwAg2cyYMUM+n08XXXRRndd3oX64CzQrBmimVq5caSSZyZMnB19bvXq1mTx5smnXrp2RZCSZHj16mH/+859V5r311luNJPPSSy/Vuo5DDz3USDKO44R8//LLLw+uY/Lkyeb66683t956a3D5hx56aJXpe/XqZXr16lXrugLWrFljJJnDDjss5PSPPvqokWSmT59e6zYAQKLo1auXqX5pEjiXSzJ//etfQ863fPnyGq8VFhaaPfbYw2RnZ5udO3eGXN60adOqzHPzzTcbSWbq1KnB1x5++GEjyTz44IM11rF169Yqf69evdp4vd4qrzmOY84991wjyXzxxRdV3tt3332NJPPEE0/UWPaaNWtqxFw5n1U2ffr0Guf7/Px8k52dbVJTU81PP/0UfN3n85lTTjnFSDJ33HFHleUE9sull15qfD5f8PWnnnrKSDIXXXRRleknT55sJJmvvvoqZFwBPXr0MJJCfk7G7Mq55KuaJJk333wz+PeSJUuMJPPZZ5/VOe+KFSuMZVnmnXfeiWGEQOyQE3ZJhpxgjDFbtmwxKSkpZvDgwcHX/vrXvxpJ5qmnngobq8fjMd9++23w9YKCApOTk2MyMjJM586dq3ymubm5JiUlxeyxxx5VlhXIJXPnzg25XwCgOTjssMOMJPPhhx82eBmDBg2qkV+BZMTwU2hRevbsqRkzZmjz5s364YcfdPfdd8txHF122WV66aWXGrzcUL88zcvL0z//+U/tueeeWrx4sWbMmKGpU6fqtttu08UXXxxyObZty+v1hnwvPz+/yt9ZWVnB9YSyadOm+mwCACS0zp0766abbgr5Xt++fWu81rp1a02ZMkX5+fn67rvvarzfp0+fGg8uDQyTEWr6UEMXVh92sGfPnjV+PW9Zli677DJJVYcc/Pbbb/X999/rkEMO0QUXXFBj2d27d6/xWn289dZbys/P17nnnht8SLfkzzP33HOP3G53yKFJWrVqpbvvvlu2vesScfLkyXK73SH3SyQCz37YsmVLg+ZvaXbs2KEff/xRP/74oyRp5cqV+vHHH5Wbm6uBAwfqjDPO0Nlnn6033nhDK1eu1LfffqupU6dq5syZVZbzzDPPqEuXLjryyCPjsBVAbJET6qepcsLzzz+vsrIynXXWWcHXAndThBuCSpLOPPNMjRgxIvh3Zmamjj76aBUVFemSSy6p8pn26NFDBx10kBYtWhS23QQAzdXGjRslNT4vAM0BRQ20SLZta/jw4br22muDxYy33347qutYsWKFjDEaM2aMMjIyqrz3+eefh5ynbdu2ysvLq3GBHritvbKsrCz16dNHy5YtCya2SNYBAMlo2LBhIZ9RJPmLu1deeaV22203ZWRkBMfSvuqqqySFHupv+PDhVTpppF2Ng+3btwdfO+aYY9SqVStddtllOuWUUzR9+nStWLEiZBxlZWW6//77NXLkSGVlZcm2bVmWpX322adGHN9++60kady4cRHugfr54YcfJPnHGa+uZ8+e6tu3r1asWKHCwsIq7wWe1VCZ2+1Wp06dquwXxM7333+vvfbaS3vttZck6corr9Ree+2lv/71r5Kk6dOn6+yzzw6Ouz9p0iR999136tmzZ3AZgQf1TpkypUanKtAckBPqp6lywtNPPy3LsnTmmWcGX+vXr58OOOAAffXVV/r1119Dxjd8+PAar3Xp0qXW93w+Hz/iAgCgBeOZGmgxFi5cqA4dOtQYdzBwMVx9DNnG6tWrlyTpyy+/lOM4wYbS2rVrdcMNN4ScZ8SIEZo/f75eeOGF4EM9jTG64YYbtHPnzhrTn3XWWbrjjjv017/+VU888UTw9dmzZ/M8DQDNSrgxY7dt26YRI0YoNzdXBx54oMaMGaM2bdrI5XLpxx9/1FtvvaXS0tIa8wXudqssMA66z+cLvta7d299/fXXuu222zRr1iy98sorkqTBgwfrjjvu0Mknnxyc9qSTTtI777yjgQMHBscr93g82r59ux566KEqcQTuvuvWrVsD9kbdCgoKJIXfb126dNFvv/2mgoKCKg8NDLVfJP++qbxf6iPQcdexY8cGzd/SHHbYYVUeNlydx+PR7bffHnz4Yyi2bWvNmjWxCA9ICOSE+mmKnPDNN99owYIFGj16dJUiq+S/W+PLL7/UM888U+Mh3+HWE9j/tb0X7oHrANBcde7cWYsXL9a6des0aNCgeIcDxBVFDbQYc+bM0TXXXKMDDzxQAwcOVPv27bVixQq9/fbbSktLC94KHi1dunTRiSeeqNdff1377ruvjjjiCG3atEnvvvuujjjiCC1fvrzGPJdffrmmT5+u888/X3PmzFHHjh31+eefa/v27Ro2bJh++umnKtNfe+21euONN/Tkk09q4cKFOuSQQ7RmzRq98sorOuqoo2oMRQEAySrcA6affvpp5ebm6m9/+5tuvvnmKu9NmzZNb731VqPXPXToUL322msqLy/XvHnz9N577+nhhx/WKaecoq5du+rAAw/Ud999p3feeUfjx4/XzJkzq/w6/uuvv9ZDDz1UZZmBh5euW7eu0fGFEugECvcr1sAdfuE6rKJlxYoVWrNmjTp27FjnQ2wBIFLkhPppipwQGF5q7ty5YT+f5557TnfddZc8Hk+D1wMALdmBBx6oTz75RB999JEOP/zweIcDxBXDT6HFGD9+vC677DIVFBTojTfe0AMPPKDvv/9ep5xyiubNm6d999036uucMWOGrrrqKv3+++965JFH9PXXX+vKK6/Uiy++GHL6oUOH6v3339c+++yj1157Tc8//7yGDBmiL7/8MtjYqaxVq1b69NNPdeGFF2rp0qV68MEHtXjxYv3nP//RSSedFPXtAYBEEygQH3fccTXei/YwfB6PR6NGjdLtt9+uhx9+WMYYvfvuu1XiOOqoo2oM9xMqjpEjR0ry31lXl8Dy6nOnRGDook8++aTGe2vWrNHy5cvVt2/fKr/IjYW//e1vkqRTTjklbCcXAEQLOSG0WOeEnTt36uWXX1ZGRobOO++8kP/23HNP5eXlBfdRtDVkvwBAsgkMLfrEE09o8+bNtU4b6s5EoDnhTg00W717964yfMNuu+2mBx98MKJ5b7vtNt122211TheqYVBZ69atde+99+ree++t8V64oSVGjx6tr7/+OuJ1tWvXTo8//rgef/zxGu9NmTKl1vgAINkFhvr74osvtMceewRff/HFFzVr1qxGL3/evHkaMGBAjV+vVh+6sHIcf/zjH4PTLVy4UFOnTq2x3BEjRmjEiBH67LPP9OSTT9Z4MOy6deuCw5C0bdtWlmXVazih4447TtnZ2Zo+fbouu+wy7b777pL8uee6666T1+uNaY7YsWOHbr31Vs2YMUNdunTRjTfeGLN1AUAAOSG0WOeEV199VYWFhTr77LP11FNPhZxm9uzZGj9+vJ5++mkdf/zxDV5XOIEHtTP0HoDmrH///rr22ms1depUHXnkkXr11VfVp0+fKtOUlJToX//6lzZv3hwy5wDNBUUNAACQtM466yzdfffd+uMf/6i5c+eqV69e+umnn/TRRx/phBNO0BtvvNGo5T///PN6/PHHdcghh6hfv37KysrSokWLNGvWLLVr107nnHOOJP+vbEeOHKlXXnlFGzZs0KhRo5Sbm6u3335bRx11lF577bUay37hhRd02GGH6cILL9Tzzz+v/fffXyUlJVq4cKF++OEHbd26VZK/QB7o7DrrrLM0YMAA2bats846K9hxVl1WVpaefPJJnXbaadpvv/10yimnqGPHjvrwww81b948jRw5Utdcc02j9k3AU089pffff1/GGBUWFmrp0qX69NNPVVhYqN13310vv/xy8IGvABBL5IT45ITA0FOB7Q9lzJgx6t69u95//32tX79eXbt2bfD6Qhk9erQsy9KNN96ohQsXKjs7W23atNHll18e1fUAQLzdeeed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5phjdOyxxzab37e//W2NGzcu4+sBtFcg2wUAXvSLX/xCd911l8aNG6enn35a++23X6P7q6qq9Ic//EHbt2+XJF1xxRU6++yz1b9///ppjDG69NJL9ac//Um//OUv9T//8z8ZXQcAQPolmheXXXaZrrrqqmbzWb58uSZOnKirrrpKZ511lizLykj9AIDMSDQvGnr33Xf1m9/8RvPmzdNll12WqZIBAFmQbF4ce+yxuummmzJYKZBefFIDSNDq1au1//77q1u3blqxYkWrn7CoqalRfn5+i/dv2rRJ/fv314EHHqjly5eno1wAQJakMi8kafz48frggw+0c+dOde3aNdXlAgCypD15UV1drUMOOUR9+/bVa6+9Jp/Pxyc1AKCDSiYvYp/UuPHGG2lqoEPhkxpAgh566CFFIhFddNFFbX5lVFsXqILBoCQpEOBQBICOJpV5sWbNGn322WcaOHAgDQ0A6GDakxezZ89WWVmZXnjhBT7FBwAdXHvyYtWqVfrd736nqqoqlZaWaurUqRowYEA6ywXSiiupQIL+85//SJKmTp3a7nk9+OCDkqTp06e3e14AAHdpT168++67WrBggUKhkL788ks9//zzkqR77rknpTUCALIv2bx4/fXXNW/ePN15553Nvn4EANDxtOf84rHHHtNjjz1W/3cgENCPfvQj/fa3v5Xf709ZjUCm0NQAErR582ZJUmlpabvm8+GHH2rOnDnq06ePrr766lSUBgBwkfbkxbvvvqs5c+bU/923b189/PDDNMEBoANKJi/27t2r8847T0cccYR+9KMfpas0AICLJJMXvXv31q233qpvfetbGjJkiPbu3au33npLP//5z3XXXXfJsizdcccd6SoZSBtftgsActEXX3yhb37zm4pEInriiSfUq1evbJcEAHCRyy67TMYYVVZWatmyZZoxY4ZOPPFE3X777dkuDQDgAldddZU2btyoBx98UD4fp/UAgPgOPPBAXXPNNTrwwAPVqVMn9enTR6eccopee+019e7dW3fffbfKy8uzXSaQMF79AAnq16+fJGnDhg1JPX7t2rWaMmWKtm3bpqefflpTpkxJZXkAAJdob15IUmFhoQ4++GA99NBDmjFjhq655hotX748VSUCAFwg0bxYvHix7rnnHv3qV7/SyJEj01kaAMBFUnF+0XBep5xyisLhsN555512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tyH/psbll1/e7+U9PT25++67c+GFF+aqq67KqaeeOuTiAKg+eQFAs2QGAM2QFwBj25CbGkcffXRqtdqA1xdFkac+9an55Cc/OdSHAGArIC8AaJbMAKAZ8gJgbBtyU+PMM8/sN0Dq9Xq23377HHHEEXnSk560RcUBUH3yAoBmyQwAmiEvAMa2ITc1PvjBDw5jGQBsreQFAM2SGQA0Q14AjG0j9kPhAAAAAAAAw2nITY0//OEP+cpXvpJly5atvWzlypV5wxvekN122y2zZ8/OF7/4xWEpEoDqkhcANEtmANAMeQEwtg25qfHhD384Z5xxRiZNmrT2stNPPz3nnXdeli9fnoULF+ZNb3pT5s+fPyyFAlBN8gKAZskMAJohLwDGtiE3NX73u9/lmGOOWfvDTD09PbngggvyxCc+MYsXL84dd9yRnXbaKZ/+9KeHrVgAqkdeANAsmQFAM+QFwNg25KbG/fffn5kzZ679+6qrrsqyZcvy+te/PuPHj8+uu+6aF7zgBbn++uuHpVAAqkleANAsmQFAM+QFwNg25KZGe3t7Vq9evfbvX/7yl6nVajnmmGPWXjZ16tQ88MADW1YhAJUmLwBolswAoBnyAmBsG3JTY4899sgvfvGLtX9ffPHF2XPPPbP77ruvvezuu+/O1KlTt6xCACpNXgDQLJkBQDPkBcDYNuSmxite8Ypcf/31edKTnpSjjjoq119/fV72spett8wNN9yQffbZZ4uLBKC65AUAzZIZADRDXgCMbUNuarz5zW/OKaeckquvvjpXXHFFnvOc5+T0009fe/2NN96Y66+/Pscee+ywFApANckLAJolMwBohrwAGNvah3rDzs7OfPvb386yZctSq9UyadKk9a7feeed8/vf/z577LHHltYIQIXJCwCaJTMAaIa8ABjbhtzU6DN58uR+L99xxx2z4447bundA7CVkBcANEtmANAMeQEwNm1xUyNJGo1G7rvvvnR3d/d7/axZs4bjYQCoOHkBQLNkBgDNkBcAY88WNTUuuuiifPzjH89NN92U3t7efpep1Wrp6enZkocBoOLkBQDNkhkANENeAIxdQ25qfPzjH8973vOedHR05Kijjsr06dPT3j4sH/wAYCsiLwBolswAoBnyAmBsG/KM/9nPfja77bZbfvOb32TGjBnDWRMAWxF5AUCzZAYAzZAXAGNbfag3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ac6s2vw2UL2PPPJI8YQnPKE48MADi4MPPrg49thji+uuu66l9d55553FEUccsbamZz7zmWvfnV3G7ZZqKNM2MNTcGEnDnRUjXduWZMNwGoksGI36tmTuHy4jMdePdG1l2e62RK0oiqKVTRUAAAAAAIBm+PopAAAAAACgEjQ1AAAAAACAStDUAAAAAAAAKkFTAwAAAAAAqARNDQAAAAAAoBI0NQAAAAAAgErQ1AAAAAAAACpBUwO2wDXXXJNXv/rV2WeffbLNNttkwoQJ2XvvvfOKV7wi8+fP32j55cuX5wMf+EAOPPDATJw4MVOmTMlhhx2Ws846qwXVAzBams2Lo48+OrVabZP/fO1rX2vhSAAYSYM5vliyZEnOPPPMHHzwwZk0aVJ23HHHHHHEEfnc5z6XVatWtWgEAIyGweTFX//615x22mmZNWtWxo0bl1133TWvetWrsnDhwhZVD1uuVhRF0eoioGoajUbe9a535VOf+lTa29tz7LHH5sADD0xHR0duv/32/OxnP8vDDz+cf/mXf8kZZ5yRJFmwYEGOPfbY3H777TnuuONy6KGHZvXq1bn11luzYMGC3HDDDS0eFQDDbbB58dWvfjV33nnnRvfT3d2dc845J/V6PQsWLMiuu+46+oMBYMQMNi+WLFmSJzzhCbn99tvztKc9LU960pOyevXq/PjHP85tt92WY489NvPnz0+97n2MAFuTwebFbbfdliOPPDKLFy/OCSeckIMPPji33HJLfvCDH2SnnXbKb37zm+y9996tHhYMWnurC4Aq+n//7//lU5/6VA455JB897vf3SgAVq5cmc997nN58MEHkyQ9PT05+eSTc8899+TnP/95jjnmmPWW7+npGbXaARg9g82LuXPn9ns/l1xySYqiyIknnqihAbAVGmxefOlLX8rtt9+et7/97fnUpz61drmurq489alPzWWXXZYrrrgiRx111KiOA4CRNdi8eNvb3pbFixfn05/+dN761reuXe7iiy/Oi1/84rzpTW/KT37yk1EdAwwHn9SAQbr11lvzuMc9LlOmTMmNN96YnXfeecBlV69enc7OznzrW9/KP/zDP+SMM87Iv/zLv4xitQC0ylDyYiAnnnhifvzjH+f73/9+XvCCF4xEuQC0yFDy4vWvf33OO++8XHrppTn++OPXW+b9739/zj777Hz3u9/NySefPNLlAzBKBpsXRVFk0qRJmTp1ahYtWpRarbbeMoceemiuu+663Hbbbdlrr71GunwYVj6LCoP01a9+Nb29vTnttNM2GSBJ1p6g+va3v50kOeWUU7Jw4cJ88YtfzLnnnpuLL744jzzyyIjXDMDoG0pe9Oevf/1rfvrTn2b69Ol57nOfO9xlAtBiQ8mLAw88MEkyb9689a7v6urK/PnzM2HChDzlKU8ZmYIBaInB5sWDDz6Ynp6e7L777hs1NJJkzz33TJL84he/GJF6YST5+ikYpF//+tdJkmOPPbbp21xzzTVJkssvvzz/9E//lNWrV6+9bqeddsp3vvOdHH300cNaJwCtNZS86M8FF1yQRqORV77ylWlv99INYGszlLx49atfna9//ev5t3/7t1xzzTVrf1Nj3rx5eeSRR/Ltb3/b1xUCbGUGmxfbb7992tractddd6Uoio0aG3fccUeS5Oabbx7eQmEU+KQGDNK9996bJJkxY0bTt1m8eHGSNd9l+Pa3vz0LFy7M/fffn8985jNZunRp/u7v/i6LFi0akXoBaI2h5MWGiqLIBRdckGTNCSwAtj5DyYsJEybksssuyytf+cr87//+bz7+8Y/ns5/9bO688878wz/8Q4488siRKheAFhlsXkycODFHHXVU7rvvvnz+859f77rvfe97ue6665IkS5YsGc4yYVRoasAoaDQaSZLnPe95OffcczNjxozsuOOOectb3pK3v/3tWbp0ac4///wWVwlA2Vx22WW544478oxnPCOzZ89udTkAlMT999+fZz7zmfn1r3+defPmZenSpVm0aFH+/d//Pf/xH/+RJz/5yVm2bFmrywSgxT71qU9l2223zZvf/OY8+9nPzrvf/e686EUvyimnnJKDDz44SVKvOz1M9dhqYZB22WWXJMndd9/d9G222267JMlJJ5200XV9l1199dXDUB0AZTGUvNhQX8P7Na95zbDUBED5DCUv3vGOd+TKK6/MJZdckuc85zmZPHlydtlll5x22mn5yEc+kltvvTWf/exnR6pkAFpgKHkxZ86cXHXVVXnxi1+ca6+9Np/+9Kfzl7/8Jeedd15e8YpXJEmmTZs2IvXCSNLUgEF66lOfmiT5+c9/3vRt9ttvvyTJlClTNrqu77KVK1ducW0AlMdQ8mJdDz/8cP7rv/4rU6ZMyd///d8PZ2kAlMhQ8uLHP/5xdthhh7Xvsl3XMccckyT5/e9/PzwFAlAKQz2+eNzjHpdvf/vbWbx4cVavXp0bb7wxr3nNa/LHP/4xSXL44YcPe60w0jQ1YJDmzp2btra2fOlLX8r999+/yWX7fhC870ecbrrppo2W6btsjz32GN5CAWipoeTFui666KKsWrUq//iP/5jx48ePVJkAtNhQ8qKrqyvLli1LV1fXRsv03UdnZ+fwFwtAy2zp8cW6li9fnv/5n//J1KlTc/zxxw9nmTAqNDVgkGbPnp13v/vdeeCBB/Kc5zwnd9xxx0bLrFq1Kp/85CfzwQ9+MEnyqle9Kp2dnfnsZz+73scEly9fnrPPPjtJ8uIXv3hU6gdgdAwlL9bV99VTfiAcYOs2lLx46lOfmp6ennzoQx/aaLkPf/jDSf72iQ0Atg5DyYuVK1emp6dnvWVWr16dV7/61XnooYdy5plnegMVldTe6gKgij784Q9n1apV+dSnPpX99tsvxx57bA488MB0dHTkjjvuyM9+9rM8+OCDaw8o9txzz3zsYx/LW9/61syZMycvfOEL09nZmR/96Ee58847c9ppp+WZz3xmi0cFwHAbbF70ueaaa3L99dfnsMMOy6GHHtqi6gEYLYPNi3POOSdXXHFFPvzhD2f+/Pk58sgjs3Llyvz4xz/OXXfdlac85Sk59dRTWzwqAIbbYPPimmuuyYte9KIcf/zxmTlzZpYtW5Yf/ehHWbBgQV772tfmLW95S4tHBENTK4qiaHURUFVXX311vvCFL+Tyyy/P3XffnUajkenTp+fII4/Mq171qhx33HHrLf8///M/+djHPpbf//736enpyQEHHJDXv/71fgAWYCs32Lx44xvfmC984Qv5/Oc/nze84Q0tqhqA0TaYvLj55ptz9tln5xe/+EUWLVqU9vb27LPPPjnllFPyT//0T5kwYUILRwLASGo2LxYsWJB3vetd+e1vf5v77rsvEydOzGGHHZY3vvGNOfnkk1s8Chg6TQ0AAAAAAKAS/KYGAAAAAABQCZoaAAAAAABAJWhqAAAAAAAAlaCpAQAAAAAAVIKmBgAAAAAAUAmaGgAAAAAAQCVoagAAAAAAAJWgqQEAAAAAAFRCe6sLoPV6e3vT3d3d6jJg0Do6OtLW1tbqMmDMaDQa6erqanUZMGjyAkafYwyqSF7A6JMXVNW4ceNSr/u8QKtoaoxhRVHk3nvvzZIlS1pdCgzZlClTsssuu6RWq7W6FNiqdXV15Y477kij0Wh1KTAk8gJGh2MMqk5ewOiQF1RdvV7PnnvumXHjxrW6lDFJU2MM6wuPadOmZeLEiV60USlFUWTFihVZvHhxkmT69Oktrgi2XkVRZNGiRWlra8vMmTO9G4VKkRcwuhxjUFXyAkaXvKDKGo1G7rnnnixatCizZs2y/baApsYY1dvbuzY8pk6d2upyYEgmTJiQJFm8eHGmTZvmo+IwQnp6erJixYrsuuuumThxYqvLgUGTFzA6HGNQdfICRoe8YGuw00475Z577klPT086OjpaXc6Y462WY1Tf9xU6OUXV9W3DvoMTRk5vb2+S+FgtlSYvYOQ5xmBrIC9g5MkLtgZ9x8d9x8uMLk2NMc7Ho6g62zCMHvsbVWb7hdFjf6PKbL8weuxvVJntt7U0NQAAAAAAgErwmxpskVXdvZn3h0W59Mb7smRFV6ZMHJcTDtg5Jx40PeM7qvv9o3Pnzs2SJUvy/e9/v9WlbFW++tWv5u1vf3uWLFnS6lKAUba15kUiM0aCvICxS14wGPICxratNTPkxciQGVsXn9RgyObfdF+eePbP8s7vXJ9Lb7o3v73joVx6071553euzxPP/ll+dtN9I/K4c+fOTa1WS61WS0dHR/bcc8+8+93vzqpVq0bk8Sqh0Ugeviu578Y1/200RvTh1n0O1v3n1ltvHdHHBaqpVXmRyIyNyAugxORFicgLoOSckyqJUc6LRGawhk9qMCTzb7ovr/va1Umx5u/GBv9dvrInr/3a1fnSKw7P8fvvPOyP/+xnPzsXXHBBuru7c8011+SVr3xlarVa/vVf/3XYH6v07v9L8qf/SR64JelZlbSPT3bcJ3n885Od9huxh+17Dta10047jdjjAdXU6rxIZMZa8gIoMXlRIvICKLlWZ4a8eEyL8iKRGfikBkOwqrs3/3TxdUmxNj82Ujz2r3ddfF1WdfcOew2dnZ3ZZZddMnPmzPzd3/1djjvuuMyfPz9J0mg0cs4552TPPffMhAkTMmfOnHz3u99de9ve3t68+tWvXnv9fvvtl09/+tPDXuOouP8vyW+/mCy6IZm4QzJ1nzX/XXTDmsvv/8uIPXTfc7DuP5/+9Kdz0EEHZZtttsnMmTPzxje+MY888sjA5d9/fw4//PC88IUvzOrVqzf73AHVUoa8SGRGEnkBlJq8KBF5AZRcGTJDXqSleZHIDDQ1GIJ5f1iUZSt7BgyPPkWSpSt78uM/LhrRev74xz/mN7/5TcaNG5ckOeecc3LhhRfmi1/8Ym688ca84x3vyMtf/vL86le/SrImYGbMmJGLL744N910U84888ycfvrp+c53vjOidQ67RmNNR3zFg8lOj0s6Jyf1tjX/3elxay7/8w9H5aN/fer1ej7zmc/kxhtvzH/+53/msssuy7vf/e5+l124cGGe/vSn58ADD8x3v/vddHZ2bva5A6qlbHmRjNHMkBdAycmLkpAXQAWULTPkRTnyIpEZY42vn2LQLr3xvtRrf/tY36bUa8lP/3hfXnjojGGt4Yc//GG23Xbb9PT0ZPXq1anX6/nc5z6X1atX5+yzz87PfvazPOUpT0mS7LXXXrniiity3nnn5RnPeEY6Ojpy1llnrb2vPffcM1deeWW+853v5MUvfvGw1jmili5c8xG/7XZLarX1r6vVksm7JfffvGa57Xcf9ofvew76POc5z8nFF1+89u899tgjH/7wh/P6178+n//859e77V/+8pccf/zxeeELX5h/+7d/S61Wa+q5A6qlDHmRyAx5AZSdvCgJeQFUQBkyQ160Ni8SmYGmBkOwZEVXU+GRrAmZJSu7hr2GY445Jl/4whfy6KOP5lOf+lTa29tz8skn58Ybb8yKFSty/PHHr7d8V1dXDj300LV///u//3u+8pWvZMGCBVm5cmW6urpyyCGHDHudI6rrkTXfWdixTf/Xj5uYLL9nzXIjoO856LPNNtvkZz/7Wc4555z8+c9/zrJly9LT05NVq1ZlxYoVmThxYpJk5cqVefrTn56Xvexl+bd/+7e1t7/11lubeu6A6ihDXiQyQ14AZScvSkJeABVQhsyQF63Ni0RmoKnBEEyZOG5QXfEpE8YNew3bbLNNZs+enST5yle+kjlz5uT888/PgQcemCT50Y9+lN12222923R2diZJvvWtb+Vd73pXPvGJT+QpT3lKJk2alI997GP5v//7v2Gvc0SN23bNjzB1P7rmI34b6lqx5vpx22583TBY9zlIkjvvvDPPe97z8oY3vCEf+chHssMOO+SKK67Iq1/96nR1da0NkM7Ozhx33HH54Q9/mH/+539e+zz1fc/hpp47oFrKkBeJzJAXQNnJi5KQ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ZsqUKbn22mtzwAEHDLje9vb2tLe3r3d6W1tbQ+8wzXrnSxp/WYdb2fIm5ctctrxJ+TKPVN4yXSeNNBydMVJ90bvOZlW2ba2X3COnjJkTuct42RvBMcbwKuN2VcbMidwjqYyZk8bmLuPl31TN1hdD+UCXZrndyrANydgYMjZGmTOOVu6mGmokycUXX5y5c+fmvPPOy5QpU3LppZcmSd7+9rfn+OOPz/HHH59Zs2blrLPOyiGHHJJqtZrp06fni1/84ignB2Ck6QwA6qEvAKiHvgAoh6Ybauy11165+eab1zv9kksuWevnU045JaeccspIxQKgCekMAOqhLwCoh74AKIdNHmo8/vjjufvuu/PII48M+G3np5566qaeDQAlpy8AqJfOAKAe+gJgbBryUGPFihX5y7/8y3zlK19JV1dXv8sURZFKpaJAAMYwfQFAvXQGAPXQFwBj25CHGn/1V3+VL3/5y9l///3zpje9KdOmTUtra9N9mhUAo0xfAFAvnQFAPfQFwNg25D3+Nddck4MOOig333xzWlpaGpkJgM2IvgCgXjoDgHroC4CxrTrUP+zu7s7hhx+uPADYIH0BQL10BgD10BcAY9uQhxoHH3xw5s+f38gsAGyG9AUA9dIZANRDXwCMbUMeavz93/99rrvuunz7299uZB4ANjP6AoB66QwA6qEvAMa2IX+nxstf/vJcd911Of7443PggQfmgAMOyJQpU9ZbrlKp5Oyzz96kkACUl74AoF46A4B66AuAsW3IQ40nn3wyH/rQh/L000/n+9//fr7//e/3u5wCARjb9AUA9dIZANRDXwCMbUMeavzlX/5lbrrpphx33HF585vfnGnTpqW1dcirA2AzpS8AqJfOAKAe+gJgbBvyHv///u//cvjhh/v8QgA2SF8AUC+dAUA99AXA2DbkLwoviiIHHXRQI7MAsBnSFwDUS2cAUA99ATC2DXmo8YpXvCJ33HFHI7MAsBnSFwDUS2cAUA99ATC2DXmo8ZnPfCa33HJL/vmf/7mReQDYzOgLAOqlMwCoh74AGNuG/J0an/70p7P//vvnr//6r/NP//RP2X///TNlypT1lqtUKvnSl760SSEBKC99AUC9dAYA9dAXAGPbkIcal112Wd+/77nnntxzzz39LqdAAMY2fQFAvXQGAPXQFwBj25CHGvfff38jcwCwmdIXANRLZwBQD30BMLYNeaix8847NzIHAJspfQFAvXQGAPXQFwBj25C/KBwAAAAAAGAkDfmdGldccUXdy5566qlDPRsASk5fAFAvnQFAPfQFwNg25KHG3LlzU6lUNrhMURSpVCoKBGAM0xcA1EtnAFAPfQEwtg15qHHppZf2e/qSJUty22235aqrrsrxxx+f17/+9UMOB0D56QsA6qUzAKiHvgAY24Y81DjttNM2+PszzjgjRx55ZN71rncN9SwA2AzoCwDqpTMAqIe+ABjbhu2Lwl/+8pfn+OOPzznnnDNcZwHAZkBfAFAvnQFAPfQFwOZt2IYaSbLzzjvnjjvuGM6zAGAzoC8AqJfOAKAe+gJg8zVsQ42iKHLjjTdmwoQJw3UWAGwG9AUA9dIZANRDXwBs3ob8nRo33nhjv6d3dXXl4YcfzhVXXJFbbrklp5566pDDAVB++gKAeukMAOqhLwDGtiEPNQ4//PBUKpUBf18URV7xilfks5/97FDPAoDNgL4AoF46A4B66AuAsW3IQ41zzjmn3wKpVqvZeuutc/DBB+elL33pJoUDoPz0BQD10hkA1ENfAIxtQx5qfOxjH2tgDAA2V/oCgHrpDADqoS8AxrZh+6JwAAAAAACARhryUOM3v/lNvvzlL2fp0qV9p61YsSLvete7Mn369MyePTtf+MIXGhISgPLSFwDUS2cAUA99ATC2DXmo8YlPfCJnn312Jk+e3HfaWWedlYsvvjjLli3LwoUL8xd/8ReZN29eQ4ICUE76AoB66QwA6qEvAMa2IQ81fvGLX+SII47o+2Kmrq6uXHrppXnJS16SxYsX5/7778/UqVNz0UUXNSwsAOWjLwCol84AoB76AmBsG/JQ4/HHH8/MmTP7fr7llluydOnSvPOd78z48eOz00475Y//+I9zxx13NCQoAOWkLwCol84AoB76AmBsG/JQo7W1NatWrer7+YYbbkilUskRRxzRd9q2226bJ554YtMSAlBq+gKAeukMAOqhLwDGtiEPNXbZZZf88Ic/7Pv561//enbdddfsvPPOfac9/PDD2XbbbTctIQClpi8AqJfOAKAe+gJgbBvyUOOUU07JHXfckZe+9KU57LDDcscdd+Qtb3nLWsv8+te/zh577LHJIQEoL30BQL10BgD10BcAY9uQhxpnnnlmTjzxxNx666256aab8trXvjZnnXVW3+/vuuuu3HHHHTnyyCMbEhSActIXANRLZwBQD30BMLa1DvUP29vb81//9V9ZunRpKpVKJk+evNbvd9hhh/zqV7/KLrvssqkZASgxfQFAvXQGAPXQFwBj25CHGr2mTJnS7+nbbbddtttuu01dPQCbCX0BQL10BgD10BcAY9MmDzWSpFar5bHHHktnZ2e/v581a1YjzgaAktMXANRLZwBQD30BMPZs0lDjyiuvzGc+85ncfffd6e7u7neZSqWSrq6uTTkbAEpOXwBQL50BQD30BcDYNeShxmc+85l84AMfSFtbWw477LBMmzYtra0NeeMHAJsRfQFAvXQGAPXQFwBj25D3+J///Oczffr0/PSnP82MGTMamQmAzYi+AKBeOgOAeugLgLGtOtQ/fPzxx3PCCScoDwA2SF8AUC+dAUA99AXA2Dbkocaee+6Zp59+upFZANgM6QsA6qUzAKiHvgAY24Y81Pibv/mb/M///E8efPDBRuYBYDOjLwCol84AoB76AmBsG/J3apx22mlZvHhxDjnkkLz73e/OAQcckClTpvS77GGHHTbkgACUm74AoF46A4B66AuAsW3IQ40kWbp0aZYsWZJzzjlng8t1d3dvytkAUHL6AoB66QwA6qEvAMauIQ81zjnnnJx33nmZOnVq3vzmN2fatGlpbd2kGQkAmyF9AUC9dAYA9dAXAGPbkPf4X/7yl7PnnnvmlltuyRZbbNHITABsRvQFAPXSGQDUQ18AjG1D/qLwp59+On/0R3+kPADYIH0BQL10BgD10BcAY9uQhxr77bdfFi1a1MgsAGyG9AUA9dIZANRDXwCMbUMeanz4wx/ON7/5zdx2222NzAPAZkZfAFAvnQFAPfQFwNg25O/UePrpp3P00UfnkEMOySmnnJIDDjggU6ZM6XfZU089dcgBASg3fQFAvXQGAPXQFwBj25CHGnPnzk2lUklRFPnSl76UJKlUKmstUxRFKpWKAgEYw/QFAPXSGQDUQ18AjG1DHmpceumljcwBwGZKXwBQL50BQD30BcDYNuShxmmnndbIHABspvQFAPXSGQDUQ18AjG1D/qJwAAAAAACAkTTkd2osWLCg7mVnzZo11LMBoOT0BQD10hkA1ENfAIxtQx5q7LLLLut9CVN/KpVKurq6hno2AJScvgCgXjoDgHroC4CxbchDjVNPPbXfAlmyZEnu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59YZw2MsHGM0e75ExkaRsTHKnnE0+sK4HQAAAAAAKAVDDQAAAAAAoBQMNQahvb09H/3oR9Pe3j7aUepWtsxly5uUL3PZ8ibly1y2vAyPMt4Pypg5kXsklTFzIjfNray3cxlzlzFzIvdIKmPmpLy5Gbxmv62bPV8iY6PI2BgyDt2Y/KJwAAAAAACgfLxTAwAAAAAAKAVDDQAAAAAAoBQMNQAAAAAAgFIw1BiE+fPn55BDDsmee+6Zgw8+OHfddddoR8ouu+ySvfbaK3PmzMmcOXPyX//1X0k2nHWkL8df/dVfZZdddkmlUsntt99eV47RzD9Q3oGu69HOu3LlyrzhDW/InnvumQMOOCBHH3107rnnniTJ4sWL85rXvCZ77LFH9t1339x44419fzfU3w135sMPPzy77rpr3/X8uc99rikyH3PMMdl///0zZ86cHHroofnVr36VpHnvx4yuZr599cbw5S9bfyTl7JCN5W7WHkl0Cetr5ttQX+iLNemLkc2d6AzW1wy34XDsC4bLpZdemkqlkm9+85tNl2/VqlU588wzs8cee2S//fbLySefnKS5tuFrr702Bx54YObMmZN99903l19+eZLRvR7L0Pv9ZdzQdpOM/HU60PXYa91tZzQy1qWgbkcccURx6aWXFkVRFF//+teLgw46aHQDFUWx8847F7/61a/WO31DWUf6cvzoRz8qFi5cuF7WoWYc7vwD5R3ouh7tvCtWrCi+853vFLVarSiKovj85z9fvOpVryqKoije+ta3Fh/96EeLoiiKX/ziF8X06dOLjo6OTfrdcGd+1ateVfz3f/93v383mpmffvrpvn9/4xvfKPbff/+iKJr3fszoaubbV28MX/6y9UdRlLNDNpa7WXukKHQJ62vm21Bf6Is16YuRzV0UOoP1NcNtOBz7guFw//33Fy9/+cuLl73sZX3beTPle8973lOceeaZfdfjokWLiqJonm24VqsVW2+9dXHHHXcURdFzfba3txdLly4d1euxDL3fX8YNbTdFMfL3zYGux6Lof9sZjYz1MNSo02OPPVZMnjy56OzsLIqiZwPfYYcdivnz549qrv7ugBvKOpqXY82sQ804kvnrPcholry9brnllmLnnXcuiqIoJk2a1FeORVEUBx98cDFv3rxN+t1wZ97QwUWzZL700kuLAw44oBT3Y0Zes9++emP485e1P4qinB2ybu4y9EhR6BL0xXBlLdM2pS/0Rb10Bs16GzZiX9Bo3d3dxVFHHVXceuuta23nzZLv2WefLSZPnlwsWbJkrdObaRuu1WrFNttsU/zoRz8qiqIo7rjjjmKnnXYqVq1a1RTXYxl6f0MvVFhzuymK0btvrptxoG1nNDNuiI+fqtPChQszbdq0tLa2JkkqlUpmzZqVBQsWjHKy5NRTT81+++2Xt73tbXn88cc3mLVZLsdQM452/nWv6025LMPloosuyh//8R/nySefTGdnZ3bccce+3+2yyy5ZsGDBkH833Jl7ffCDH8x+++2Xk046Kffdd1+SNEXmU089NTNnzszZZ5+dr3zlK6W9HzO8ynD76o2Rz1+G/kjK2SFr5u7VrD2S6BKeV4bbUF/oi4Hoi5HJrTPo1ay34abuC4bDZz/72bziFa/Ii1/84r7Tminfvffem2222SbnnXdeDjrooBx66KH5/ve/31TbcKVSyX/913/ljW98Y3beeee88pWvzOWXX55ly5Y1zfXYq4z7xTW7qJnum/1tO82WcU2GGiV344035te//nVuu+22bLfddjnttNNGO9JmqwzX9XnnnZd77rkn559//mhHqdu6mb/yla/kd7/7XX7961/n0EMPzete97pRTvi8K664IgsXLswnPvGJfOADHxjtODAkZdiXbW7Kcp2XsUOScvVIoksoj7LsuzYnZbnO9cXI0Rk0s2bcF9x555255ppr8pGPfGS0owyoq6srDz74YPbZZ5/ceuut+ad/+qecdNJJ6erqGu1ofbq6uvKJT3wi3/jGN/Lggw/m+9//fk455ZSmylhWzbjdJOXYdtZlqFGnmTNnZtGiRX0bcFEUWbBgQWbNmjWquXrPv62tLe95z3vy4x//eINZm+VyDDXjaObv77relMvSaJ/5zGfyjW98I9/97nczceLEbLvttmltbc2jjz7at8wDDzyQWbNmDfl3w5056bk+k54p+Zlnnpn77rsvTz75ZNNkTpLTTjstP/zhDzNjxozS3Y8Zfs1+++qNkc/f7P2RlLND+sudlKNHEl2Cvhgu+kJf1JM7KU9fJDqD5uuMRu0LGu3HP/5xHnjggeyxxx7ZZZdd8rOf/Synn356vva1rzVFvqRnX1+tVvPnf/7nSZIXvehF2XXXXfPggw82zTZ8++2355FHHslhhx2WJDn44IMzY8aM/PrXv26a67FXmXq/vy5q9m3n3/7t35om43qG8aOtNjuvetWr1voCmRe/+MWjmufZZ59d68vDLrzwwuLQQw8timLDWUfrcqz7WW1DzThS+dfMu6HruhnyXnjhhcWBBx5YPPXUU2udftppp631ZT077bRT35f1DPV3w5m5s7OzePTRR/t+vvrqq4tZs2Zt8uXZVE8//XTx8MMP9/383//938X06dOLWq3W9PdjRkez3r56Y2Tyl6k/ejOVrUMGyt2sPVIUuoT+NettqC/0RX/0xcjl1hn0p1luw0bvC4bTmt8L0Ez5jj766OI73/lOURRFcd999xXbbrtt8dBDDzXNNvzoo48WW2yxRXH33XcXRVEU8+fPL7beeuviwQcfbIrrsQy9v27Ggbabohi9++aGvvdj3e/UaIbbfV2GGoPwu9/9rnjZy15W7LHHHsWLX/zi4te//vWo5rn33nuLOXPmFPvtt1+x7777Fscff3xx//33bzTrSF+O008/vZg+fXrR0tJSbL/99sXuu+++SRmHO39/eTd0XY923oULFxZJit1226044IADigMOOKB4yUteUhRFTxEdffTRxezZs4t99tmn+MEPftD3d0P93XBmfvbZZ4sXv/jFxb777lvsv//+xZFHHlncfvvto575gQceKA4++OC+XEcddVTfjr9Z78eMrma9ffXG8OYvW38URTk7ZEO5m7VHikKX0L9mvQ31hb5Yl74Y2dw6g/40w204HPuC4bTmE7PNlO/ee+8tDj/88L5t/Oqrry6Korm24auuuqov37777lt89atfLYpidK/HMvR+fxk3tN0UxchfpwNdj2tad6jRTNtPr0pRFMXwvx8EAAAAAABg0/hODQAAAAAAoBQMNQAAAAAAgFIw1AAAAAAAAErBUAMAAAAAACgFQw0AAAAAAKAUDDUAAAAAAIBSMNQAAAAAAABKwVAD6vDLX/4yb3vb27LHHntk0qRJmTBhQnbfffeccsopmTdvXt9yixcvzvnnn583velN2XXXXVOpVFKpVDa6/ltuuSXHHXdcttpqq0yaNCkve9nL8rWvfW04LxIAw2A4++LKK6/MGWeckYMOOijt7e2pVCq57LLLhvkSATAchqsvHn744fzjP/5jjjnmmMyaNSvjxo3LjjvumBNOOCE///nPR+KiAdBAw/181Jo+9alP9f3dz372s0ZfFGioSlEUxWiHgGZVq9Xyvve9L5/73OfS2tqaI488Mvvuu2/a2tpy33335frrr8/TTz+dj3/84zn77LNzww035IgjjkilUskee+yRhx56KMuXL8+GNrMf/vCHOfbYYzN+/Pi8+c1vzuTJk3PNNdfkwQcfzGc+85n87d/+7QheYgCGYiT6YpdddsmDDz6Y7bbbLpMmTcqDDz6YSy+9NHPnzh25CwrAJhnuvvjgBz+YT33qU9l9991z+OGHZ+rUqZk/f36++c1vpiiKXHXVVTnppJNG+FIDMFgjcXyxpjvvvDMHHXRQWltb89xzz+Xmm2/Oy172smG+lDB0raMdAJrZRz7ykXzuc5/LnDlzcvXVV2f33Xdf6/crVqzIP//zP+fJJ59Mkuy999750Y9+lBe96EWZPHlyXvCCF+T3v//9gOvv6urKO97xjlSr1dx4442ZM2dOkuScc87JS17ykpx11ll505velJ133nnYLiMAm264+yJJLrnkkuyxxx7Zeeedc8EFF+RDH/rQsF0eAIbHcPfFS17yktxwww151atetdbpP/7xj3PUUUflXe96V97whjekvb298RcOgIYZieOLXp2dnTnttNMyZ86c7LHHHrnyyisbfnmg0bxTAwZwzz335AUveEG22mqr3HXXXdlhhx0GXHbVqlX9Hhj0lshAm9l1112XY489Nm9961vz5S9/ea3fXX755Zk7d27OPffcnHPOOZt2YQAYNiPRF+vqHWp4pwZAeYxGX6zp2GOPzXXXXZdbbrklBx100KD/HoCRMdJ98bGPfSwXXHBBbrvttnz605/O5Zdf7p0aND3v1IABXHbZZenu7s4ZZ5yxwQJJMuRXOt1www1JkmOOOWa93x177LFJkh/96EdDWjcAI2Mk+gKA8hvtvmhra0uStLZ6GgCgmY1kX9x222355Cc/mY9//OPZZ599NmldMJJ8UTgM4Cc/+UmS5Mgjjxy285g/f36SZI899ljvdzvuuGO22GKLvmUAaE4j0RcAlN9o9sWCBQty/fXXZ9q0adlvv/1G/PwBqN9I9cWqVaty6qmnZs6cOXn/+98/rOcFjeYlGjCARx99NEkyY8aMYTuPJUuWJEm23HLLfn8/ZcqUvmUAaE4j0RcAlN9o9UVnZ2dOOeWUrFq1Kp/61KfS0tIyoucPwOCMVF+cc845mT9/fn75y1/qBkrHOzUAAABgM1Sr1TJ37tzceOONecc73pFTTjlltCMB0ARuvvnmfOYzn8lHPvKR7LvvvqMdBwbNUAMGsOOOOyZJHn744WE7j953aAz0boylS5cO+C4OAJrDSPQFAOU30n1Rq9Xy//7f/8tVV12Vk08+OV/4whdG5HwB2DTD3RddXV057bTTsv/+++eDH/zgsJwHDDdDDRjAK17xiiTJ97///WE7j97v0ujvezMeffTRPPvss/1+3wYAzWMk+gKA8hvJvqjVannrW9+ayy+/PH/2Z3+Wyy67LNWqw3+AMhjuvnj22Wczf/783H777Rk3blwqlUrf/y6//PIkyctf/vJUKpV885vfHJYMsKk8qoEBzJ07Ny0tLfniF7+Yxx9/fIPLrlq1akjn8apXvSpJct111633u+9973trLQNAcxqJvgCg/EaqL3oHGldccUVOOumkfOUrX/FZ6QAlMtx90d7enre97W39/q/3hbXHH3983va2t2WXXXYZykWAYWeoAQOYPXt23v/+9+eJJ57Ia1/72tx///3rLbNy5cp89rOfzcc+9rEhncdRRx2V3XbbLVdddVVuv/32vtOXLFmS8847L+PGjcupp546xEsAwEgYib4AoPxGoi96P3LqiiuuyIknnpgrr7zSQAOgZIa7LyZMmJBLLrmk3/8dcsghSZIPfehDueSSSzJnzpxNvDQwPFpHOwA0s0984hNZuXJlPve5z2WvvfbKkUcemX333TdtbW25//77c/311+fJJ5/MJz7xib6/mTt3bt+/Fy1atN5pH/zgB/OCF7wgSdLa2ppLLrkkxx57bA477LC8+c1vzuTJk3PNNdfkwQcfzGc+8xlTcYASGO6+SJJLLrkkN910U5LkN7/5Td9pN9xwQ5Lkla98Zd7+9rcP0yUEoBGGuy8+/vGP5/LLL88WW2yRPffcc6319HrDG97gSSqAJjcSxxdQZpWiKIrRDgHN7tZbb82//du/5cYbb8zDDz+cWq2WadOm5ZBDDslb3/rWvPrVr+5btlKpbHBdP/zhD3P44YevddovfvGLfPSjH81Pf/rTdHZ2Zr/99st73/venHTSScNxcQAYJsPZF3Pnzu37jNv+nHbaabnssss29SIAMAKGqy821hVJcumll671JBcAzWu4n49aV2+P3HzzzXnZy17WiIsAw8JQAwAAAAAAKAXf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uON03HHHad68ec1ON3PmTF1yySW65JJLdMUVV6QLx7HHHqsRI0aooqJC//znP7Vu3TqdfPLJevLJJ+U4Tvr+TzzxhN59990mH/v222/Xzp079d///lcHHXRQ+vYf/vCHuuOOO9SrVy+dcsopKikp0Zw5c7RixQr98Ic/1O2335615QAA2Lt81YxYLKbDDz9c//3vfzVu3DgdddRRkqSXXnpJCxcu1P77768333xTZWVl6fssXrxYhxxyiKqqqvTNb35Tffr00dNPP61Fixbp8ssv1+9+97ucLRcAQH0214u6PvvsM40aNUq7d+/Wzp079fDDD+uMM87I6rIAADTP5npx1FFH6ZVXXtGNN97YKE+nTp30/e9/P2vLAciYAYpUMpk0gwcPNqFQyHz66afNTnfQQQcZSWb+/PlmzZo15g9/+IPZsWNHvWl27NhhJkyYYCSZ//u//3P1/AsWLDCSzOjRo+vdPn/+fCPJDB061GzevLnec0ycONFIMq+//rqHOQUAtFa+asYjjzxiJJmvfe1rjR771FNPNZLMn//853q3H3HEEUaSmTNnTvq26upqc/jhh1MzACDPbK4XdX3lK18xgwYNMj/84Q+NJPPwww97nFMAQGvYXC+OPPJIwy5j2I7TT6FoOY6j8847T8lkUrNmzWpymkWLFunNN9/UmDFjNGHCBPXt21ff+c531K5du3rTtWvXTldeeaUk6ZVXXnH1/Pfee68k6fzzz693+z/+8Q9J0g9+8AN16dKl3nNce+21kqS77rrL1XMAALIjXzXjk08+kSSdeOKJjR7/pJNOkiRt3LgxfduSJUv06quv6uijj653n9LS0vSpDf/0pz95nV0AQIZsrRd13X///frnP/+pe+65R+3bt/c2gwCArAhCvQBsRlMDRW3atGkKhUK6//77mzzveG1hadh4aEpJSYkkKRKJ7HXaqqoqPfTQQ4pGozrnnHPq/e2zzz6TJA0ePLjR/Wpve/HFF/f6HACA7MpHzRg1apQk6Zlnnml0n6efflqO4+joo49O3/byyy9LkiZPntxo+sMOO0zt2rVz3WwHAGSHjfWi1urVq/X9739fF110kY499ti9zwwAIGdsrhdS6lqvt956q37961/r5ZdfVjKZ3GsOIF/2vvcVKGD9+/fX5MmT9eyzz+rFF1+s98E+Ho/rwQcfVDQa1dlnn73Xx7rvvvskNb1jqaHHHntMFRUVOuOMM+odjSFJ3bp1kyStWLGi0f1qb1uzZo127drV7DlyAQDZl4+acdJJJ+mrX/2q/v73v+uAAw6od87bFStW6O6779b48ePT0y9dulSSNGzYsEbPEQ6HNXjwYC1evFjxeNxV0x0A0Ho21gtJMsbo/PPPV3l5OdfoAwAL2Fovap111ln1fh8+fLj++te/asKECV5mE8gJjtRA0avteNcWgFpPPfWUPv/8c5166qmNGg8N3X333XrmmWd0zDHHaMqUKXt9ztpTT11wwQWN/lZ7SOCvf/1rbdu2LX37rl27dNttt6V/r6io2OvzAACyK9c1w3EczZ49W1dddZUWLlyoX//61/r1r3+thQsX6mtf+5omTZpUb/raWtDx/7N35/FR1ff+x99nliQECPu+I4giClqtrTsqqFTpr1Vba13w1l1brXWneKVWsYttbasVq6K41FbttVZQwa2WqlVcUEBkEWQn7AGyzfL9/TFJSMgkOWdyTuacmdfz8Wgxk+85530mM9/PzHzmnNOpU9ptlZSUKJlMateuXY72EwDQOn6rF1LqFLZz587Vn//8Z3Xs2LGVewgAcIMf68U3v/lNvfjii1q3bp3Ky8u1ePFiXXPNNVqxYoXGjRun1atXt3KvARdk9YoegA9UV1ebHj16mHbt2pkdO3bU3X7GGWcYSeaVV15pdvl//vOfJhqNmkGDBpn169e3uL1ly5YZy7LMkCFDTDKZTDvm/PPPN5JMnz59zGWXXWauvvpqM3ToUDNw4EDTqVMnI8ls3LjR2Y4CAFrN65qxZ88eM3HiRNOrVy/z9NNPmy1btpgtW7aYp59+2vTq1cv07NnTrFy5sm78JZdcYiSZuXPnpt3eUUcdZSSZbdu2ZbbDAICM+K1erFixwrRv3978z//8T4P1/O///i8XCgeALPJbvWjOlClTjCTzwx/+0NE+Al6gqQEYY6677jojydx///3GGGM2bNhgIpGIGThwoEkkEk0uN2vWLFNYWGj69+9vVqxYYWtbt9xyi5Fk7rjjjibHJBIJc++995pDDjnEFBYWms6dO5vvfve75ssvvzQdOnQwkUjEVFdXO9tJAIArvKwZkydPNpLMP/7xj0a/e/75540kc/HFF9fddv311xtJ5tlnn027vlGjRhnLskwsFnOyiwAAF/ipXpxwwgmmX79+DT4wM4amBgD4gZ/qRXPWrl1rJJnDDjvM1njAS5x+CtDew/1qTwv1+OOPKx6P66KLLlIolP5pMmvWLH37299W9+7d9cYbb2jo0KEtbieRSOixxx5TOBzWRRdd1OS4UCikH/3oR1qwYIEqKyu1fft2Pf3000omk9q9e7cOOeSQuotAAQDalpc1o/YCfuku1ld720cffVR3W+21NGqvrVFfIpHQypUrNWTIEK6nAQBZ4Kd68dFHH2ndunXq3LmzLMuq+9/UqVMlSd/73vdkWZZ+97vfZbazAICM+aleNKdbt26yLEt79uyxNR7wEu9wAUkjR47U1772Nb377rv65JNPNGPGDFmW1WTjYdasWTrzzDPVtWtXvfHGGxo2bJit7cyePVvr16/XN77xDfXr189xzieffFKSdM455zheFgDgDi9rRnV1tSRp8+bNjc53vnnzZklSYWFh3W3HH3+8JGnOnDm6+eabG4yfN2+e9uzZUzcGANC2/FQvLrjgApWXlzdaz4cffqiPPvpIY8eO1dChQzVq1CjH+wkAaB0/1YvmvPfeezLGaPDgwbbGA57K9qEigF/8+c9/NpLM0UcfbSSZcePGpR03e/ZsU1hYaHr37m2WLFniaBvf/OY3jSTz97//vdlxO3fubHTbW2+9Zdq3b28GDRpkysrKHG0XAOAur2rGZZddZiSZCy64oMGh5vF43Hz/+983kszkyZMbLHPccccZSWb27Nl1t1VVVZljjz3WSDL/+c9/MtxLAEBr+alepMPppwDAH/xSL7744guzdevWRutZu3atOeigg4wk89hjj2Wwh4C7LGOMaeM+CuBLu3btUp8+feoOo3v66af13e9+t8GYJUuWaMyYMaqqqtI555yjESNGNFrP4MGDNWnSpEa3b9q0Sf3791e3bt20du3aZk8FMn78eFVUVOiQQw5RSUmJPv30U7300kvq2rWr5s6dqzFjxrRqXwEAreNVzVi9erWOPPJIbdy4UQcddJBOPPFESdJrr72mxYsXa/jw4frvf/+rLl261C2zaNEiHX300aqoqNB3v/td9enTR7NmzdKiRYt09dVX6w9/+IMH9wAAwA4/1Yt0br/9dk2dOlV/+ctfOBocALLIL/Xi0Ucf1RVXXKFjjz1WQ4YMUZcuXbRy5UrNmjVLe/bs0fe//309/vjjsizLo3sCsCnbXRXA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nSwTJLm2f7eGPrR9qhNjpPiA70gB3/dc+xvui/1rfrl840XNcKte1Oenx222spylB2w3mY2R4uf/vc3mY/4+6ZHFvznqZ6Be2OP39xiZcONNXBAfD356HnotX/Y1X/ZTCt6+BiWnm3KhXrTl381Pj2mypEeW9MiSXtDeY/iqqeFUWVmZzjjjDN144406/PCmv2E/bdo0TZ06tdHtc+bMUXFxsePtzp071/EyQZIL+3ew/u3oAuGJhDS7x+nS7NnehWpDufA3bA7711B5eblHSXKLnZrhdr2oz0+P27bNEtad1lu2m8yJhDR70W5pUdvOx/n792keWRrzSw6JeuGVbL3HsGuCK2sxmh3g171+eh56LV/2NV/2UwrOvlIzWuZ9vXB66onszO1+ekyTJT2ypEeW9ILyHsMyxpisbDmN0tJSDRs2TNu2bVMkEpExRn369NG8efMadcV37dqlU045RRMmTNBPf/rTZtebris+YMAAbdmyRSUlJbbzxWIxzZ07V+PGjVM0GnW2cwGQS/uXvK27Cgrsj99VLbX72RbvArWRXPobpsP+pVdWVqbu3btr586djua0oPOiZrhVL+rz0+M2G1mGT5mjZeFzbTea43FJt7fdfJzvfx+yBC9Ha7JQL/z5HsOxO7s3/mZamnd08bg0PPFUk6tZdsd4V2O1BT89D72WL/uaL/spBW9f87Fm+K1eOHkdXTvnt+Xc7qfHNFnIQpbsZclWvfDVkRo9e/bUYYcdpieeeEKTJk3Sc889p/79+zcqHrt379app56qU089tcXiIUmFhYUqLCxsdHs0Gs3oAZPpckER+P1LJhV38IUGY6RxZrL+G+R93kfg/4YtYP8aj89HXtQMt+uF2+twi5+y7CuZlAqzkM1P9wlZ0vNLFr/kkKgXdgXlPUamMv2GWpAfD356HnotX/Y1X/ZTCs6+BiGj23KhXmTj7+anxzRZ0iNLemRJLyjvMXx1oXBJmj59uqZPn679999fd999t2bMmCFJuvjii/XCCy9Iku6991699957+vvf/64xY8ZozJgxuvPOO7MZG35y92mOLhAej0ubdJB3eQB4hprhf4dqrqPraUww13gbCEBeol4AAOygXgBAMPjqSA1JGjFihN55551Gtz/00EN1/z158mRNnjy5LWMhSKrftT3UGOna5KkehgHgJWqG/z1tzXB0PY0V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587mzTffNMYYs3TpUtOrVy9TXV2d1jrqH6A5uf02daBoTGbmPuxx85yaLG7ZB9Op/j7dtm3bBs3lsWPHmgULFjhUWXLNnj3bjBw5MmMf16ayPZMfU6SOW56DNFdHumq0O0emY1+zM4+l8n5JZJ5J1f0S67mqE/dLU8czbth2DzzwQMceo+aOrZzejxLFx08lYO3atXrwwQd1xx13OF1Kyr322mvatWuXxo4d63QprbJhwwYVFRUpEAhIkizLUt++fbV+/XqHK0uN++67T2eeeabTZSTV7373Ox199NE67LDDnC4l6dasWaPOnTvrzjvv1JgxY3Tsscfq9ddfd7osJJlbsyPd87yb52Mn5063zHFumo8sy9Jzzz2n73znO+rXr5+OOeYYPf7448rNzXWkHsm9228m5j7sces2mSrZMt7oPr1jxw4Fg0H17Nmz7m/9+/f3/HgvueQSFRcXa8aMGXryyScz9nGNle2Z+pgi9dyynzRXR7pqtDNHpnpfi2ceS+X9Eu88k477ZcSIEbr88su1bds2R+6Xpo5nnN523333Xe3atUunn366I49RU8dW5eXljm0vrRVwugA3GjdunFatWhXzbx9//LH+93//V3/84x+Vn5+f5sqSo6XxFRcXS5I+++wzXXbZZXruuefUtm3bdJaIVrjzzju1evXqjHpRfNmyZZozZ467PrsviUKhkL7++msNGzZMd999tz7++GNNnDhRy5cvV48ePZwuDza5KTuY5+Pn5NzppjnOTfNRKBTSL3/5S/3973/XcccdpyVLlmjKlCn67LPP1LVr17TW4maZmPtANqu/T1dWVjpdTko88cQTkqTHH39cN954o37xi184XFHyuSnbgUziljnSDfOY2+aZt956S3379lUwGNTPfvYzXXrppY7cL00dz8ydOzfttdT3yCOP6JJLLqlrnKRbU8dW9b8vx3OcPlXEa3bv3m06d+5s+vXrZ/r162e6dOli8vPzzYknnuh0aUm1fPly07dvXzN//nynS0mKTD2leX+/+c1vzGGHHdbgMx4zwQMPPGB69uxZt9/l5eWZbt26mQceeMDp0pJi27ZtxufzmVAoVHfZmDFjXHNKH1rPjdnh1DzvxvnY6bnTTXOcm+ajJUuWmMGDBze4bMyYMWnfZt3y0TexTul3etuF89w4pyabW/bBdIi1TxcUFLj2Yx+SoU2bNmbLli0Z97g2l+2Z/pgiNdzyHMTJj/CJd45M177W0jyWqvsl0XkmHffLpk2bTLt27RzZXpo6nnnuuecc23bLy8tNu3btzOeff153Wbofo+aOrZzeXhJFU6OV3Pa56MmwYsUK069fP/Pqq686XUpSHX/88Q2+9Oewww5ztqAku+eee8zo0aPNzp07nS4l5TLtOzWMMWbixIlm7ty5xhhjvvrqK9OlSxfzzTffOFwVUsXp7HB6nnfTfOzGudPpOc4t89GWLVtMu3btzIoVK4wxxqxatcp06tTJfP3112mtY/9mglPb7/51uHHbhTPcNKemglv2wVRrap++9NJLG3xBZ69evVzzBZ3x2rVrl9m4cWPd7//4xz9M7969TSQSydjHNap+tmfSY4r0cstzkObqSFWNicyRqdjXEp3H0vHY2Z1nUnG/7Nmzp0Gz6Z577jHHHntsXV3pvl+aOp5x6jF6+OGHzdFHH93gsnQ/Rs0dW6W7lmShqdFKTr8wlQoTJkwwHTt2NCNHjqz7LxMaHF988YU58sgjzeDBg81hhx1mPv30U6dLSpoNGzYYSWbgwIF1j9nhhx/udFkp4/QLfqmwZs0ac8IJJ5jhw4ebQw45xLzwwgtOl4QUcjo7nJ7n3TIfu3XudHqOc9N89PTTT9fVMXz4cPPXv/41beu+8sorTe/evY3f7zfdu3c3BxxwgDEm/dtvrDrcuu3CGW6ZU5PNLftgOjS3T2/ZssVMnDjRDBo0yAwbNswsXLjQ4WoTt27dOjN27Ni6ef2kk06qe6E0Ex/X+upneyY9pkgvNzwHaamOVNSY6ByZin0t0XksHY+d3XkmFffLmjVrzKhRo8yIESPM8OHDzZQpU8zatWuNMc7cL00dzzj1GI0bN848+uijDS5L92NkTNPHVk7UkgyWMcY4+vlXAAAAAAAAAAAANvicLgAAAAAAAAAAAMAOmhoAAAAAAAAAAMATaGoAAAAAAAAAAABPoKkBAAAAAAAAAAA8gaYGAAAAAAAAAADwBJoaAAAAAAAAAADAE2hqAAAAAAAAAAAAT6CpAQAAAAAAAAAAPIGmBrLWhRdeKMuy9MwzzzS7XFlZmQoKCtSxY0eVl5drzpw5uvTSS3XQQQepXbt2at++vY444gj9+c9/VjgcjnkblZWV+t3vfqfRo0erU6dO6tixo0aOHKk77rhDpaWlTa77jTfe0Jlnnqnu3bsrLy9PxcXFOvvss7V06dJWjR0AEB+3ZsYbb7why7Ka/e+AAw5I2v0AAGheOvNi165duv766zVo0CDl5eWpW7duOuecc7R8+fIm17ty5Uqdd9556tq1q/Lz8zVy5Ej9+c9/ljGmVeMGAMTHzXnxr3/9Sz/84Q919NFHq23btrIsSz//+c9bO2QgqSzDsxdkqddff10TJkzQhAkTtGDBgiaXmzVrlq6++mpdffXVuvbaa+uC46STTtLQoUNVWlqqf/3rX9q0aZNOP/10vfTSS7Isq+76wWBQxx57rN577z2NGjVKJ5xwgiRp0aJFWrp0qQ4++GC9//77KigoaLDeO+64Qz/72c/Uq1cvnXbaaeratau2bt2qd955Rz/72c900UUXpeR+AQA05tbMWLdunR577LGYtbz22mt65513dM011+iBBx5I2n0BAGhauvJix44dGjdunFatWqVx48Zp3Lhx2rx5s+bMmaNAIKCFCxfqiCOOaLDOFStW6KijjlJlZaXOO+889erVS3PnztXy5cs1ffp03X///Sm7XwAADbk5L0444QS9+eabKiwsVPfu3bV69WrdfvvtNDbgLgbIUpFIxAwYMMD4fD7z9ddfN7nc4YcfbiSZJUuWmG+++cb86U9/Mnv27GmwzJ49e8yYMWOMJPO3v/2twd+ee+45I8mcffbZjW77zDPPNJLM448/3uDyF1980UgyZ511lqmoqGh0vWAwGM9QAQCt5ObMaMrw4cONJPPhhx/aWh4A0Hrpyosf/OAHRpK57rrrGlz+7rvvGr/fb4YNG2bC4XCDvx133HFGkpk3b17dZdXV1ebYY481ksy7776b6LABAHFyc1689dZbZuXKlSYSiZhnnnnGSDK333576wYMJBkfP4WsZVmWLrvsMkUiEc2ePTvmMsuXL9f777+vQw45RGPGjFHv3r31/e9/X23btm2wXNu2bXXddddJkt58880Gf/vqq68kSaeeemqj2z/ttNMkSdu2bWtw+U033aT27dvrscceU35+fqPrBQIBm6MEACSDmzMjlvfff1/Lli3TqFGjNHr06JYHCABIinTlxT//+U/5fD7NnDmzweXjxo3TGWecoRUrVjS4zsqVK/XWW29p/PjxDTImNzdXv/jFLyRJf/nLXxIfOAAgLm7NC0k69thjNXjw4AZnfABuQ1MDWW3atGny+Xx67LHHYn6ObDRYLr/88hZvKycnR1LjhsPw4cMlSa+88kqj68ydO1eWZWn8+PF1ly1dulRffPGFJk6cqHbt2umVV17Rr371K91///18lwYAOMiNmdGUhx9+WJJ0xRVXtLgsACC50pEXW7ZsUdeuXdWuXbtG1xkwYIAkaeHChXWXvfHGG5KkSZMmNVr+mGOOUdu2bRu9qAUASC035gXgFbzdG1mtuLhYkyZN0quvvqqFCxfqpJNOqvtbKBTSU089pby8PFvfX/Hoo49KanygcNppp+mss87SP/7xDx166KENPh997dq1euihhxq8i/bDDz+UJHXu3FlHH3203nvvvQa3993vflePPvqocnNzExozACAxbsyMWPbu3atnn31W+fn5+u53vxvnKAEArZWOvOjatatKSkq0Z8+eRi9UrV27VlLt2RlRq1atkiQNHjy40Tr8fr8GDBigFStWKBQKcVY4AKSJG/MC8ArO1EDWi3a8owEQ9fLLL2vr1q0688wz1blz52Zv46GHHtIrr7yiE088UZMnT27wN8uyNGfOHN14441aunSp7r33Xt17771aunSpzj77bE2cOLHB8iUlJZJqO/I7duzQwoULVV5ero8++kjjxo3TX//6V82YMaO1wwYAJMBtmRHL888/r/Lyck2dOlUdO3aMb4AAgKRIdV6ceuqpikQijT5O5L333tPLL78sSdq9e3fd5aWlpZKkDh06xFxXYWGhIpGIysvLWx4cACBp3JYXgFfQ1EDWO/PMM9WtWzf94x//qHuyL30bKC2d5vfyyy9r+vTp6tevn5566qlGf6+oqNDZZ5+txx57TM8884y2b9+u7du369lnn9Wrr76qww8/XOvWratbPhKJ1P187rnnNH78eLVr106HHnqoXnzxRbVr105//OMfVV1dnYTRAwDi4bbMiOWRRx6xVQsAIHVSnRf/93//p6KiIv32t7/VMccco+uvv17f/e53ddxxx2nYsGGSJJ+Pw30AcDvyAkgMWy2yXk5Oji6++GJVVlbq6aefllT7mYOvvPKK+vbtqwkTJjR53Xnz5umcc85Rjx49tHDhQhUVFTVa5s4779RLL72khx56SOeff766dOmiLl266Pzzz9esWbNUUlKiO+64o2756Lun+vTp0+gjRrp3764jjzxSFRUV+vzzz5MxfABAHNyWGfv78ssv9fbbb2vQoEF1H10FAEi/VOdFnz59tGTJEl1++eVau3at/vCHP+i///2v/u///k+33HKLpNpjh6joMUb9F8zqKysrk2VZat++fcJjBgDEz215AXgFTQ1A33a+o+9uffLJJxUKhXTZZZc12bGeO3euvvOd76hr165atGiRBg4cGHO56Je9xvpi1+hlH3/8cd1lQ4cOlaQmPzIkenllZWULowIApIKbMmN/nKUBAO6RyryQpN69e+vhhx/Wxo0bVVNTozVr1ujGG2+se/PTmDFj6paNfpdG9Ls16guHw1q7dq0GDBjA92kAgAPclBeAV9DUACQNGzZMRx55pD788EN9+umnmj17tizL0mWXXRZz+blz52rq1Knq3LmzFi1apEGDBjV52zU1NZKkbdu2Nfpb9LK8vLy6y4488kjl5+frq6++UlVVVaPrrFixQpLUv39/2+MDACSPmzKjvlAopCeeeEKBQEDTpk2Lc1QAgGRLZV40JRwO69lnn1UgENDUqVPrLj/++OMlSfPnz290nbffflt79+6tWwYAkF5uygvAK2hqAPtEO+Pf//739fnnn2vChAnq169fo+VeeeUVTZ06VZ06ddKiRYvq3vXUlKOPPlqSNHPmzLrvy5BqA+T222+X1PAdue3atdPFF1+svXv36pe//GWD23ryySe1YsUKHXPMMTFPKwQApIdbMqO+6JcJTp48WT179kxoXACA5EpVXgSDwUZnbkciEV1//fX68ssv9cMf/lC9evWq+9vQoUN13HHHadGiRXVnBUq1zfQZM2ZIkq644oqExwkAaB235AXgFZYxxjhdBOAG5eXlKioq0t69eyVJzz77rM4///wGy3zxxRcaNWqUqqurdcEFF9R9VFR9/fv3b/AO2fXr1+uII47Qli1bdPDBB+vEE0+UJL3++utasWKFBg8erPfee0+dOnWqu86OHTt01FFHaeXKlTr++OM1ZswYrVq1Sv/617/UsWNHvf3223Vf6AQASD83ZUbUGWecoZdfflkvvfSSzjjjjCSOFgCQqFTlxTfffKODDz5YkyZN0oABA1RTU6N///vf+uKLL3Taaadpzpw5jc7sW758uY4++mhVVlbq/PPPV1FRkebOnavly5dr+vTpuv/++5N/BwAAbHFTXrz44ot68cUXJUlr167VW2+9pZEjR2rUqFGSpAMPPFA3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VVVVMsaorKxMffr0caJkAIBDyAwAgB3kBQDADvICALwj4HQB9W3YsEFFRUUKBGrLsixLffv21fr16zVo0KC65c444wwtWrRIPXv2VPv27dW7d2+9+eabTd5udXW1qqur634vKyuTJAWDQQWDwRSN5lvpWEes9aV7vc1xY00SdcXDjTVJ7qwr3TW5aezplIrMcDovksHs+xmSJI/U3BQ37t+pki1jzZZxSu4cq5tqSadMOMZI52Pnpm2XWmKjltioJbZEa3FD7emWCXmxv2DtilK6jpjrddE+UJ8b63JjTZI763JjTRJ1OTVuVzU17Prggw+0bNkybdy4UYWFhbrpppt09dVX66mnnoq5/F133aWZM2c2unz+/PkqKCiIc+3+OJc3mjdvXpzXSY4FCxY4st7muLEmibri4caaJHfWla6aKioq0rIer4onM5KbF8ngl2QlfG2n8ifZ3Lh/p0q2jDVbxim5a6zkRfPSd4zhjeMJN2271BIbtcRGLbHFWwuZ0TTnXpNK7NjAyWMCN+0D9bmxLjfWJLmzLjfWJGVvXU7lhWWMMS0vlh4lJSUaNGiQdu7cqUAgIGOMioqK9Pbbbzfoik+fPl29evWq+8zC5cuXa9KkSdq4cWPM243VFS8uLtb27dtVWFgYV42DZ8zXKv+FCthoB4VC0uDw01r1i0lxraO1gsGgFixYoIkTJyonJyet626KG2uSqCsebqxJcmdd6a6prKxMXbt2VWlpadxzmpelIjOSmRfJMHjG/EaXtZhB+45zQpJ06/ZUlJU2bty/UyVbxpot45TcOVbywh3HGG4/nnDTtkst1EItztWSjZnhtrzYX/1jA9s5YsmRYwI37QP1ubEuN9YkubMuN9YkUZdTeeGqMzW6d++u0aNH66mnntK0adM0Z84c9enTp0F4SNLAgQM1b948XX/99crNzdXLL7+s4cOHN3m7eXl5ysvLa3R5Tk5OWjY2pzbodI0vHm6sSaKueLixJsmddWX6HOO0VGSG03mRDNH3buVIkkdqbomX7v/WypaxZss4JXeN1S11pFsmHGM48di5bdullsaoJTZqiS3eWtxSdzplQl40WkftilK6jmbX76J9oD431uXGmiR31uXGmqTsrcupMbuqqSFJs2bN0rRp03TnnXeqsLBQs2fPliRdccUVmjJliqZMmaIf/OAH+vzzzzVy5Ejl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/5lE9nBD/qRDMmOjFzU2rq5bt07HHXec+vfvryFDhui///2vw9U23zHHHKNhw4ZpxIgROvTQQ/XJJ59Iyr73tdrMmTNlWZaee+45Sdn5niL1Mv15cMvfosmOh+n6XCUzXqX7vUtkTEnXeklmvy5d66WyslKXXXaZ+vfvr6FDh+qss85ypJbG/u534j2aM2eORo4cqREjRmjIkCF6+OGHm3w98il7uOFvKrcem+K4VMPc8reAnbqcPi7VUF2Ss8emOC4lySApRx55pJk5c6YxxphnnnnGjBo1KuM1VFRUmNmzZ5toNGqMMeZvf/ubOfzww40xxhx++OHm//2//5fxmqr16tXLfPLJJ/Ued8N6q/bnP//ZnHjiicaYzK6vt956y5SWltZbR42tm0yst3h1NbaNGZP+9dbQumpo+zLGuXW1p9rblzHOfyaRPdw0jqZSMmOjFzU2rp533nnm97//vTHGmA8//NB0797dVFVVOVRpamzevLnm///zn/+YYcOGGWOy7301xpilS5eaAw880BxwwAE14302vqdIk+lDSgABAABJREFUvUx/Htzyt2iy42G6PlfJjFfpfO8SHVPStV6S2a9L13q54oorzGWXXVazzaxevdqxWmqr/Xd/pt+jaDRq2rVrZz777DNjTGy7yc/PN2VlZY5sL8g8N/xN5dZjUxyXaphb/hawU5fTx6UaqssYZ49NcVzKGJoaSVi7dq1p3bq1CYVCxpjYHxJdunQxixYtcrSu+fPnm169ehljnN9Q432o3LbefvSjH9WsIyfWV+111Ni6yfR6a2xArL2NGZO59WY3ONy0rmpvX8Y4/5lEdnDbOJoOdsfGbFF7XG3ZsmXNARpjjBk9erSZN2+eQ5Wl3syZM83w4cOz8n2NRCLm6KOPNgsWLKgz3mf7e4rmc/Lz4La/Re2Oh5n4XNkZr9K5XpIZU9K1XhLdr0vXetm+fbtp3bq12bp1q+O17Kn23/2Zfo+i0ahp3769eeutt4wxxnz22WemW7duprKy0vHPEdLPrX9TueXYFMelmua2vwXi1bUnp45LxavLDcemcvm4FJefSkJpaamKi4sVCAQkSZZlqWfPnlq+fLmjdd111106+eSTa36+7rrrNHToUJ1xxhn6/vvvM17POeeco6FDh+r888/X+vXrXbXe3nvvPW3evFknnnhizWNOrq/G1o2b1tue25jk3Hrbc/uS3PPZjLd9Sc5/JuF9btnGMyUXlrd6XN24caNCoZC6du1a87vevXtnxbKec845Kikp0ZQpU/Too49m5ft6++236+CDD9a+++5b81g2v6dIHbd8Htzwt6id8TDdn6tExqt0rpdEx5RMrBe7+3XpWi9LlixR+/btdcstt2jUqFE69NBD9dprrzm+7db+u9+J98iyLD399NP6yU9+ol69eumQQw7Rww8/rG3btjm2vSBz3JIhe3LTsSmOS9nn9Hhql5uOS0nuPTaVC8elaGpkiVtuuUWLFy/W9OnTJUmPPvqovvnmG33++ec69NBD623E6fbf//5Xn3/+uT7++GN17NhR5557bkZfvykPPPCAzjnnnJoBxun15QV7bmOSc+vNa9uXxDYGoL5442o2euSRR1RaWqqbbrpJ1157rdPlpNyXX36pWbNm6Xe/+53TpQCe5Zbx0A3jldvGFLf83R0Oh/XDDz9o8ODBWrBggf7617/qjDPOUDgcdqSeavH+7s+kcDism266Sf/5z3/0ww8/6LXXXtPZZ5/t+HpB7nLTsSm3jF8N4bhU4tx0XEpy9zaWE8elnD5VxIvcdrran//8Z7PvvvvWuQ7snvLz882GDRsyV1Qtq1atMq1atXLNetu2bZtp1aqV+frrrxucJhPry0un+dnZxoxJ33pr7HS66u3LGHdcfsrO9mWMs59JeJdbxtF0ypXLT8UbVwsLC7P+UhAtWrQwa9asyar39Z///Kfp2rWr6dWrl+nVq5fJz883nTp1Mv/85z9z4j1F83D5qcTHw0x9rpoar9K1XpIdUzKxXuzs16Vrvaxfv974fD4TDodrHhs1apR5+umnHdt24/3dn+n3aP78+aZ///51Hhs1apSZO3eu49sL0s9tfyu7+dgUx6Xic8vfAo3VVc3p41IN1VXNqWNTuXxcijM1ktC5c2eNHDlSjz32mCRp1qxZ6tGjh/r165fxWm6//XY9+eSTmjdvntq2bSsp9m2NtWvX1kwza9YsdenSRR06dMhITTt27NCWLVtqfn7yySe1zz77uGa9Pf300xo+fLh+9KMfSXJ+fUmNb1NOr7d425jk3HpraPuS3PHZ3HP7ktyxjSE7uGEbz6RsXd6GxtXTTz9dd999tyRp/vz5WrlypQ4//HCHqmy+LVu2aNWqVTU/P/fcc+rQoUPWva8XX3yxVq9erWXLlmnZsmU64IADdO+99+riiy/OuvcUqeeWz4NTf4smMx6m43OVzHiVrvWS7JiSjvWSzH5dutZLx44ddfTRR+uVV16RJC1dulRLly7VwQcf7Nh+VLy/+zP9HpWUlGj16tX6+uuvJUmLFy/WkiVLNHDgwIzXgsxzS4ZI7js2xXGpxHFcKjFuPjaVM8elnO6qeNU333xjDjjgANO/f3+z7777ms8//zzjNZSWlhpJpm/fvmb48OFm+PDhZr/99jPbt283++67rxkyZIgZNmyYOeqoo8ynn36asbqWLFliRowYYYYOHWqGDBlixo8fb5YuXWqMccd6O/DAA82DDz5Y83Om19eFF15ounfvbvx+v+ncubPZa6+9jDGNr5tMrLd4dTW0jRmTmfUWr6bGti9jnFtX1fbcvozJ/DaG7OaGcTQdkhkbvaixcXXNmjVm7Nixpl+/fmbw4MHm9ddfd7ja5lm2bJkZPXp0zdh39NFH13yLKNve19pq34Av295TpEemPw9u+Vs02fEwHZ+rZMerTLx3dseUdKyXZPfr0rVelixZYo444oia9+nZZ591rBZj4v/dn+n3yBhjnnjiiZp1MmTIEPP44487Vgsyzw1/U7nx2BTHpRrnlr8F7NTl9HGphupy+tgUx6WMsYwxxsmmCgAAAAAAAAAAgB1cfgoAAAAAAAAAAHgCTQ0AAAAAAAAAAOAJNDUAAAAAAAAAAIAn0NQAAAAAAAAAAACeQFMDAAAAAAAAAAB4Ak0NAAAAAAAAAADgCTQ1AAAAAAAAAACAJ9DUAAAAAAAAAAAAnkBTAzlrwoQJsixLTz75ZKPTlZWVqbCwUG3bttW2bds0a9YsnXvuuRo0aJBatWql1q1ba//999e//vUvRSKRuPPYvHmzrrnmGvXr10/5+fnq1KmTTjvtNC1cuLDetBs3btS9996r8ePHq2/fvsrPz1fHjh11/PHH65VXXknJsgMAEuPWzJCkG2+8UWPGjFFJSYkKCgrUsWNHjRo1SnfccYfKy8ubvewAAPvcnBd7evrpp2VZlizL0lNPPZXwsgIAkufmvDjiiCNq8mHPf3r37t3cRQdSwjLGGKeLAJzw2muvacyYMRozZozmzZvX4HT33HOPLrroIl100UW6/PLLa4Lj6KOP1sCBA7V161a98MILWrVqlU488UQ9//zzsiyr5vkbN27UgQceqEWLFunAAw/UgQceqNWrV2vWrFkKBAJ6/fXXtf/++9dMf/fdd+viiy9Wt27ddPTRR6t79+5asWKFZs2apYqKCt166636zW9+k9Z1AwCoy62ZIUnt27dX//79NWTIEHXu3Fnbtm3Tm2++qYULF2r48OF67733VFhYmLZ1AwDYzc15UduaNWs0ZMgQ7dy5Uzt27NCTTz6pM888M6XrAgDQMDfnxRFHHKG33npLv//97+vV07ZtW11xxRUpWw9A0gyQo6LRqOnTp4/x+Xzmhx9+aHC6/fbbz0gy8+fPNytWrDD/+Mc/zPbt2+tMs337djNq1Cgjyfz73/+u87tLL73USDJXXXVVncffe+894/f7zeDBg00kEql5/LXXXjPPP/98nceMMeabb74xbdq0McFg0KxcuTLZxQYAJMGtmWGMMRUVFXFrOeuss4wk8/e//z2RRQUANIOb86K2k046yfTu3dtcffXVRpJ58sknk1haAECy3JwXhx9+uOGQMdyOy08hZ1mWpfPOO0/RaFQzZ86MO83ChQv14YcfatiwYRo1apS6d++uSy65RC1btqwzXcuWLXXVVVdJkt566606v/u///s/+Xw+TZs2rc7jBx54oE466SR99dVXdZ5z1FFH6aSTTpLPV/fjOXDgQJ1xxhkKhUJ67733kl5uAEDi3JoZktSiRYu49Zx++umSpMWLF9tfUABAs7g5L6o99NBDeuGFF3T//ferVatWyS4qAKAZvJAXgJvR1EBOmzhxonw+nx566CGZOFdiqw6W888/v8l5BYNBSVIgEKjz+Jo1a9SxY8e4Owx9+vSRJL3++uu26m3oNQAA6ee1zJg9e7YkaciQIbamBwCkhpvzorS0VFdccYUuvPBCHX300U0vDAAgbdycF5L0xBNP6JZbbtGdd96pN998U9FotMk6gEyhqYGcVlJSomOOOUbLli2rN4iHw2E99thjys/P11lnndXkvB588EFJ0jHHHFPn8Y4dO2rDhg3avn17vecsXbpUkvTdd981Of+ysjI9++yzatGihQ499NAmpwcApJbbM+PWW2/V1KlTdcUVV2j06NG69957dcwxx+icc86xtXwAgNRwa14YY3T++eerqKhIf/nLXxJaJgBA6rk1L6r9/Oc/1w033KArr7xSRx55pAYNGqQFCxbYWjYg3WhqIOdVd7yrA6Da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AABICzQ1ErR+/Xp17txZJ598sttR9M9//lNDhgzRXnvtpb333lvPPPOMa1kWLlyoQw45RLvvvrsOOOAAzZkzx7UsVcrKynTyySdr99131z777KORI0dq0aJFbseqNmXKFFmWpddee83tKJKk8vJyXXbZZRowYID22msvnXnmmW5HkiRNmzZN++23n4YOHaohQ4boySefTHmGyy+/XH369JFlWfruu++qb/fi+x7OmThxojp27KihQ4dq6NCh+u1vf+t2pJTi/R7Vp08fDRw4sPp98OKLL7odKSVYD+7S0LLI1PcGnMN2R31eW+ewvRE/r21rsI0BL/LSer8ur9SBWNLhd8br9aIuL9WPWLxWU2LxQp2JpUXUHoOEnHzyyea8884zJ510kttRzLvvvmu2bt1qjDFm+fLlpn379mbRokWuZDnyyCPNlClTjDHGvPzyy2bYsGGu5KiptLTUTJ061UQiEWOMMffee6854ogj3A21088//2yGDx9uDj74YPOf//zH7TjGGGN+//vfm8suu6x6ea1Zs8blRMZEIhHTtm1b8/333xtjosstOzvbFBUVpTTHhx9+aFasWGF69+5tvv322+rbvfi+h3P+9Kc/mSuuuMLtGK7h/R5Vdz2QKVgP7tLQssjU9wacw3ZHfV5b57C9ET8vbWuwjQGv8tJ6vy6v1IFY0uF3xsv1oi6v1Y9YvFRTYvFKnYmlJdQejtRIwGOPPaa+ffvq8MMPdzuKJOnoo49W69atJUk9e/ZUly5dtGLFipTnWL9+vWbNmlXdGR07dqxWrFjhetc5JydHo0ePlmVZkqSDDz5YS5cudTWTJEUiEV1wwQW69957lZ2d7XYcSdKOHTv02GOPadKkSdXLq0uXLi6nirIsS1u3bpUkFRUVqX379ilfbr/4xS/Uo0ePWrd59X0POIH3O1gP7hJrWQDJxnZHfV5c57C9ER8vbmuwjQGv8dp6vy4v1IFY0uV3xqv1oi6v1Y9YvFhTYvFCnYmlJdQemho2/fzzz3rwwQc1adIkt6PE9O6772rLli064IADUv7YK1asUNeuXRUIBCRFf3F79eql5cuXpzxLY+655x6ddNJJbsfQXXfdpUMPPVT777+/21GqLV68WO3atdNtt92mYcOG6fDDD9d7773ndixZlqUXX3xRp5xyinr37q3DDjtMTz75pLKystyOljbveyTXyy+/rH322UdHHXWUZs6c6XaclOH9XtvZZ5+tvfbaS+eff742bNjgdhzX8L6oj/cGkoHtjtjSYZ3D9kZsXtvWYBsDXuP19X5dbu5/qitdf2e8Ui/q8lr9iMVrNSUWL9eZWNLt9yjgdgCvGT58uBYuXBjzZ99++63OO+88/etf/1Jubq5nMvXs2VOS9OOPP+rcc8/Viy++qFatWqUsXzq57bbbtGjRItdXdLNnz9arr76q//3vf67mqCsUCmnZsmUaNGiQbr/9dn377bcaOXKk5syZo86dO7ua69Zbb9W///1v/eIXv9BXX32lE088UT/++KM6dOjgWi60TE2tcy+55BJNmDBBwWBQn3zyicaMGaOvvvpKvXv3TnFSuOl///ufevXqpcrKSt14440655xzNG3aNLdjwQN4byBebHe0TGxvNMxr2xpsYyDVvLjer4s6kDpeqRd1ebF+xOK1mhILdcZhbp//Kp1s3brVtGvXzvTu3dv07t3btG/f3uTm5pqjjjrK7Whmzpw5plevXmb69OmuZVi3bp0pKCgwlZWVxpjoueM6d+5sFi5c6Fqmmv72t7+Z/fff32zZssXtKOb+++83Xbp0qX4vZWdnm44dO5r777/f1VwbNmwwPp/PhEKh6tuGDRtmZsyY4WIqY7766iszYMCAWrcNGzbMtfd7zXMOev19D+eNGjXKvPLKK27HSAne77GtXr3a5Ofnux0jpVgP7tLYNTQy8b2B5GC7o2FeXuewvdE4r21rsI0BL/Hyer8ut+tALOn2O+OlelGXF+tHLF6rKbF4rc7Eks61h6ZGM0yZMsUTF26aO3eu6d27t3n77bfdjmKOOOKIWheU2X///d0NtNOdd95p9ttvP7N582a3o8R0xBFHeObCSyNHjjRTp041xhizZMkS0759e7Ny5UpXM61du9bk5+ebuXPnGmOMWbhwoWnbtq1ZtmyZK3nq7sDy6vsezlixYkX1/y9YsMB06tTJzJ8/38VEqcX73Zji4uJaGyB33nmnOfzww90L5ALWg7vUXBa8N+AUtjtq8+I6h+2N+HhpW4NtDHiZV9b7dXmlDsSSLr8zXq8XdXmlfsTipZoSi9fqTCzpXHtoajSDV4rMiBEjTJs2bcw+++xT/cetAvPTTz+Zgw8+2AwYMMDsv//+5ocffnAlR00rVqwwkky/fv2ql8+BBx7odqxavFQkFi9ebH75y1+aIUOGmL333tsz30B/7rnnqjMNGTLEPPvssynPcNFFF5nu3bsbv99vOnXqZHbbbTdjjDff93DO2WefbQYPHmz22Wcfs99++5mXX37Z7Ugpxfs9up4cOnSo2WuvvcyQIUPMiSeeaH7++We3Y6UE68FdYi2LTH5vwFlsd9TmtXUO2xvx89q2BtsY8CqvrPfr8kodiCUdfmfSoV7U5ZX6EYvXakosXqgzsbSE2mMZY4zLZ8ACAAAAAAAAAABoks/tAAAAAAAAAAAAAPGgqQEAAAAAAAAAANICTQ0AAAAAAAAAAJAWaGoAAAAAAAAAAIC0QFMDAAAAAAAAAACkBZoaAAAAAAAAAAAgLdDUAAAAAAAAAAAAaYGmBgAAAAAAAAAASAs0NZCxxo0bJ8uy9Pzzzzc6rqioSHl5eWrTpo22b9+uV199Veecc4723HNP5efnq6CgQAcddJAeeOABhcPhmPexZcsWXXPNNerfv7+ys7PVsWNHnXrqqZozZ069sR988IEsy2r0z2677ZaUZQAAiI9Xa0aVmTNnavTo0erZs6dyc3O12267ady4cfr++++b9bwBAPZ4vV4899xzOvTQQ5Wfn69WrVrpgAMO0BNPPNGcpwwASEAi9aK0tFTPPvusxowZo912200FBQXKz8/X4MGDdeWVV2rVqlUN3s+zzz6rAw88UK1atVLbtm11/PHH65tvvqk3btWqVbr77rs1atQo9erVS1lZWerSpYvGjh2rL774otnPG0gWyxhj3A4BuOG9997TiBEjNGLECM2YMaPBcQ899JAuueQSXXLJJbriiiuqNzSOPvpoDRw4UNu2bdMbb7yh1atX6/jjj9frr78uy7Kq52/atEnDhw/XwoULNXz4cA0fPlxr1qzRq6++qkAgoPfff18HHXRQ9filS5c2uGHx7rvv6pNPPtHvfvc73X///UlbFgCAxnm1ZkjSvffeq8svv1xt2rTRKaecoo4dO2rBggV64403ZFmWpk2bphEjRji2bAAAu3i5Xlx99dW666671KVLF5144okKBoOaNm2afv75Z1199dX6+9//7thyAQDUlki9eOCBB3TCCSdo4cKF2n///dW1a1cZY/Tdd99p5syZat26tT7++GMNHjy41n1MmjRJN954o3r37q2xY8dq+/bteuGFF1RRUaH33ntPhx56aPXY66+/XnfccYd22203/fKXv1THjh21cOFCvfbaazLG6LnnntPpp5/u2HIB4maADBWJREzfvn2Nz+czy5Yta3DcgQceaCSZr776yqxcudLcd999pri4uNaY4uJiM2zYMCPJvPTSS7V+9n//939Gkrnqqqtq3f7pp58av99vBg0aZMLhcFyZhwwZYiSZr7/+Os5nCQBIBq/WjIqKClNYWGgKCwvN8uXLa83597//bSSZI488MtGnDQCwyav14quvvjKSTP/+/c2mTZtqPcYBBxxgJJlPP/20OU8dAGBDIvXCGGNKS0tjjnv00UeNJHPqqafWun3BggUmEAiY3Xff3WzdurX69m+//dZkZ2ebPffcs1a9ePXVV80HH3xQ7/7/97//mWAwaNq2bWvKyspsPVfACZx+ChnLsiyde+65ikQimjJlSswxc+bM0Zdffqm9995bw4YNU/fu3XXppZeqVatWtca1atVKV111lSTpww8/rPWz//73v/L5fLrllltq3T58+HCdcMIJmjt3br05sXz55ZeaPXu2hg4dqv3228/OUwUANJNXa8amTZtUVFSkIUOGqGfPnrXm/OpXv5JlWdqwYUPCzxsAYI9X68V///tfSdKVV16pdu3a1XqMCRMmSJIefPDBBJ81AMCuROqFJOXk5MQce9ppp0mSFi1aVOv2KVOmKBQKacKECWrdunX17UOHDtVvfvMbzZs3Tx9//HH17aeccoqOOOKIevd/+OGH68gjj9SWLVv0448/2nuygANoaiCjjR8/Xj6fT0888YRMjDOxVRWW888/v8n7CgaDkqRAIFDr9rVr16pDhw7Kz8+vN6dv376SpPfff7/J+3/00UclSRdccEGTYwEAyefFmtG5c2d16NBBs2fP1ooVK2qNnzp1qowxOvroo5vMAwBIHi/Wi7Vr19b6WVPjAQDOS2a9mDp1qiRpyJAhtW7/4IMPJEmjRo2qN+eYY46RVL9x3pCGahLgBpoayGg9e/bUqFGjtHTp0nof4kOhkJ555hllZ2frzDPPbPK+Hn/8cUn1C0WHDh20ceNGFRcX15vz888/S5IWLFjQ6H3v2LFDL7zwgnJzc/Xb3/62ySwAgOTzYs2wLEv33XefSktLtffee+v888/X9ddfr1NOOUWnn366TjvtNN166622nysAIHFerBcdOnSo9bNY41euXKmSkpImMwEAkqM59eKll17SxIkTde211+pXv/qVzjrrLPXt21d//vOfa41buHCh8vPz1aVLl3r3MWDAgOoxTVm+fLneffddde3aVXvttZedpwk4gqYGMl5Vx7tqg6HKm2++qXXr1umkk06qdYh2LA8//LDeeustHXXUURo9enStnx133HGKRCL1Dg3/4osv9Oabb0qStm7d2uj9v/zyy9q+fbvGjh2rNm3axPGsAABO8GLN+PWvf6133nlH2dnZevzxx3XHHXfoP//5j/bYYw+dffbZMb/FCwBwltfqxXHHHSdJuvvuu2vdXlJSosmTJ1f/e9u2bfE9QQBAUiRaL1566SXdcsst+tvf/qZp06Zp33331YwZM+odkbdt27Zap52qqbCwsHpMYyorK3XWWWepvLxcd9xxh/x+f9zPD3CMq1f0ADygoqLCdOzY0eTm5ta6aNIJJ5xgJJl33nmn0flvvPGGCQaDpnfv3mb16tX1fr5ixQrTtWtXI8kceuih5uqrrzbjxo0zWVlZZu+99zaSzLHHHtvoYxx22GFGkpk5c2ZCzxEAkBxerBmPPvqoycrKMldeeaVZvHix2bFjh/n666/NqFGjjCRz3333JefJAwDi5sV6cdZZZxlJpmvXrubiiy82l112menXr5/p1auXad26tZFk1q5dm5wFAACIS3PrxZYtW8z7779vhg8fblq3bm3ee++9Wj8PBoOme/fuMecuWLDASDInnnhig/cfDofNuHHjjCRz4YUX2nhmgLNoagDGmKuuuspIMvfff78xxpg1a9aYQCBgevXqZcLhcIPzpk6darKzs02PHj3M4sWLGxy3cuVKc/7555tu3bqZYDBo+vXrZ26//XbzwgsvGEnm7LPPbnDuTz/9ZCSZ/v37J/4EAQBJ46WaMW/ePBMIBMyYMWPq3c+OHTtM9+7dTUFBgSktLW3GMwYAJMJL9cKY6I6pe+65x+y9994mOzvbtGnTxpx++ulm2bJlJj8/3wQCAVNRUZGcJw8AiFui9aKmbdu2mS5dupju3bvXWpd36NDB5Ofnx5wza9YsI8mcddZZMX8eDofNOeecYySZM888M+4sQCpw+ilAuw73e+yxxyRJTz/9tEKhkM4991z5fLF/TaZOnapTTjlFHTp00MyZM9WvX78G77979+569NFHtWrVKlVUVGjx4sW67rrrNG/ePEnSsGHDGpxblSmeC0MBAJznpZoxY8YMhUIhHXnkkfXuJy8vTwceeKC2b9+uRYsWJfx8AQCJ8VK9kCSfz6fLL79c33//vcrKyrRlyxa98MILikQiKi4u1t577119EVgAQOokUi/qKiws1MEHH6xVq1bV+uw/YMAAFRcXa+3atfXmVF1Lo+raGjVFIhGde+65evLJJ/Wb3/xGTzzxRNxZgFTg3QhIGjRokA4++GB9/fXX+uGHHzRlyhRZlqVzzz035vipU6dq7NixateunWbOnKn+/fvbfsxwOKwXXnhBgUBAY8eOjTkmFArpqaeeUiAQ0Pjx420/BgAg+bxUMyoqKiRJGzZsiDmv6vbs7GzbjwkAaB4v1YvGPPvss5KkM844w/bjAQCaz269aMjq1aslqVaD+ogjjpAkTZ8+vd74d955p9aYKlUNjaeeekqnn366nn76aa6jAc+hqQHsVNUZv/TSSzVv3jyNGDFCvXv3rjfurbfe0tixY9W2bVvNnDkzZke7psrKSpWWlta6LRKJ6JprrtH8+fP1//7f/1O3bt1izq26MNTo0aPVpUuXBJ8ZACDZvFIzDj30UEnRi8muWrWq3mN/8skn6tmzZ0I7xgAAzeeVeiFJRUVF9e7no48+0uTJk9W7d29dcskldp8eACBJ4qkX27dv1/z582POf/zxx/Xll19qwIABtT77n3vuuQoEApo0aVKtC4J/9913ev7557XnnnvqsMMOq749EonovPPO01NPPaXTTjtNzzzzDA0NeJJljDFuhwC8YPv27eratat27NghSXrhhRd0+umn1xrz008/aejQoSovL9cZZ5yhgQMH1rufPn361DqqYuXKlRo8eLBGjRqlvn37qqKiQu+8845++ukn/epXv9Krr77a4DdoTzjhBL355pt6/fXXdcIJJyTvyQIAmsVLNeO3v/2tnnvuORUUFGjMmDHq0qWL5s2bpzfffFM+n0+vvvqqTjrppOQvBABAk7xUL0aNGqXS0lLtvffeKiws1I8//qi33npL7dq104wZMzR06NCkP38AQHziqRdLly5Vv379NGzYMO2xxx7q3r27tmzZoq+++krffPONCgsL9fbbb2v48OG15k2aNEk33nijevfurbFjx2r79u164YUXVFFRoffee6/6i1KSNHHiRN1yyy3Kz8/XFVdcoUAgUC/rySefTM2A+9y+qAfg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8rqUakpKSnTVVVepZ8+e6t+/v84//3yvS6pm5syZGjx4sAYNGqR+/frp8ccf97qkpOQo/OWBBx5Q//79K9azv//9757W47eMePXVV3XQQQcpNzdXV199tSc1+O39Vdt2wAt+zMWRI0dqwIABGjRokI488kh98cUXntZTzk+ZbHcfFv7lxnYpkd8xUnVfXduawsJCnXjiierZs6f69eun999/v+KxUnVfbdsdPyy7cntvg/yw3GrbFvlhudW2r+J1bR9++GGtn/P54TX1lIFr3nzzTbN161ZjjDErV640LVu2NEuXLq1x7NFHH23+/e9/u17T8OHDzbRp04wxxrzwwgtmyJAh1cZ8//33pl27dmbt2rUmFouZU045xdx///2u12aMMbt27TKvvvqqicVixhhj7rvvPnP00UdXG7d8+XLTrFmzlNS0ty5dupgvvviizjFeLsPK7rrrLnPyySdXuz2Vy++9994zq1atqrbc7KyLxqRmWdZUo9110Rhv10f4x+mnn25+9atfmdNOO83rUqpxkkepZndb4BUn2wKvLV++3Bx22GHm0EMPTcnvFE5dffXV5qqrrqpYlmvXrvW4oqpisZjZZ599zPz5840x8eWZm5trioqKPK2roTkK/ynfHhtjzLZt20ynTp3MvHnzPKvHbxmxaNEi8+WXX5pbbrnF/Pa3v/WkBr+9v2rbDnjBj7m4ZcuWiv//61//MgMGDPCumD38lsl+WHfQMG5slxL5HSNV99W1rbn44ovN7bffbowx5tNPPzUdOnQwpaWlKb2vsLCwov7K2x0/LDtjat4G+WG51bYt8sNyq21fxQ+1VVb5cz4/vKbl93mBpkYK9e3b17zzzjs13peKpsb69etN06ZNTSQSMcbEd97btGljlixZUmXcX/7yFzN27NiKn1999VUzbNgwV2urzdy5c02XLl2q3e73poZfluH+++9f43rlxfKrvNzsrovGpHZZ1vXa1rYuGkNTA8Y88sgj5pprrjHTpk3zZVNjb3XlUSo52Rb4RV3bAi+VlZWZ4447znz22Wcp+6KEEzt27DBNmzY127Zt87qUWsViMdOiRQvz3nvvGWOMmT9/vmnfvr0pKSnxuLK4RHMU/rZmzRrTtm1bT5sae/NLRtx+++2eNDX8/P7y4wfTfsvFadOmmYEDB3pagx8z2Y/rDuxze7tk93eMVN9X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rMyUlJRUe/xIJGKOOeYYI8m88sorjp4rAKBh/JoZlZWWlprBgwebQw45xJx//vlGkpkzZ47TpwoAaAA/50WXLl1Mly5dEnxmAIBk8nNe/O1vfzOSzK9//WsTjUarzSsSidh+noBb+Ko3MpZlWbr44osVi8U0bdq0GscsWLBAn376qQYMGKAhQ4ZIkvLy8moce/bZZ0uSli5dWuX2adOmKRqN6pZbblGzZs0qbh80aJB++ctf6ttvv9UHH3xQcXsoFFJOTk61xw+HwzrjjDNqnAcAwF1+zYzKJkyYoAULFujRRx9VVlaW4+cIAGi4IOQFAMB7fs2LXbt2afz48erevbvuvffeGvcrwuGwsycLuICmBjLa6NGjFQqF9Nhjj8nUcCa28mAZM2ZMvY/16quvSpL69etX5fZ3331XkjRy5Mhq05xwwgmSpPfee6/ex4/FYnr99ddrnAcAwH1+zox58+ZpwoQJuv3229WnT5965w8AcI+f86KkpESPPfaY7rzzTt1///365JNP6q0BAOAOP+bFrFmztGXLFp1++ukqKyvTv/71L02aNEkPPfQQX7CFr9BaQ0br1KmTRo4cqddff11vv/22jjvuuIr7otGonnrqKeXm5ur888+vNu3zzz+vhQsXqri4WAsWLNAbb7yhbt266Q9/+EOVcUuWLFGTJk3Utm3bao/Rs2fPijF7Ky0t1Z133iljjDZt2qS33npL3333nS6++OIqdQIAUsOvmVFSUqILL7xQgwYN0vXXX5+MpwoAaAC/5oUkrVu3ThdffHGV24YOHapnnnlG++23X0LPFwCQGD/mxeeffy5JysrK0oABA7R48eKK+0KhkK655hrdfffdDXviQBLQ1EDGGzNmjF5//XU9+uijVQLklVde0fr163XOOeeoRYsW1aZ7/vnn9eKLL1b8PGTIED377LPq1q1blXHbtm1T69ata5x3QUFBxZi9lZaWavz48RU/W5al6667ThMnTnT2BAEASePHzLjtttu0ZMkSff7555x2CgB8wo95cfHFF+vII49Uv3791KRJEy1evFj33HOPnnzySR133HH6+uuv1bRp04SfMwDAOb/lRWFhoSTpnnvu0eDBg/Xpp5/qgAMO0BdffKHLLrtMkydP1n777acrrrgi8ScNJAGnn0LGO+2009SqVSv9+9//rrIhf/TRRyXVfpjfjBkz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sdrlRo4cmU022SQf/ehHc8MNN6x1kQBUi7wAoF4yA4B6yAsAevSrqXHJJZfkJS95SU4//fQXXfbd7353Nt5440yfPn3AxQFQTfICgHrJDADqIS8A6NGvpsYvfvGLHHbYYRk1atSLLjtq1Kgcdthh+fnPfz7g4gCoJnkBQL1kBgD1kBcA9OhXU+PRRx/NtttuW/fy22yzTR577LF+FwVAtckLAOolMwCoh7wAoEe/mhptbW1r/DKmF+rs7ExbW7+/ixyAipMXANRLZgBQD3kBQI9+nd233HLL3HXXXXUvf9ddd2X8+PH9LgqAapMXANRLZgBQD3kBQI9+NTUOOuigXH/99XnwwQdfdNkHH3ww119/fQ4++OCB1gZARckLAOolMwCoh7wAoEe/mhrvfve709nZmTe84Q3505/+tNrlnnrqqbzxjW9MV1dX3vnOd/aroHvvvTf7779/Jk+enH333TezZs1a7bJFUeTQQw/NRhtt1K91ADC4hiIvEpkBMBy4xgCgHvICgB79amrsvffeed/73pfbb789O++8c84555zccMMNuffee3PvvffmJz/5Sc4+++zsvPPOue222/L+978/e++9d78KOvXUU/OOd7wj99xzTz70oQ9l2rRpq1323/7t3/LSl760X88PwOAbirxIZAbAcOAaA4B6yAsAerT39wHnn39+1llnnfzrv/5rPvWpT+VTn/rUSvcXRZERI0bkIx/5SD75yU/267nnzZuXW2+9NTNmzEiSHHfccTn99NMze/bsbLfddistO2vWrHzve9/L9OnTc9lll/V3GAAMssHMi0RmAAwnrjEAqIe8ACAZQFOjVqvl05/+dN7+9rdn+vTp+cUvfpHHH388SbLFFlvkgAMOyLRp0wbUrZ47d27GjRuX9vb23nVNmjQpc+bMWSlAOjs7c8opp+Siiy7KiBEjXvR5lyxZkiVLlvT+PH/+/N7n6ezs7Hedq9PI52q2nrEMpzH1pVXGmRjrcFT2cQ5mXiSDkxmtkBdlnjdlri0pd31qG5hWq62M4+zhGmP1yrrfynz8rElV606qW3tV606qW3sj6i7rmOXF6pVln1XluFFnY6mzsapWZzP0u6nR46UvfemA/rK2Ec4999y8/vWvz0477VTXF0Sdd955Offcc1e5fcaMGRk9evRqHvXiwbSyItdee20/H1N+M2fObHYJ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4yxYsCAbbrhhs8sYVuQFMBzJi8EhM4DhSGY0nrwAhqOhzota0YJt9+7u7jz66KPZYIMNUqvV6n7c/PnzM3HixMydOzdjxowZxAqbr1XG2irjTIx1OOoZ55w5c1Kr1bLlllumrc2nCjbScMwLtQ1cmetT28C0Wm1FUWTBggXyYpAMx8xYE3UPvarWXtW6k+rW3oi6ZcbgGe55oc7GUmdjqbOxeuq8++67s8MOOwxpXrTkOzXa2toyYcKEAT9+zJgxpZ5QjdQqY22VcSbGOhxtuOGGLTHOZhjOeaG2gStzfWobmFaqzV/bDp7hnBlrou6hV9Xaq1p3Ut3a17ZumTE4WiUv1NlY6mwsdTbW+PHjh7wBrt0OAAAAAABUgqYGAAAAAABQCZoa/TBq1Kh87GMfy6hRo5pdyqBrlbG2yjgTYx2OWmWcVVTmfaO2gStzfWobGLVRBlXd1+oeelWtvap1J9Wtvap1s2ZV2a/qbCx1NpY6G6uZdbbkF4UDAAAAAADV450aAAAAAABAJWhqAAAAAAAAlaCpAQAAAAAAVIKmRh/uvffe7L///pk8eXL23XffzJo1q8/lLrroomy//fZ56UtfmlNOOSWdnZ1DXOnaq2es119/ffbbb7/svPPO2WWXXfLBD34w3d3dTah24Ordp0lSFEUOPfTQbLTRRkNXYAPVO9bf/e53OeSQQ7LTTjtlp512ypVXXjnEla6desbZ3d2dM844IzvvvHN23333TJkyJbNnz25CtWvnPe95T7beeuvUarXccccdq11uOJyThov+nHPqtbp5sKZ1DcV9t99+e/72b/82kydPzh577JGpU6f2Hmfz5s3LEUccke233z677rprbrzxxt7nGar7Dj/88Oy+++7Zc889c9BBB+U3v/lNKbbbivdNnz49tVot3/ve90qz3ZJk6623zg477JA999wze+65Z/73f/+3NNtuyZIlOf3007P99ttnt912ywknnFCK2n7+85/3bq8999wzkydPTnt7e55++unS7FfKZTDyYm0M5XG/NsqSiY2sfXXbviy1L168uDR536i6DznkkGyzzTa92/zf/u3fSlN3ktK8hqEchnIfVem4Kcvr1TV56qmnVvv6sNnbsyx5+mLbtq861zRPk+bM1bJk/EC255rmabO254sqWMWUKVOK6dOnF0VRFJdddlmxzz77rLLM/fffX4wbN6547LHHiu7u7uKYY44p/uM//mOIK1179Yz19ttvL+67776iKIpi0aJFxQEHHND7mKqoZ5w9zj///OLkk08uNtxww6EprsHqGeuf//znYptttil+9rOfFUVRFF1dXcW8efOGssy1Vs84v/vd7xb77bdfsXTp0qIoiuITn/hE8cY3vnEoy2yIn/70p8XcuXOLrbbaqvjNb37T5zLD5Zw0XPTnnFOv1c2DNa1rKO7be++9i2uuuabo7u4uiqIovvzlLxevetWriqIoire97W3Fxz72saIoiuLXv/51MX78+N7jcajuW/HcduWVVxa77757KbZbz30PPPBA8cpXvrJ4xSteUXz3u98tzXZbunTpas85Zdh273vf+4rTTz+9d9499thjpaltRf/6r/9aHH300UVRlGe/Ui6DkRdrYyiP+7VRlkxsZO1rep1XhtoXLVpUmrxvVN2vetWrerP3hZpdd1EUxTPPPNP73818DUM5DOU+qtJxU5bXq/2x4uvDZm/PsuTpi23bvupc0zwtiuZs27Jk/EC25wutOE+LovlztS+aGi/wxBNPFBtssEHR2dlZFEVRdHd3F5tvvnlx7733rrTc5z73ueLUU0/t/fmaa64pDjjggCGtdW3VO9YXeve739076aqgP+O86667ioMOOqiYPXt2JZsa9Y71v//7v4u/+7u/a0aJDVHvOL/3ve8Ve+yxRzF//vyiu7u7+Kd/+qfi/e9/fzNKbog1Bc5wOCcNFwM9t9ZrxXmwpnUN9X09brnllmKrrbYqiqIo1ltvvd5fNhdFUey7777FzJkzm3JfURTF9OnTiz322KM02+2Pf/xj8epXv7q49dZbV3qRWJbt1tc5pwzbbuzYscV6661XPPfcc6Wr7YXHw4477li6/Up5DHZeDMRQHfeDUW+zjvNG1N7Xzz3KWHtRNDfvG1X3mn5BU7a6m/UahnJo9j4q83FThter/bXi68OybM+yX2P2VecLrThPi6K527aZGd+o7bniPC2K8szVFfn4qReYO3duxo0bl/b29iRJrVbLpEmTMmfOnJWWmzNnTrbaaqven7feeutVlim7ese6oscffzyXX355jj766KEqc63VO87Ozs6ccsopueCCCzJixIhmlLrW6h3r3XffnVGjRuXoo4/OnnvumRNPPDFPPvlkM0oekHrHecwxx+SQQw7JFltskXHjxuXHP/5x/uVf/qUZJQ+64XBOGi4Gcm4djHUN9X09vvjFL+a1r31tnnrqqXR2dmaLLbbova9nXg71fSeeeGImTpyYs88+O1//+tdLs92+8IUv5IADDsjLXvay3prLtN2S5MQTT8xuu+2Wt7/97XnyySdLse0222yzrL/++vn0pz+dffbZJwcddFB+/OMfl6K2FY+HX/ziF3nmmWdy9NFHl26/Ug5DmRf9MRTH/WBoVu410gu3/WCNqxGalfeNqrvHhz/84ey2225585vfnPvvvz/J4GTxQDX7NQzl0Ox9VPbjptmvV/tjxdeHZd2eZXtNXa8XztOkXNt2qDK+Eduzr3latu2Z+E4N+mH+/Pk55phj8sEPfjD77LNPs8tpuHPPPTevf/3rs9NOOzW7lEHX1dWVH/3oR7ngggvym9/8JuPHj8873/nOZpfVcLfeemvuuuuuPPLII3n00Ufz6le/Oqeddlqzy4Jh69Of/nRmz56d8847r9mlrOSSSy7J3Llz88lPfjIf+tCHml1OkmThwoW58cYb88///M/NLmW1brzxxvz2t7/N7bffnk033TQnnXRSs0tKsvy7r5544onsvPPOufXWW/OlL30pb37zm9PV1dXs0lZy0UUX5cQTT+y9oIAqKOtx3wqqtO3Lmvcv5oV1f/3rX88f/vCH/Pa3v81BBx1Uyj/cK+NrGFpL2Y+bKp07k1VfH5Zte1ZVX7lUpm1b9XmalGt79tDUeIGJEyfmscce670wLooic+bMyaRJk1ZabtKkSXnooYd6f37wwQdXWabs6h1rkixYsCBHHHFEXvva1+aMM84Y6lLXSr3j/OlPf5ovf/nL2XrrrXPggQdm/vz52XrrrSv1Dob+zN8pU6Zk/PjxqdVqOeGEE/LLX/6yGSUPSL3jvOSSS3q/9L2trS0nnXRSbrjhhmaUPOiGwzlpuOjPuXUw1zXU933+85/PlVdemeuuuy6jR4/OJptskvb29jz++OO99fbMy6G+r0fPOWDChAml2G5/+tOfsv3222frrbfOL3/5y7zjHe/Id77zndJst55t19HRkfe973352c9+Voo59+STT6atrS1///d/nyTZa6+9ss022+Shhx5qem099z3//PP5zne+k3/4h39IklIeDzTfUOZFvYbquB8MQ32cN1pf236wxrU2mp33jao7Wb5tk+V/xXr66afn/vvvz1NPPVWquns06zUM5dCsfVSF46YMr1fr9cLXh2Xcnj01leU1dT36mqdl27ZDmfFruz37mqdl25696v6gqhbyqle9aqUvVHnZy162yjL33XffKl/K++Uvf3mIK1179Yx1wYIFxf7771+ce+65Q1xd49QzzhU98MADlfxOjaKob6wPPfRQseOOO/Z+HvnnPve54qijjhrKMtdaPeM8//zzi1e/+tXFkiVLiqIois985jPF4YcfPpRlNtSaPu9wuJyThov+nnP644XzYE3rGqr7zj///GLvvfcunn766ZVqPemkk1b64q8tt9yy94u/huK+LbbYonjwwQd76/nud79bjB8/vuju7i7FdlvRip9R2uzttuWWWxbPPPPMSl9Qev755xcHHXRQU7ZPX/dNnTq1uOaaa4qiKIr777+/2GSTTYqHH364FLUVRVFceOGFq3yvURn2qy8KL5/BzIv+ev7554f0uG+EZmdio2pf07YvU+1lyftG1N3Z2Vk8/vjjvT9ffvnlxaRJkwZ1TP3xzDPPFI888kjvz818DUM5DPU+qsJxM9S5tbb74IWvD8u0PZudp/Vu2xfWubpcava2bXbGD3R7FkXf1zHN3p6ro6nRhz/84Q/FK17ximL77bcvXvaylxW//e1vi6Ioire//e3FVVdd1bvcV7/61WLbbbcttt122+If/uEfKnmhWM9YP/nJTxbt7e3FHnvs0fu/T37yk80su9/q3ac9qtzUqHesl1xySbHLLrsUu+22W3HEEUcUc+bMaVbJA1LPOBcvXlycfPLJxY477ljstttuxdSpU4v77ruvmWUPyDve8Y5i/PjxxYgRI4qxY8cWL33pS4uiGJ7npOFidfNzbaxuHqxpXUNx34wZM4okxbbbbtubEfvtt19RFEXx+OOPF1OnTi222267Yueddy6uv/763ucZivu++c1vFvvuu2+x6667Frvvvnvx6le/uvdFW7O32wvnxIpNjWZvt+uvv7647777ij333LPYbbfdil133bU49thjiwceeKA02+6+++4rDjnkkN59e/nll5emtqIoile+8pXFxRdfvNI+LsN+pXwGIy8GaqiP+7VRlkxsVO1r2vZlqX3u3LmlyftG1P38888XL3vZy3pz5NBDDy3uuOOO0tT94IMPluY1DOUwlPuoKsdNmV6v1uOFrw/LsD3Lkqcvtm37qnNNudSsbVuWjB/I9uzR13VMGeZqX2pFURT1v68DAAAAAACgOXynBgAAAAAAUAmaGgAAAAAAQCVoagAAAAAAAJWgqQEAAAAAAFSCpgYAAAAAAFAJmhoAAAAAAEAlaGoADLIbb7wxxxxzTLbccsvUarV873vf6/dzFEWRz3/+85k8eXJGjRqV8ePH51Of+lTjiwUAAACAEtPUoGUdf/zxqdVq+da3vrXG5ebPn5/Ro0dno402yqJFi/KNb3wjr3vd6/LSl740G2ywQdZff/3ssssuef/7359HHnlktc/zjW98I/vtt1/WW2+9vOQlL8nRRx+d22+/fZXlvva1r6VWq63xf69+9avXevwMnT//+c/ZY4898p//+Z8Dfo73vve9ufDCC/P5z38+f/jDH3L11Vdnv/32a2CVwJqUNTOS5U3PK6+8MlOmTMm4ceMyevTo7LDDDjn11FNz//33r9W4AeifMudFd3d3/uM//iN77713Ro8enTFjxuTggw/O1VdfvVZjBqD/hiovFi5cmPPPPz/HH398dtxxx7S1taVWq+XBBx9c43rvueeevOlNb8qmm26addddN3vssUf+67/+K0VRrM2woWFqhdlIi/rxj3+cww47LIcddlhmzpy52uUuuOCCnHbaaTnttNPyX//1XznmmGNy77335mUve1nGjRuXoihyxx135IYbbsiGG26Ym266KbvssstKz/GpT30q//zP/5ytttoqxx13XBYsWJBvf/vbWbp0aX784x/ngAMO6F32jjvuWO1f8l9++eWZNWtWPvvZz+aDH/xgQ7YDQ6tWq+W73/1u/vZv/7b3tiVLluSjH/1ovvWtb+XZZ5/Nrrvums9+9rM55JBDkiS///3vs/vuu+euu+7KDjvs0JzCocWVNTOS5AMf+EC+8IUvZNy4cXnta1+bMWPG5M4778yMGTOy/vrr5xe/+EV23XXXQdkuAKysrHlRFEXe+MY35oorrshLX/rSHHnkkVmyZEmuuuqqzJs3L1/+8pdz+umnD9p2AWBlQ5UXDz74YLbZZpskyVZbbZUFCxbk6aefzgMPPJCtt966z3Xefffd2X///bNo0aK86U1vypZbbplrrrkms2bNyumnn54vf/nLDd0WMCAFtKju7u5im222Kdra2oqHHnpotcvtt99+RZLilltuKYqiKBYtWtTnchdeeGGRpHjDG96w0u333HNP0d7eXkyePLl49tlne2//zW9+U4waNarYaaedimXLlr1ovUuWLCk22WSTor29vXj88cfrGSIllKT47ne/u9JtJ598crH//vsXN954YzF79uziX//1X4tRo0YV99xzT1EURfHZz362mDx5cvH5z3++2HrrrYutttqqePvb31489dRTTRgBtKayZsZjjz1WtLW1FVtttdVKyxdFUXzhC18okhRve9vb+j1eAAamrHlx2WWXFUmKAw44oFi4cGHv7U8++WSx1VZbFaNGjSoeeOCBgQwZgAEYqrxYsGBBMWPGjN7fH7zmNa8pkqzxnH/wwQcXSYprr72297YlS5YUBx10UJGk+MUvflHvMGHQ+PgpWlatVsvb3va2dHd3Z/r06X0uM2vWrPz617/O7rvvnn322SdJss466/S57Bvf+MYkyezZs1e6ffr06enq6spHP/rRbLjhhr2377nnnvm7v/u7/P73v89NN930ovV+73vfy1NPPZWjjz46m2++eV1jpPzmzJmT6dOn57LLLstBBx2Ul770pTnzzDNz4IEH9s7L+++/Pw899FAuu+yyXHLJJfna176W2267LW94wxuaXD20jrJmxoMPPpju7u4ccMABKy2fJEcffXSS5Mknn+znaAEYqLLmxVVXXZUkOeuss7Luuuv23r7pppvm/e9/f5YsWbLaegFovKHKi/XXXz9Tp07NxhtvXFdd99xzT2688cZMmTIlRx55ZO/tI0eOzCc+8YkkyX//93/X9VwwmDQ1aGnTpk1LW1tbvva1r/X5uYA9wfL2t7/9RZ/rmmuuSZJVPuLjJz/5SZLk8MMPX+Uxr3nNa5IkP/3pT1/0+S+88MIkycknn/yiy1Idv/vd77Js2bJMnjw566+/fu//fvrTn+a+++5Lsvzzj5csWZJLLrkkBx10UA455JBcdNFFueGGG/LHP/6xySOA1lHGzNh+++0zcuTI/PznP8/8+fNXWv773/9+kvgeJoAhVsa8ePzxx5Ok9yNIVtRz2/XXX/+i9QDQOEORF/21pnw58MADs95669X1OywYbO3NLgCaaeLEiTn88MPzgx/8INdff/1Kv/jp6urKpZdemlGjRuWEE05Y5bHf+c53cvfdd2fhwoWZNWtWfvjDH2abbbbJv/zLv6y03L333pv1118/W2yxxSrPsf322/cusyYPPfRQfvzjH2fChAk54ogjBjJUSur555/PiBEjctttt2XEiBEr3bf++usnScaNG5f29vZMnjy5976ddtopyfJ3evieDRgaZcyMTTbZJJ/5zGfygQ98IDvuuONK36lx/fXX513vepfPSAcYYmXMi0033TRJ8sADD/S+juzxwAMPJFn+17kADJ2hyIv+6smOnixZ0YgRI7LNNtvk7rvvTldXV9rb/VqZ5jH7aHlvf/vb84Mf/CAXX3zxSgHy/e9/P0888UTe9KY39fk2ve985zu54ooren/eZ5998u1vf3uVv3567rnnMnbs2D7XPWbMmN5l1mT69Onp7u7OtGnTVvnFN9W21157ZdmyZZk3b14OOuigPpc54IAD0tXVlfvuuy8vfelLk/z1onOrrbYaslqBcmbG+9///owfPz4nn3xyvvKVr/TefuCBB+b44493sQHQBGXLiyOPPDLf/va385nPfCaHHnpo78eXPPXUU/n3f//3JMmzzz47oLECMHCDnRf91ZMdL/xo2x5jxoxJd3d3FixYkJe85CVrtS5YGz5+ipb32te+Nptttlm++93vrvTC/+KLL06y+rf5XX755SmKIs8880yuv/76dHR05GUve1nD37bd8/mKtVot//AP/9DQ52ZoPP/887njjjtyxx13JFn+13B33HFH5syZk8mTJ+fv//7vc+KJJ+bKK6/MAw88kF//+tc577zzet8+ethhh2XvvffOP/zDP+Q3v/lNbrvttpx66qmZOnXqSu/eAAZfGTPjX/7lX3LCCSfkrLPOyty5c7NgwYL87Gc/y+LFi3PIIYfk6quvXut1ANA/ZcuL448/PlOmTMnPfvaz7LbbbvnHf/zHnHbaadlll116myBtbX49ADDUypYXUBVetdDyOjo68ta3vjWLFi3KN7/5zSTLP3P2uuuuy6RJk3LYYYet8fEbbbRRpkyZkh/84AdZd911c+KJJ6azs7P3/g033HC178To+fzz1XXAk+RHP/pR5syZk0MPPXStO+40x6233pq99tore+21V5LkjDPOyF577ZVzzjknyfJ34px44on5wAc+kB122CF/+7d/m1tuuSWTJk1KsvwC8//+7/+y6aab5uCDD87f/M3fZKeddsq3v/3tpo0JWlXZMuNHP/pRPvaxj+X000/Phz/84UyYMCHrr79+DjzwwPzf//1fOjo68oEPfGBthw1AP5UtL9rb23Pdddfl4x//eNra2vLVr341V155ZV772tfm8ssvT5LVvvMDgMEz2HnRXz3ZsaaMqdVq2WCDDQa8DmgETQ3IXzvfF110UZLk61//erq6uvK2t72t7r9YGjNmTF7xilfkkUceyezZs3tv33777fP888/3fjnfitb0WYU9fEF49R1yyCEpimKV/33ta19LsvxFzLnnnpsHHnggS5cuzaOPPporr7wyu+22W+9zbLnllrniiiuyYMGCPP7445k+fXqfb0EFBl+ZMuO6665LkkyZMmWV5bfYYovsuOOOmT17dp5//vk6RwdAo5QpL5Jk1KhR+djHPpY//vGPWbJkSebNm5cLLrggjzzySJLlH10CwNAbzLzorzV99+uyZcvywAMPZJtttvERtzSdpgYk2XnnnfOKV7wit912W37729/2ftzT2972tn49z6OPPppk+S+pe7zqVa9KksyYMWOV5X/4wx+utMwLPfXUU7nqqquy8cYb53Wve12/agFgcJQpM5YuXZokefLJJ/tcx5NPPpm2traV1gHA0ChTXqzJN77xjSTJW97yln7VBUBjDGZe9Nea8uWmm27Kn//857rzBQaTpgb8RU9n/F3veld+//vf57DDDlvlS5gXLFiQP/7xj30+/uKLL86vf/3rbL/99tluu+16b3/b296W9vb2fOpTn1rp7Xt33HFHvvWtb2WnnXbKgQce2Odzfv3rX8/SpUtzwgknZNSoUWs7RAAapCyZccABByRJvvCFL6zyFvGvfOUrefjhh/PKV75ShgA0SVnyIvnrx1Kt6PLLL8/FF1+cfffdN69//esHPE4A1s5g5UV/7bDDDjn44INzww039L4rPFn+x1Rnn312Ep8kQjnUiqIoml0ElMGCBQsybty4/PnPf06SfPvb386b3/zmlZZ58MEHs+2222afffbJjjvumPHjx+eZZ57JLbfckttvvz1jxozJD37wg7zyla9c6XGf+tSn8s///M/Zaqutctxxx2XBggX59re/naVLl+bHP/5x7y+lXmi33XbLXXfdld/+9rcrfRQRAM1VlsxYtmxZDj300Nx4440ZO3Zsjj322Gy00Ua5/fbbc/3112fdddfNT37yk+y3336Dv1EAWEVZ8iJJdtppp0ycODE77bRT1llnnfz617/OT37yk2y77ba5/vrrV/nlGQBDZzDz4swzz8yf/vSnJMnMmTPz6KOP5rjjjsv666+fZHmTYsVG+KxZs3LAAQdk0aJFefOb35xx48blmmuuyaxZs3L66afny1/+8mBuCqhPAfR629veViQpNt5442Lx4sWr3P/8888X55xzTnHwwQcXW2yxRdHR0VGst956xS677FK8//3vL+bOnbva57700kuLffbZp1h33XWLDTfcsDjqqKOK2267bbXL/+pXvyqSFPvtt19DxgZAY5UlMxYvXlycd955xV577VWMHj26aG9vL8aPH1+ccMIJxd13392w8QIwMGXJi4997GPFbrvtVmywwQbFOuusU+y0007FP//zPxfPPfdcw8YKwMANVl5stdVWRZLV/m/69OmrPOYPf/hD8YY3vKHYeOONi1GjRhW77bZb8Z//+Z9Fd3d3o4cNA+KdGgAAAAAAQCX4Tg0AAAAAAKASNDUAAAAAAIBK0NQAAAAAAAAqQVMDAAAAAACoBE0NAAAAAACgEjQ1AAAAAACAStDUAAAAAAAAKkFTAwAAAAAAqIT2ZhdA8y1btiydnZ3NLgP6raOjIyNGjGh2GdAyuru7s3Tp0maXAf0mL2DoucagiuQFDD15QVWNHDkybW3eL9AsmhotrCiKPP7443n22WebXQoM2EYbbZQtttgitVqt2aXAsLZ06dI88MAD6e7ubnYpMCDyAoaGawyqTl7A0JAXVF1bW1u22WabjBw5stmltCRNjRbWEx5jx47N6NGjvWijUoqiyMKFCzNv3rwkybhx45pcEQxfRVHksccey4gRIzJx4kR/jUKlyAsYWq4xqCp5AUNLXlBl3d3defTRR/PYY49l0qRJ5m8TaGq0qGXLlvWGxyabbNLscmBA1l133STJvHnzMnbsWG8Vh0HS1dWVhQsXZsstt8zo0aObXQ70m7yAoeEag6qTFzA05AXDwWabbZZHH300XV1d6ejoaHY5LcefWraons8r9Mspqq5nDvsMThg8y5YtSxJvq6XS5AUMPtcYDAfyAgafvGA46Lk+7rleZmhparQ4b4+i6sxhGDqON6rM/IWh43ijysxfGDqON6rM/G0uTQ0AAAAAAKASfKcGa2Vx57Jc+7vHMmPWE3l24dJsNHpkDt9l8xy127is01Hdzx+dNm1ann322Xzve99rdinDyte+9rW8733vy7PPPtvsUoAhNlzzIpEZg0Fe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Hnnkkdx555154IEHBv2286OOOmpNbwaAitMXANRLZwBQD30BMDo1PNRYtGhR/uEf/iEXXnhh+vr6VrlNURSp1WoKBGAU0xcA1EtnAFAPfQEwujU81Hj/+9+f8847LzvvvHPe8pa3ZOLEiensLN2nWQHQZvoCgHrpDADqoS8ARreGX/Evu+yy7L777rnhhhsyZsyYZmYCYATRFwDUS2cAUA99ATC6dTR6waVLl2a//fZTHgCslr4AoF46A4B66AuA0a3hocYee+yRu+++u5lZABiB9AUA9dIZANRDXwCMbg0PNf7t3/4tV199db773e82Mw8AI4y+AKBeOgOAeugLgNGt4e/UeMUrXpGrr746hx56aHbbbbfMmDEjEyZMWGm7Wq2WU045ZY1CAlBd+gKAeukMAOqhLwBGt4aHGo8++mhOOumkPP744/nRj36UH/3oR6vcToEAjG76AoB66QwA6qEvAEa3hoca//AP/5Drr78+Bx98cP72b/82EydOTGdnw1cHwAilLwCol84AoB76AmB0a/gV//vf/372228/n18IwGrpCwDqpTMAqIe+ABjdGv6i8KIosvvuuzczCwAjkL4AoF46A4B66AuA0a3hocbee++d2267rZlZABiB9AUA9dIZANRDXwCMbg0PNT7/+c/nxhtvzH//9383Mw8AI4y+AKBeOgOAeugLgNGt4e/U+OxnP5udd945H/jAB/Jf//Vf2XnnnTNhwoSVtqvVajn33HPXKCQA1aUvAKiXzgCgHvoCYHRreKhx/vnnD/z33LlzM3fu3FVup0AARjd9AUC9dAYA9dAXAKNbw0ONe++9t5k5ABih9AUA9dIZANRDXwCMbg0PNbbYYotm5gBghNIXANRLZwBQD30BMLo1/EXhAAAAAAAAw6nhd2pccMEFdW971FFHNXozAFScvgCgXjoDgHroC4DRreGhxqxZs1Kr1Va7TVEUqdVqCgRgFNMXANRLZwBQD30BMLo1PNSYPXv2Kk9/8sknc8stt+Siiy7KoYcemkMOOaThcABUn74AoF46A4B66AuA0a3hocbRRx+92vNPOOGEHHDAAXnPe97T6E0AMALoCwDqpTMAqIe+ABjdWvZF4a94xSty6KGH5tRTT23VTQAwAugLAOqlMwCoh74AGNlaNtRIki222CK33XZbK28CgBFAXwBQL50BQD30BcDI1bKhRlEUue6667L22mu36iYAGAH0BQD10hkA1ENfAIxsDX+nxnXXXbfK0/v6+vKnP/0pF1xwQW688cYcddRRDYcDoPr0BQD10hkA1ENfAIxuDQ819ttvv9RqtUHPL4oie++9d/793/+90ZsAYATQFwDUS2cAUA99ATC6NTzUOPXUU1dZIB0dHVl//fWzxx575OUvf/kahQOg+vQFAPXSGQDUQ18AjG4NDzU+8YlPNDEGACOVvgCgXjoDgHroC4DRrWVfFA4AAAAAANBMDQ81fvOb3+S8885LT0/PwGmLFi3Ke97znkyaNCnbbLNNvvSlLzUlJADVpS8AqJfOAKAe+gJgdGt4qHH66afnlFNOybrrrjtw2sknn5yzzjorTz31VObPn5/3vve9mTNnTlOCAlBN+gKAeukMAOqhLwBGt4aHGr/85S+z//77D3wxU19fX2bPnp2XvexlWbBgQe69995svPHG+cIXvtC0sABUj74AoF46A4B66AuA0a3hocYjjzySKVOmDPx84403pqenJ+9+97uz1lprZfPNN88b3vCG3HbbbU0JCkA16QsA6qUzAKiHvgAY3RoeanR2dmbx4sUDP//4xz9OrVbL/vvvP3DahhtumD//+c9rlhCAStMXANRLZwBQD30BMLo1PNSYNm1arr322oGfL7nkkmy55ZbZYostBk7705/+lA033HDNEgJQafoCgHrpDADqoS8ARreGhxpHHnlkbrvttrz85S/PK1/5ytx22205/PDDV9jm17/+dbbddts1DglAdekLAOqlMwCoh74AGN0aHmq8733vy1vf+tbcdNNNuf7663PQQQfl5JNPHjj/jjvuyG233ZYDDjigKUEBqCZ9AUC9dAYA9dAXAKNbZ6MX7O7uzte//vX09PSkVqtl3XXXXeH8TTfdNL/61a8ybdq0Nc0IQIXpCwDqpTMAqIe+ABjdGh5qLDdhwoRVnr7RRhtlo402WtOrB2CE0BcA1EtnAFAPfQEwOq3xUCNJ+vv78/DDD6e3t3eV50+dOrUZNwNAxekLAOqlMwCoh74AGH3WaKjxla98JZ///Odz5513ZunSpavcplarpa+vb01uBoCK0xcA1EtnAFAPfQEwejU81Pj85z+fj3zkI+nq6sorX/nKTJw4MZ2dTXnjBwAjiL4AoF46A4B66AuA0a3hV/wvfvGLmTRpUn7+859n8uTJzcwEwAiiLwCol84AoB76AmB062j0go888kgOO+ww5QHAaukLAOqlMwCoh74AGN0aHmpMnz49jz/+eDOzADAC6QsA6qUzAKiHvgAY3Roeanzwgx/Mt771rdx///3NzAPACKMvAKiXzgCgHvoCYHRr+Ds1jj766CxYsCB77bVX/v7v/z4zZszIhAkTVrntK1/5yoYDAlBt+gKAeukMAOqhLwBGt4aHGknS09OTJ598Mqeeeupqt1u6dOma3AwAFacvAKiXzgCgHvoCYPRqeKhx6qmn5lOf+lQ23njj/O3f/m0mTpyYzs41mpEAMALpCwDqpTMAqIe+ABjdGn7FP++88zJ9+vTceOONGT9+fDMzATCC6AsA6qUzAKiHvgAY3Rr+ovDHH388f/M3f6M8AFgtfQFAvXQGAPXQFwCjW8NDjZ122ikPPvhgM7MAMALpCwDqpTMAqIe+ABjdGh5qfOxjH8sVV1yRW265pZl5ABhh9AUA9dIZANRDXwCMbg1/p8bjjz+emTNnZq+99sqRRx6ZGTNmZMKECavc9qijjmo4IADVpi8AqJfOAKAe+gJgdGt4qDFr1qzUarUURZFzzz03SVKr1VbYpiiK1Go1BQIwiukLAOqlMwCoh74AGN0aHmrMnj27mTkAGKH0BQD10hkA1ENfAIxuDQ81jj766GbmAGCE0hcA1EtnAFAPfQEwujX8ReEAAAAAAADDqeF3asybN6/ubadOndrozQBQcfoCgHrpDADqoS8ARreGhxrTpk1b6UuYVqVWq6Wvr6/RmwGg4vQFAPXSGQDUQ18AjG4NDzWOOuqoVRbIk08+mdtuuy333ntvXvWqV2XatGlrkg+AitMXANRLZwBQD30BMLo1PNQ4//zzBz2vKIqceeaZ+exnP5tzzz230ZsAYATQFwDUS2cAUA99ATC6teSLwmu1Wj70oQ/lJS95Sf75n/+5FTcBwAigLwCol84AoB76AmDka8lQY7ndd98911xzTStvAoARQF8AUC+dAUA99AXAyNXSocY999zjC5kAeEH6AoB66QwA6qEvAEauhr9TYzD9/f3505/+lPPPPz/f+ta38upXv7rZNwHACKAvAKiXzgCgHvoCYHRoeKjR0dGRWq026PlFUWT99dfPmWee2ehNADAC6AsA6qUzAKiHvgAY3Roearzyla9cZYF0dHRk/fXXzx577JF3vvOd2WSTTdYoIADVpi8AqJfOAKAe+gJgdGt4qPHjH/+4iTEAGKn0BQD10hkA1ENfAIxuQ/6i8E9+8pM5+eST09vbO+g2S5Ysycc+9rF8+tOfXqNwAFSXvgCgXjoDgHroCwCSIQ41fvjDH+bUU0/NhhtumK6urkG3Gzt2bDbccMN87GMfy7XXXrvGIQGoFn0BQL10BgD10BcALDekocYFF1yQ9ddfP+973/tecNv3vve92WCDDTJ79uyGwwFQTfoCgHrpDADqoS8AWG5IQ42f//znec1rXpPu7u4X3La7uzuvec1r8rOf/azhcABUk74AoF46A4B66AsAlhvSUOOBBx7IVlttVff2W265ZR588MEhhwKg2vQFAPXSGQDUQ18AsNyQhhodHR2r/TKm5+vt7U1Hx5C/ixyAitMXANRLZwBQD30BwHJDenXffPPNc/vtt9e9/e23355JkyYNORQA1aYvAKiXzgCgHvoCgOWGNNTYd999c8011+S+++57wW3vu+++XHPNNXnlK185pEB333139tprr0yfPj177LFH7rjjjkG3LYoiBxxwQNZbb70h3QYArTUcfZHoDICRwDEGAPXQFwAsN6Shxnvf+9709vbmLW95S/785z8Put2jjz6at771renr68t73vOeIQU64YQTcvzxx+euu+7KRz7ykcyaNWvQbf/jP/4jW2+99ZCuH4DWG46+SHQGwEjgGAOAeugLAJYb0lBjt912yz/+4z/mlltuyQ477JBTTz011157be6+++7cfffd+fGPf5xTTjklO+ywQ26++eZ88IMfzG677Vb39S9YsCA33XRTjjjiiCTJYYcdlvnz52fu3LkrbXvHHXfkiiuuyEc/+tGh7AIAw6DVfZHoDICRwjEGAPXQFwAs1znUC5x55plZa6218rnPfS6f/OQn88lPfnKF84uiyJgxY3LSSSfl9NNPH9J1z58/PxMnTkxn57JYtVotU6dOzbx587LNNtsMbNfb25vjjjsu5557bsaMGfOC17t48eIsXrx44Oeenp6B6xnKl0y9kGZeV6stz1qlzIOxL+VkX4ZPWXO1si+S1nTGaOuLsq/t5eRsLjmbq2o5y8oxxuDa+diVeX3L1hjZGjMas5VxXxN9sTplfcyGqszPt2azryPPaNnPpP37OuShRq1Wy6c+9akcc8wxmT17dn7+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l1xySbH77ru3N9DzLFq0qLjyyiuL/v7+oiiK4otf/GLxqle9qiiKonjnO99ZfPzjHy+Koih++ctfFpMmTSqWLFmyRucNh3vvvbd4xSteUey5557FN7/5zcruyz/+4z8W73vf+wYemwcffLAoitWvqUbPa6X+/v5i/fXXL2677baiKJY9Pt3d3UVPT08lHpef/OQnxfz584stttii+NWvfjVweiseh7K/XtB6w7kGVvf6/6pXvWrg9fP52vG8ff7zb7kyPw8/97nPFa9//euLomjv/VmW17AXul9XlXN1a7Qo2nO/DnZ/DrZGW3WfNXJ/Pt9z12hRlO95z+q1oi/K/Hox3McsQz1vwYIFA/kvv/zyYueddy7NfTdcx0aNnFeWfl/VecN5LLYmr/fPfS0vy+NK+9TTDX/4wx+KiRMnFg8++GDR399fHHLIIcV///d/D3PSNVPPft5yyy3FPffcUxTFsr9T7r333gOXqZKh9P2ZZ55ZHHvsscWLXvSi4QnXZPXs6zPPPFNsueWWxU9/+tOiKIqir69vhQ6ugnr285vf/Gbxspe9bOA19d/+7d+Kt771rcMZc43VczzSrtcjQ406PPzww8W6665b9Pb2FkWx7B93N9100+Luu+9uc7LB3XjjjcUWW2xRFEVRrLPOOgN/eSuKothjjz2KOXPmrNF5rbZ06dLi1a9+dXHTTTetcHBetX15+umni3XXXbd48sknVzh9dWuq0fNarb+/v9hggw2Kn/zkJ0VRFMVtt91WbL755sXixYsr9bg894W4FY9DFV8vaK52r4Hnvv6v7h832/G8XdVfhMr+PHzxi188cB+W4f5s52vYUO7X1f2l97lrtCjae7/WO9Qo8/353DVaFOVYp9Sn1X1RhdeLVh+zrMm6nj17djFjxoxS3HebbLJJsddeew3LsVEj55Wh3we739ZZZ51hORZb0+fDc1/Ly/K40h71vn5+9rOfLU444YSBn6+88spi7733Htasa6LRDnzve987MISriqHs6+23317su+++xdy5cys51Kh3X//3f/+3+Lu/+7t2RGyKevfziiuuKGbMmFH09PQU/f39xT//8z8XH/zgB9sReY2t7nikXa9HPn6qDvPnz8/EiRPT2dmZJKnVapk6dWrmzZvX5mSD+8IXvpA3vOENefTRR9Pb25vNNtts4Lxp06Zl3rx5DZ83HP793/89e++9d1760pcOnFbFfbnnnnuywQYb5FOf+lR233337LvvvvnRj3602jXV6HmtVqvV8vWvfz1vfvObs8UWW2SfffbJl7/85Tz11FOVe1yWa8XjUMXXC5qr3Wtg+ev/ch/96Eez00475e1vf3v+8Ic/JGnv6+lRRx2VnXbaKcccc0weeeSRUj8Pf/7zn+fxxx/P61//+lLen8N93zXrfn3+Gi3b/fr8NZqUty9WtUbLdn8yuOHsi7K+XrTymKXR84466qhMmTIlp5xySi688MJS3Hdjx47N1ltv3fJjozV5LWh3v6/qvI033jjjx48flmOxNXk+PPe1vGyPK8Ov3tfPefPmZYstthj4uWqPWyMd+NBDD+XSSy9d6e89ZVfvvvb29ua4447LWWedlTFjxrQj6hqrd1/vvPPOdHd35/Wvf3122WWXHHXUUQN/766CevfzkEMOyX777ZfNNtssEydOzI9+9KP867/+azsit1S7Xo8MNUagT33qU5k7d27OOOOMdkdpyO23357LLrss//Iv/9LuKGusr68v999/f3bYYYfcdNNN+a//+q+8/e1vT19fX7ujDVlfX19OP/30XH755bn//vvzox/9KEceeWQl9wVGque//l944YX53e9+l1//+tfZd999234AcN111+XXv/51brnllmy00UY5+uij25rnhZx77rk56qijBv6yWrb7s4pW9XeUMt2vVV+jSbnuT1idsh6zXHDBBZk/f35OP/30fOQjH2l3nNx+++15/PHHB74LoozK+tpZFEUefvjh0h+Lreq1HFhRT09PDjnkkHz4wx/O7rvv3u44LXHaaaflzW9+c7bffvt2R2m5vr6+/PCHP8xZZ52VX/3qV5k0aVLe8573tDtW09100025/fbb86c//SkPPPBAXv3qV+fd7353u2ONGIYadZgyZUoefPDBgb/8FEWRefPmZerUqW1OtrLPf/7zufzyy/O9730v48aNy4YbbpjOzs489NBDA9vcd999mTp1asPntdpPf/rT3Hfffdl2220zbdq0/OIXv8jxxx+fb3zjG5Xbl6lTp6ajoyPveMc7kiS77rprttxyy9x///2DrqnVrbd2rsVbb701DzzwQF75ylcmSfbYY49Mnjw5v/71ryv3uCzX6H1d1seIcmjXGnj+6//yLMmy3xx53/velz/84Q959NFH29YNy7fr6urKP/7jP+anP/1paZ+HTz/9dL7xjW/kXe9618BpZbs/h/u+W9P7dVVrtGz366rWaDvu63qsao2W7f5k9YazL8r2ejEcxyxruq6PPvroXHvttZk8eXJb77vrrrsuixYtyrve9a6WHxs1el4Z+n1V5z3yyCPDdizW6HnPfy0v43OB4VVvN0ydOjX333//wM9Ve9yG0oFPPfVUXve61+UNb3hDTjzxxOGOusbq3def/OQn+eIXv5hp06Zln332SU9PT6ZNm1apdzAMZf3uv//+mTRpUmq1Wo444oj84he/aEfkhtS7nxdccMHAl753dHQM/N1ipGnb61HzP9FqZHrVq161whfAvPSlL21voFU488wzi91226147LHHVjj96KOPXuGLvzbffPOBL6lp9Lzh9NzPja3ivsycObO48sori6JY9uU5G264YfHHP/5xtWuq0fNa6aGHHirGjx9f3HnnnUVRFMXdd99drL/++sX9999fqcfl+Z8D2IrHoQqvF7TWcK+BVb3+9/b2Fg899NDAz5deemkxderUgZ+H+3n79NNPF48//vgKmffdd9+iKMr5PDznnHNW+BzQstyf7X4Nq/d+fX7Owf6O0u779bk5V7dG1+R+acX9WRQrr9GiaP/9ydC1si/K+noxnMcsQzlvs802K+67776BPN/85jeLSZMmFf39/aW575af18pjo6Ge9/jjj5em31d13nAeizVy3qpey8vwuHqNb696uuGee+5Z6Yt5v/jFLw5z0jVTz34+9dRTxV577VWcdtppw5yuuYba9/fee28lv1OjKOrb1/vvv7948YtfPPCdR5/97GeLgw8+eDhjrrF69vPMM88sXv3qVxeLFy8uiqIoPv3pTxcHHnjgcMZsmtV9p0a7Xo8MNer0u9/9rthzzz2LbbfdtnjpS19a/PrXv253pBXMnz+/SFJstdVWxYwZM4oZM2YUL3vZy4qiWPaP0TNnziy22WabYocddiiuueaagcs1et5weu5f3Ku4L/fcc0+x3377FTvuuGOx8847F5deemlRFKtfU42e12oXXXTRwH7suOOOxVe/+tWiKKrxuBx//PHFpEmTijFjxhSbbLJJsfXWWxdF0ZrHoeyvF7TecK6BwV7/n3766eKlL33pwHP2gAMOKG699daByw338/aee+4pdtlll2KnnXYqdtxxx+LQQw8t7r333qIoyvk8fMUrXlGcd955Az+3+/4sy2vYC92vq8q5ur+jtOt+XVXO1a3RMt2fyz1/jbbz/qRxreiLMr9eDPcxy1DOu+iii4o99thj4Pnz6le/euDgvQz33XKtPjYa6nll6vdVnTecx2KNnLeq1/IyPK6012Dr5Zhjjim+9a1vDWx39tlnF1tttVWx1VZbFe9617sqN4yqZz9PP/30orOzc6AzZsyYUZx++untjN2Qeh/T5ao81Kh3Xy+44ILiJS95SbHTTjsVr3vd64p58+a1K3JD6tnPZ599tjj22GOLF7/4xcVOO+1UzJw5s7jnnnvaGXvIBvt7ZRlej2pFURStfz8IAAAAAADAmvGdGgAAAAAAQCUYagAAAAAAAJVgqAEAAAAAAFSCoQYAAAAAAFAJhhoAAAAAAEAlGGoAAAAAAACVYKgBAAAAAAAjzHXXXZdDDjkkm2++eWq1Wq644oohX0dRFPn85z+f6dOnp7u7O5MmTconP/nJ5ocdAkMNRq3DDz88tVotF1988Wq36+npybhx47Leeutl0aJF+epXv5o3velN2XrrrbPuuutm/PjxeclLXpIPfvCD+dOf/rTS5RcuXJgzzzwzhx9+eF784heno6MjtVot991336C3+Z3vfCf/8A//kL333jvrrLNOarVaPvGJT6zhHgPQqLJ2xqOPPpqzzz47hx56aLbaaqt0d3dno402ykEHHZQf/OAHzdh1AIagrH3xXD/+8Y/zhje8IZtsskm6u7szZcqUvOlNb8ptt93W6G4DMERl7Ysf//jHqdVqq/3f1ltv3Yy7gGHyzDPPZMaMGfl//+//NXwdH/jAB3LOOefk85//fH73u9/l29/+dl72spc1MeXQdbb11qGNjjnmmFx88cU577zz8nd/93eDbnfxxRdn0aJFOfroo7P22mvna1/7Wu6+++7sueeemThxYoqiyK233povfOELOf/883P99dfnJS95ycDlFyxYkA996ENJki222CLrr79+HnvssdVmO/PMM/OTn/wkEyZMyOabb565c+c2Z6cBaEhZO+OSSy7Je97znmy++eZ59atfnUmTJuWPf/xjLrvssnz/+9/PZz/72fzzP/9z8+4IAFarrH2x3Cc/+cn8y7/8SzbffPO88Y1vzEYbbZSHH344P/vZz/Kb3/wmM2bMWPM7AYAXVNa+mDZtWj7+8Y+v8rwf/vCH+dnPfpbXvva1De417XDQQQfloIMOGvT8xYsX52Mf+1guvvjiPPHEE9lxxx3zmc98Jvvtt1+S5Le//W3+53/+J7fffnu22267JMmWW245HNFXr4BRqr+/v9hyyy2Ljo6O4v777x90u5e97GVFkuLGG28siqIoFi1atMrtzjnnnCJJ8Za3vGWF05966qni6quvLh599NGiKIrita99bZGkuPfeewe9zeuuu6646667iv7+/uLiiy8ukhQf//jHh7aDADRNWTvjRz/6UfHtb3+7WLp06Qqn/+53vyte9KIXFV1dXcWf/vSnencTgDVU1r4oiqK44ooriiTFG9/4xmLhwoUrnd/b2/tCuwdAk5S5Lwaz4447FkmKm2++eciXpRySFN/85jdXOO3YY48t9tprr+K6664r5s6dW3zuc58ruru7i7vuuqsoiqL4zGc+U0yfPr34/Oc/X0ybNq3YYostimOOOWZgTbWLj59i1KrVannnO9+Z/v7+zJ49e5Xb3HHHHfnlL3+ZnXfeObvvvnuSZK211lrltm9961uTZKV3VYwfPz4zZ87MBhtsUHe2fffdN9tuu21qtVrdlwGgdcraGQcccEAOOeSQdHSs+Fe67bbbLm9/+9vT29ubn//853VdFwBrrqx9kSQf/ehHs+666+b888/P2muvvdL5nZ0+yAFguJS5L1bll7/8ZW6//fbssssu2W233dbouiiPefPmZfbs2bnkkkuy7777Zuutt86HPvSh7LPPPgPr8g9/+EPuv//+XHLJJbngggty/vnn5+abb85b3vKWtmY31GBUmzVrVjo6OnL++eenKIqVzl/+BD7mmGNe8LquvPLKJMmOO+7Y3JAAlELVOqOrqyuJf6QCGG5l7Ivbbrstv/vd7zJz5syMHz8+3/ve9/KZz3wmX/ziF32XBkCblLEvBnPOOeckSY499tiWXD/t8Zvf/CZLly7N9OnTM378+IH//eQnP8k999yTJOnv78/ixYtzwQUXZN99981+++2Xc889N9dee21+//vfty27o1xGtSlTpuTAAw/M97///VxzzTV59atfPXBeX19fvvKVr6S7uztHHHHESpf9xje+kTvvvDMLFy7MHXfckR/84AfZcsst86//+q/DuQsADJMqdUZPT08uvfTSrLXWWtl3331bchsArFoZ++Lmm29OkmywwQbZe++983//938rnP+Od7wj5513XsaOHbtGtwNA/crYF6vyzDPP5Gtf+1rWXnvtvOMd72j69dM+Tz/9dMaMGZObb745Y8aMWeG88ePHJ0kmTpyYzs7OTJ8+feC87bffPsmyd3os/56N4Waowah3zDHH5Pvf/37OO++8FQrku9/9bh5++OG87W1vW+Xb9L7xjW/ksssuG/h59913z9e+9rVyfFkOAC1Rlc5497vfnYcffjj/+q//mg033LAltwHA4MrWFwsWLEiy7Ld+t9xyy1xzzTXZY489cvfdd+e9731vvvrVr2bSpEn5zGc+s0a3A8DQlK0vVuWSSy7JU089lSOOOCLrrbde06+f9tl1112zdOnSLFiwYNBfhtt7773T19eXe+65J1tvvXWS5K677kqy7Mvn28XHTzHqveENb8jGG2+cb37zm3nyyScHTj/vvPOSDP42v0svvTRFUeTxxx/PNddck66urrz0pS/NNddcMyy5ARh+VeiMk046KRdffHFe97rX5eSTT2769QPwwsrWF/39/QN/fv3rX8/++++f8ePHZ9ddd80VV1yR8ePH57//+7+zePHiNbodAIambH2xKueee+5qs1BuTz/9dG699dbceuutSZJ77703t956a+bNm5fp06fnHe94R4466qhcfvnluffee/PLX/4yZ5xxxsBHmr3mNa/Jbrvtlne961351a9+lZtvvjknnHBCZs6cucK7N4aboQajXldXV4488sgsWrQoF110UZLkoYceyve+971MnTo1r3nNa1Z7+fXWWy/7779/vv/972fttdfOUUcdld7e3uGIDsAwK3tnnHLKKfn0pz+dAw44IJdffvlKbyEGYHiUrS9e9KIXJUkmT5680he8brLJJtlzzz2zcOHC/Pa3v234NgAYurL1xfP9/ve/z/XXX59tttkm++23X9Oul+Fz0003Zdddd82uu+6aJDnxxBOz66675tRTT02y7F2cRx11VP7pn/4p2223Xd74xjfmxhtvzNSpU5MkHR0d+c53vpONNtoor3zlK/M3f/M32X777fO1r32tbfuUGGpAkr9Om5dPny+88ML09fXlne98Zzo66nuaTJgwIXvuuWf+9Kc/Ze7cuS3LCkB7lbUzTjnllJx++unZb7/98p3vfCdrr712U64XgMaUqS+Wf971YB8bsvz0RYsWNXwb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18m4DZINt13254O/Xnb6I79v2U0vfwye+78vfOEL2WmnnbLOOutkypQp+fu///s8/fTTg8d/5JHsvvvuedOb3pTFixe/4GMHVEsZ+iLRGUn0BVBq+qJE9AVQcmXoDH2RtvZFojMw1KABV/3mwfQs6hu0PJYrkjy5qC/fu/3Blua5/fbb8/Of/zxjx45Nkpxxxhm54IIL8qUvfSl33HFHPvjBD+aII47IT37ykyTLCmby5Mm55JJLcuedd+bUU0/NySefnG984xstzdl0/f3LJuILH002fnHSPSHpGLPsz41fvOz03313WN76t1xHR0f+67/+K3fccUe+/OUv55prrsmHP/zhVW47f/787Lvvvtlxxx1z6aWXpru7+wUfO6BaytYXySjtDH0BlJy+KAl9AVRA2TpDX5SjLxKdMdr4+CmG7Oo7Hk5H7a9v61udjlryg9sfzpt2ndzUDN/97nczfvz49PX1ZfHixeno6Mh///d/Z/HixfnUpz6VH/7wh3nFK16RJNlqq61y/fXX56yzzsqrXvWqdHV15bTTThu4ri233DI33HBDvvGNb+Rtb3tbU3O21JPzl73F70WTklptxfNqtWTCpOSRu5Ztt/4WTb/55Y/BcgcddFAuueSSgZ+nTZuW008/Pe9+97vz//1//98Kl/3973+fmTNn5k1velP+8z//M7Vara7HDqiWMvRFojP0BVB2+qIk9AVQAWXoDH3R3r5IdAaGGjTgiYVL6iqPZFnJPLFoSdMz7L///vmf//mfPPPMM/mP//iPdHZ25rDDDssdd9yRhQsXZubMmStsv2TJkuy6664DP/+///f/ct5552XevHlZtGhRlixZkl122aXpOVtqydPLPrOwa51Vnz92XPLUA8u2a4Hlj8Fy66yzTn74wx/mjDPOyO9+97v09PSkr68vzz77bBYuXJhx48YlSRYtWpR99903hx9+eP7zP/9z4PJz586t67EDqqMMfZHoDH0BlJ2+KAl9AVRAGTpDX7S3LxKdgaEGDVhv3NghTcXXW3ts0zOss8462WabbZIk5513XmbMmJFzzz03O+64Y5LkyiuvzKRJk1a4THd3d5Lka1/7Wj70oQ/lzDPPzCte8Yqsu+66+dznPpf/+7//a3rOlho7ftmXMPU+s+wtfs+3ZOGy88eOX/m8JnjuY5Ak9913X17/+tfnPe95Tz75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T5o0KfbZZ584+eSTy90EAB2AvgAgL50BQB76AqC6tdmFwnfbbbc45JBD4vzzz2+rTQDQAegLAPLSGQDkoS8AOrY2G2pERAwaNChmzpzZlpsAoAPQFwDkpTMAyENfAHRcbTbUyLIsHn/88ejWrVtbbQKADkBfAJCXzgAgD30B0LGVfU2Nxx9/vNHb6+rq4vXXX4+bbropZsyYERMmTCg7HADFpy8AyEtnAJCHvgCobmUPNfbaa68olUpNLs+yLMaOHRs///nPy90EAB2AvgAgL50BQB76AqC6lT3UOP/88xstkE6dOkXPnj1jzJgx8bnPfa5F4QAoPn0BQF46A4A89AVAdSt7qHHBBRe0YgwAOip9AUBeOgOAPPQFQHVrswuFAwAAAAAAtKayhxp//vOf44YbboiampqG21asWBEnn3xy9OvXL4YMGRJXX311q4QEoLj0BQB56QwA8tAXANWt7KHGRRddFOedd15ssskmDbf98Ic/jGuuuSaWLVsWCxcujG9/+9sxbdq0VgkKQDHpCwDy0hkA5KEvAKpb2UONZ555Jvbee++GCzPV1dXFlClTYpdddolFixbFvHnzonfv3nHFFVe0WlgAikdfAJCXzgAgD30BUN3KHmq88847MWDAgIafZ8yYETU1NXHSSSfFhhtuGFtttVUceuihMXPmzFYJCkAx6QsA8tIZAOShLwCqW9lDjc6dO8fKlSsbfn700UejVCrF3nvv3XDb5ptvHu+++27LEgJQaPoCgLx0BgB56AuA6lb2UGPw4MHxyCOPNPx8xx13xNZbbx2DBg1quO3111+PzTffvGUJASg0fQFAXjoDgDz0BUB1K3uoccwxx8TMmTPjc5/7XIwbNy5mzpwZRx555BrrvPjiizF06NAWhwSguPQFAHnpDADy0BcA1a3socapp54ahx9+eDz77LPx5JNPxoEHHhg//OEPG5bPmjUrZs6cGfvss0+rBAWgmPQFAHnpDADy0BcA1a1zuXfs2rVr/Pa3v42ampoolUqxySabrLF8iy22iBdeeCEGDx7c0owAFJi+ACAvnQFAHvoCoLqVPdSo16NHj0Zv79WrV/Tq1aulDw9AB6EvAMhLZwCQh74AqE4tHmpERKxatSrefvvtqK2tbXT5wIEDW2MzABScvgAgL50BQB76AqD6tGiocfPNN8dll10WL7/8cnz00UeNrlMqlaKurq4lmwGg4PQFAHnpDADy0BcA1avsocZll10WZ599dnTp0iXGjRsXffv2jc6dW+WDHwB0IPoCgLx0BgB56AuA6lb2Gf/KK6+Mfv36xVNPPRX9+/dvzUwAdCD6AoC8dAYAeegLgOrWqdw7vvPOO3HYYYcpDwDWS18AkJfOACAPfQFQ3coeagwbNiyWLFnSmlkA6ID0BQB56QwA8tAXANWt7KHGmWeeGffdd1+89tprrZkHgA5GXwCQl84AIA99AVDdyr6mxrHHHhuLFi2K3XffPU455ZQYOXJk9OjRo9F1x40bV3ZAAIpNXwCQl84AIA99AVDdyh5qRETU1NTE0qVL4/zzz1/veh999FFLNgNAwekLAPLSGQDkoS8AqlfZQ43zzz8/Lrnkkujdu3ccccQR0bdv3+jcuUUzEgA6IH0BQF46A4A89AVAdSv7jH/DDTfEsGHDYsaMGbHxxhu3ZiYAOhB9AUBeOgOAPPQFQHUr+0LhS5YsiS9+8YvKA4D10hcA5KUzAMhDXwBUt7KHGjvuuGO8+eabrZkFgA5IXwCQl84AIA99AVDdyh5qnHvuuXHvvffG888/35p5AOhg9AUAeekMAPLQFwDVrexraixZsiTGjx8fu+++exxzzDExcuTI6NGjR6PrTpgwoeyAABSbvgAgL50BQB76AqC6lT3UmDhxYpRKpciyLK6//vqIiCiVSmusk2VZlEolBQJQxfQFAHnpDADy0BcA1a3socaUKVNaMwcAHZS+ACAvnQFAHvoCoLqVPdQ49thjWzMHAB2UvgAgL50BQB76AqC6lX2hcAAAAAAAgPZU9ic1FixYkHvdgQMHlrsZAApOXwCQl84AIA99AVDdyh5qDB48eJ2LMDWmVCpFXV1duZsBoOD0BQB56QwA8tAXANWt7KHGhAkTGi2QpUuXxsyZM2PevHmx5557xuDBg1uSD4CC0xcA5KUzAMhDXwBUt7KHGjfeeGOTy7Isi8svvzx++tOfxvXXX1/uJgDoAPQFAHnpDADy0BcA1a1NLhReKpXirLPOis985jPxve99ry02AUAHoC8AyEtnAJCHvgDo+NpkqFFv5513junTp7flJgDoAPQFAHnpDADy0BcAHVebDjVeeeUVF2QC4BPpCwDy0hkA5KEvADqusq+p0ZRVq1bF66+/HjfeeGPcd999se+++7b2JgDoAPQFAHnpDADy0BcA1aHsoUanTp2iVCo1uTzLsujZs2dcfvnl5W4CgA5AXwCQl84AIA99AVDdyh5qjBs3rtEC6dSpU/Ts2TPGjBkTxx13XPTp06dFAQEoNn0BQF46A4A89AVAdSt7qPHoo4+2YgwAOip9AUBeOgOAPPQFQHVr9oXCL7744vjhD38YtbW1Ta7z4YcfxrnnnhuTJ09uUTgAiktfAJCXzgAgD30BQEQzhxq///3v4/zzz4/NN988unTp0uR6n/rUp2LzzTePc889Nx555JEWhwSgWPQFAHnpDADy0BcA1GvWUOOmm26Knj17xqmnnvqJ637729+OzTbbLKZMmVJ2OACKSV8AkJfOACAPfQFAvWYNNZ566qnYb7/9omvXrp+4bteuXWO//faLP/7xj2WHA6CY9AUAeekMAPLQFwDUa9ZQ44033ohtttkm9/pbb711vPnmm80OBUCx6QsA8tIZAOShLwCo16yhRqdOndZ7Maa11dbWRqdOzb4WOQAFpy8AyEtnAJCHvgCgXrPO7ltttVW89NJLudd/6aWXol+/fs0OBUCx6QsA8tIZAOShLwCo16yhxh577BHTp0+P+fPnf+K68+fPj+nTp8e4cePKzQZAQekLAPLSGQDkoS8AqNesoca3v/3tqK2tja9+9avx7rvvNrne4sWL4/DDD4+6uro4+eSTmxVozpw5sfvuu8ewYcNizJgxMWvWrCbXzbIs9tlnn9h0002btQ0A2lZ79EWEzgDoCLzHACAPfQFAvWYNNUaPHh1nnHFGPP/887HDDjvE+eefH4888kjMmTMn5syZE48++micd955scMOO8Rzzz0XZ555ZowePbpZgSZNmhQnnnhizJ49O84+++yYOHFik+v+27/9W2y77bbNenwA2l579EWEzgDoCLzHACAPfQFAvc7NvcPll18eG264YfzsZz+Liy++OC6++OI1lmdZFhtssEGcc845cdFFFzXrsRctWhTPPvtsTJ06NSIiDjvssDj11FNj7ty5MWTIkDXWnTVrVtx7770xZcqUuOOOO5r7NABoY23ZFxE6A6Aj8R4DgDz0BQARZQw1SqVSXHLJJfGtb30rpkyZEk899VS89dZbERGx5ZZbxtixY2PixIllTasXLlwYffv2jc6dOzdsa+DAgbFgwYI1CqS2tjZOOOGEuP7662ODDTb4xMdd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v273fZXq3z+OOuqodXKt75hvj/22+eabR9++fdfZV/XWPubb+3dJ8emLe5PIpC+aXpZiZ2yxxRbRr18/faEvqkpb9UWEzmhOphT7IiKNztAX+Zcddthhje6rejojp4xc9t5772zKlClZlmXZHXfcke28884tfszHHnssW7hwYTZo0KDshRdeyLWt9lq2YsWK7IEHHshWrVqVZVmWXXnlldmee+6ZZVmWHXfccdmPf/zjLMuy7Jlnnsn69euXffjhh+26bNGiRQ3577777mzEiBHJ7Lssy7J58+Zlu+22W7brrrtm99xzTzL7be1jrRL7pqllZ5xxRnbqqac2HHNvvvlmMtlW97Of/Sw7+OCDsyxL43dav4y0tEVnZFmW1Ll5bSmc99aWynml3qpVq7KePXtmM2fObNhnXbt2zWpqatp1X6X694/ttttunVzrO+bbYt+svezqq6/Ottxyy0b7s7Fjvj0yOf93LPriniQy6Yuml6XYGRdeeGE2YsQIfdHMZRRbW/VFlumM5mRKrS+yLJ3O0Bf5l/Xq1St79dVXdUYLGWrk8Pbbb2ebbLJJVltbm2XZxyeMLbbYIpszZ06rPP7qB/H6ttXey1Y3Y8aMbNCgQVmWZdlGG23UcOLOsiwbM2ZMNm3atIosy7IsmzJlSjZy5Mhk9t3f/va3bN99982effbZbM8992w4CaWw37bYYot1Tpgp7Lc+ffpkG220UbZ06dLksq39eth+++2T+p2u/logDW3dGaur5Ll5dR999FES573Vvf/++9kmm2xS8fPK6latWpVtttlm2WOPPZZlWZbNnDkz22qrrbKVK1dWZF+l+vePpgbwWbbmMd9W+yZPfzZ1zLdnJuf/4tMX+qIofZFlaXZGv3799EUzllFc7dkXWaYzmsqUYl/UL0upM/RF/mVrv+/RGc3TudKfFCmChQsXRt++faNz5493V6lUioEDB8aCBQtiyJAh7batT3/60+26bPXndsUVV8Shhx4aixcvjtra2thyyy0blg0ePDgWLFjQ7ssmTJgQjzzySER8/FG7VPbdz3/+8xg7dmzstNNODZlT2W+vvvpqTJgwIbIsi1122SUmT56cxH7r3bt3lEqluOSSS+L3v/99dOvWLS644ILYdNNNK55t9dfDU089FUuWLImDDz44md/pggULgrS0Z2dU6ty8thTOe2t75ZVXYrPNNqv4eWX133mpVIrf/va38ZWvfCU22mijWLJkSdx9992xbNmyip8zUuiC+mXrU3/MR7TvMfbqq6+ukaOxY769Mzn/F5+++FilM+mL5p9jitAZ+mLNZRRbe/ZFhM5oKlOKfVG/LNXO0BctP+ZTyJUqQw0+0SWXXBJz586NP/zhD7FixYpKx2lw0003RUTEr3/96zj77LPjJz/5SYUTRSxfvjwef/zxmDlzZqWjNOrss8+O733ve1FbWxs/+tGP4thjj01iv2VZFm+//XbssMMOMXny5HjhhRdi/Pjx8cADD1Q62hquv/76mDBhQkNBQiWlcm5+6aWX4q677kru+zfr6uritddeS+q8UldXFxdddFHcfffdMW7cuJgxY0YccsghjX6PKuta/ZivpFSPeWiKvlg/fdHx6Ason85oWop9UZ9LZ5Qnlb6ISPOYT50LhecwYMCAePPNN6Ouri4iPv4H2AULFsTAgQPbdVvtvSwi4rLLLou77747HnrooejevXtsvvnm0blz53jrrbcaMs+fPz8GDhzY7svqHXvssfHII49E//79k9h37777bgwdOjQGDx4c//u//xsnnnhi3H777Unst89+9rMREdGlS5c444wz4oknnkjimHvnnXeiU6dOcdRRR0VExGc/+9nYeuut47XXXqt4tvpl77//ftx+++3xzW9+MyIiydcCaWiPzqj0uXl1TzzxRMyfP7/i5721DRw4MInzyur+9Kc/xRtvvBHjxo2LiIgxY8ZE//7948UXX6z4OSOFLljf62TtYz6ifc/Dqw+zmzrmr7rqKud/mkVf6Isi9kVEOp3R2H800hf6oiNqr3+T0hnrz5RiX0Sk3Rn6ouXHvM5Yj1b9MqsObM8991zjIjQ77bRTqz322t+htr5tteeyyy+/PBs9enT23nvvrZH32GOPXeNCMltttVXDhWTaY9mWW26ZzZ8/vyHPPffck/Xr1y9btWpVMvtu9eX134GXwn5b/QLrl19+ebbHHntUZN80tmz8+PHZAw88kGVZlr366qvZ5ptvnv39739PIluWZdl1112XjR07NltdpX+nqy8jLW3ZGamcm5tSyfPe2lI5r9R76623so033jh7+eWXsyzLsjlz5mQ9e/bMXnvttYrsq1T//rF2rqaO+bbaN40tW991Ptb+vttKH/cUi764J4lM+uKT91WKnaEv9EU1acu+yDKdkTdTan2RZel1hr7Iv0xntIyhRk5//etfs1133TUbOnRottNOO2Uvvvhiix/zxBNPzPr165dtsMEGWZ8+fbJtt932E7fVXssWLlyYRUS2zTbbZCNHjsxGjhyZ7bLLLlmWfXzCHD9+fDZkyJBshx12yKZPn97wWO2x7JZbbsnGjBmTDR8+PBsxYkS27777NpwEUth3q1v9JFTp/XbzzTdno0aNynbcccds+PDh2SGHHJLNmzcvmf32yiuvZHvttVfD7/XOO+9MJluWZdluu+2W3XDDDWv8fiv9O119GWlpi87Isiypc3NTKnneW1sq55XV3XLLLQ15hg8fnv3mN79p932V6t8/vvrVr66Ta33HfHvst0033TTr1avXOvtqdWu/4aj0cU+x6It7ksikL5pelmJn9OrVK+vTp4++0BdVpa36Ist0RnMypdgXWZZGZ+iL/MsOPvjgRvfV6nTGJytlWZZV8IMiAAAAAAAAubimBgAAAAAAUAiGGgAAAAAAQCEYagAAAAAAAIVgqAEAAAAAABSCoQYAAAAAAFAIhhoAAAAAAEAhGGoAAAAAAACFYKgBAAAAAAAUgqEGVevII4+MUqkUt95663rXq6mpie7du8emm24aK1asiN/85jfx5S9/ObbddtvYZJNNYuONN47PfOYzceaZZ8brr7++zv2XL18el19+eRx55JGx/fbbR6dOnaJUKsX8+fPXu91HHnkkDjrooBgwYEB069Yttt122zjyyCNj5syZLXnaAJQh9c645ZZbYuzYsbHxxhvHRhttFGPGjIkbb7yxBc8YgHK0V1/86U9/ivPOOy923XXX6NOnT3Tt2jW22WabOOWUUxpdv97s2bPja1/7WvTq1Su6desWI0eOjKuuuiqyLGvxcwcgv5T74r//+7/jtNNOi7Fjx8ZGG20UpVIpLrjggtZ42tBqDDWoWt/61rciIuKGG25Y73q33nprrFixIr7xjW9Et27d4rbbbou//OUvseuuu8akSZNi0qRJseWWW8YVV1wRw4cPj1mzZq1x/0WLFsVZZ50Vt956a/zjH/+Inj17fmK2K6+8MvbZZ594+umnY//994/vfOc7MXLkyLjjjjtizJgx8fvf/778Jw5As6XcGf/yL/8SRx11VLz66qtx1FFHxXHHHReLFy+O4447Ls4666zynzQAzdZefXHSSSfFRRddFFmWxRFHHBGnn3569O/fP6666qoYNWpU/PWvf11nmy+//HLssssucd9998WBBx4Yp59+enz00UdxyimnxOmnn956OwGAT5RyX1x++eXxy1/+Ml566aXYaqutWu9JQ2vKoEqtWrUq23rrrbNOnTplr732WpPr7bLLLllEZDNmzMiyLMtWrFjR6HrXXXddFhHZV7/61TVuX7ZsWTZ16tRs8eLFWZZl2Re+8IUsIrJ58+Y1+jgffvhh1qNHj6xHjx7ZggUL1lh29913ZxGR7b333nmfJgCtINXOmDFjRhYR2ZAhQxruk2VZ9v7772djxozJIiJ76qmnmvNUAWiB9uqLX/ziF9mcOXPWWX/y5MlZRGQHHXTQOsvGjRuXRUT24IMPNty2cuXKbI899tAXAO0s5b54/PHHs9mzZ2erVq3Kbr311iwish//+MfNeHbQ9nxSg6pVKpXiuOOOi1WrVsWUKVMaXWfWrFnxzDPPxIgRI2LnnXeOiIgNN9yw0XUPP/zwiIiYO3fuGrdvvPHGMX78+Nhss81y5Vq8eHHU1NTE8OHDY8CAAWss++IXvxilUineeeedXI8FQOtItTPuu+++iIg488wz17jPRhttFOeee25ERFx99dW5HguAlmuvvjjttNNiyJAh66x/1llnRbdu3eKxxx5b4/bZs2fH448/HnvvvXcceOCBDbd/6lOfip/85CcREfGf//mfOZ8lAC2Val9EROyxxx4xdOjQKJVKzXpO0J4MNahqEydOjE6dOsWNN97Y6PfI1hdL/ccC1+eBBx6IiIjhw4e3KNMWW2wRvXr1ipdeeikWLly4zjayLIt99923RdsAoPlS7Iy33norIiK23nrrdZbV3zZ9+vQWbQOA5qlkX5RKpejSpUt07tx5jdsfffTRiIjYf//917nP5z//+dhoo40a/YctANpOin0BReHIpaoNGDAg9t9//3j44Ydj+vTpawwL6urq4uabb46uXbvG0Ucfvc59b7/99nj55Zdj+fLlMWvWrPif//mf2HrrreNf//VfW5SpVCrFf/zHf8TRRx8dI0aMiK985SvRu3fvmD17dtx///1x+OGHx0UXXdSibQDQfCl2Rq9evSIiYt68eessq7/t73//eyxfvjy6d+/eom0BkE8l++LOO++Mmpqahv+xW2/OnDkRETF06NB17rPBBhvE1ltvHS+//HLU1dX5By6AdpJiX0BR+NsKVe9b3/pWPPzww3HDDTesUSD3339/vP322/G1r32t0a8Buf322+Ouu+5q+HnnnXeO2267rdH/LdtcX/va16J3797xjW98Y42LRu24444xYcKE2HjjjVu8DQCaL7XOOPDAA2Py5Mnx7//+73HkkUfGpptuGhERy5cvj0svvbRhvaVLlxpqALSjSvTFwoUL4/TTT49u3bo1fKVUvaVLl0ZExKc//elG79ujR49YtWpVLFu2LHr27JnrOQLQcqn1BRSFr5+i6h166KHRu3fvuOeeexr+sh8RDcOEpj7md+edd0aWZbFkyZKYPn16dOnSJXbaaadW+ZqP66+/Pg444IA48sgj45VXXokPPvggnnvuuejbt2986Utfil/96lct3gYAzZdaZ4wbNy6OOeaYmDNnTuywww5x0kknxWmnnRY77rhjvPnmmw3/eNWpk7/yAbSn9u6LxYsXx0EHHRSLFi2Ka6+9NrbbbrvWezIAtBl9AeXxDpeq16VLlzjmmGNixYoVccstt0TEx99R/tBDD8XAgQNjv/32W+/9N91009h7773j4Ycfjm7dusWECROitra27Dx//etf46STToovfvGL8fOf/zy22Wab6N69e4wePTruueee6NevX/zgBz+If/zjH2VvA4DypNYZERE33nhjXHHFFdG7d++48cYb4+abb44xY8bEE088ER999FF07tw594XHAWgd7dkXixcvjn333TdmzZoVV111VaNfU1I/5F79H8xWV1NTE6VSKTbZZJPmPE0AWii1voCiMNSA+L/J9/XXXx8REf/1X/8VdXV1cdxxx+X+3609evSIXXfdNV5//fWYO3du2VmmTZsWdXV1sffee6+zrHv37rHLLrvEsmXLWrQNAMqXUmdEfPwpjNNPPz1mzpwZ//jHP2LJkiVx2223xapVq+L999+PESNGRJcuXVq0DQCarz36ov4fqGbOnBm//OUvY9KkSY0+Tv21NOqvrbG6jz76KObNmxdbb72162kAVEBKfQFFYagBEbHDDjvErrvuGs8991y8+OKLMWXKlCiVSnHcccc163HeeOONiIgW/ePRhx9+GBER77zzTqPL62/v2rVr2dsAoHwpdcb6/OY3v4mIiCOOOKJNHh+A9Wvrvlj9H6iuvPLKOOWUU5p8jD333DMiIqZOnbrOsieffDI++OCDhnUAaF8p9QUUhaEG/P/qJ+OnnHJK/OUvf4n99tsvBg0atMY6y5Yti7/97W+N3v+GG26IZ555JoYOHRpDhgwpO8fYsWMjIuLaa6+N119/fY1lDz30UPzxj3+MAQMGtGgbALRMKp0R8fFXhqztiSeeiEsvvTQGDRoUJ510UoseH4DytVVfvPfee7HffvvFzJkz44orrohTTz11vTm22267GDduXDzyyCPx0EMPNdz+4YcfxnnnnRcREccff3xZzxGAlkulL6AoSlmWZZUOASlYtmxZ9O3bNz744IOIiLjtttvi61//+hrrzJ8/P7bZZpvYeeedY/vtt49+/frFkiVLYsaMGfH8889Hjx494uGHH47ddtttjfudddZZ8e6770bEx18v9cYbb8Rhhx0WG2+8cUR8/Abi85//fMP6Rx11VNxyyy2xySabxJe//OXYcsst4y9/+Uvcf//90alTp7jrrrvi0EMPbcvdAcB6pNQZ+++/f6xYsSJGjBgRPXr0iD//+c/x0EMPxWabbRbTpk2LUaNGteGeAGB92qov9tprr3jsscdi++23X+fx6p1xxhmx6aabNvw8a9asGDt2bKxYsSK+/vWvR9++feOBBx6IWbNmxamnnhpXXnll6+8AAHJJqS/uvffeuPfeeyMiYt68efH444/HyJEjG95XbL/99vGDH/yg9Z48lMFQA1bzzW9+M6ZMmRKbbbZZvPHGG+t8xdMHH3wQP/3pT+PRRx+N2bNnx+LFi+NTn/pUDB48OPbff//47ne/G/3791/ncQcPHhyvvfZak9udMmVKTJw4seHnVatWxbXXXhs33XRTvPTSS7F8+fLYfPPNY+zYsfH9738/dt1111Z7zgCUJ5XO+NWvfhU33nhjzJ49O1asWBEDBgyIgw8+OM4555zYYostWu35AlCetuiLT+qKiI//IWrw4MFr3Pa3v/0tfvSjH8X06dPjgw8+iGHDhsVJJ50UJ598cpRKpVZ5vgCUJ5W+uOCCC+LCCy9scv0999wzHn300WY/P2hNhhoAAAAAAEAhuKYGAAAAAABQCIYaAAAAAABAIRhqAAAAAAAAhWCoAQAAAAAAFIKhBgAAAAAAUAiGGgAAAAAAQCEYagAAAAAAAIVgqAEAAAAAABSCoQYAAAAAAFAIhhoAAAAAAEAhGGoAAAAAAACFYKgBAAAAAAAUgqEGAAAAAABQCP8fIveUXofLRY8AAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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a9cW2u62bdv00ksv6aabblLdunVVoUIF2Ww2RUdH64UXXlBSUlKRjQkAikqnTp3kcDjyLXPmzJEkzZkzRytXrsz3nM2bNyszM1N79+5V796987U7cOBAJSQkKDMzU+vWrdO1115b9IMBAKCIZGdna9GiRXr88cfVpk0bRUREyM/PT1WrVlVMTIzmzZuX7+ptUydPnlS7du1ksVhUp04d/fbbby6PnzhxQi+88IKio6MVFBSk8uXLKzIyUo899pi2b9/ujeEBgFdRYwAALjcBAQGaO3eu88TacePGKTk52fn4ypUrZbFYZPnLCbt56w4cOCBJ6tOnj3Nd3vq/Pq9z584uMX91Mcf3f+3f5s2b9cADD+iqq65SuXLl1KlTJ5f4rKwsvf322+rcubPCwsLk5+en8PBw3XHHHfruu+8K3U55OVauXKmMjAy98MILatiwoSpUqKDKlSvr9ttv17p16wrf0H/4/vvv1atXL1199dWqUKGCQkND1bx5cz311FOF/g3mYvsMAEXNt6Q7AAC4cv35jwa5ubkuj8XFxalHjx46dOiQpPNXXwQEBOjQoUP65JNPtGDBAo0ZM0axsbH52r399tuVkJAgSSpfvrwCAgKUkpLinAp9zpw5Wr58+QXvjQ2gjLJ6dqUyAAC4vKxZs0Z33HGH8/82m03ly5fXiRMn9P333+v777/XF198ofnz58tqNb8mLyEhQd26dVN8fLxatGih7777ThEREc7Hly1bpnvuuUepqamSpHLlysnPz0/79+/X/v379X//93969913XW6/BKCMoMYAAMAjfn5+eu6553TPPfcoPT1dX375pR599NELPidvhr8TJ07IbrfLZrOpQoUKzsd9fHycMceOHZMkhYSEyM/Pr8D2vHF8v3DhQt13333Kzs6WzWaTr6/rn9UTEhLUvXt354lQFotFNptNx44d06JFi7Ro0SI98cQTmjFjRqE5jh49qlatWmnPnj0qX768rFarkpOTnTMlfv3117rlllvyPe/MmTPq3bu3Pv30U+e6wMBA2e12bd26VVu3btWqVauct5b1Zp8BoKgw8xIA4KItXbpUkpxXLuc5evSoYmJidOjQIf3973/Xhg0bdPbsWaWnp+vYsWN68cUX5ePjo+eee05ffvllvnZvvPFGzZkzRwkJCTp79qxOnjypc+fOadmyZWrbtq0OHz6s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HCkfHx/t2LFDc+fOlSRdc801ztu7XegK58L8/vvvkqTo6OgCHz916pTWrVt3kT0GUOpZrcW7AAAAr8mrBaTC64Fly5YZtWW1WvXee+/p0UcfVXZ2tv7xj39o4cKF+eI6dOgg6fyVyN99991F9BpAqUeNAQCAR7KysvTaa69JkoKCgnTnnXcWW+7iOL6vXbu2atSoIeni/gZyqdq3b+9x7pLuMwCYoBoCAFy0unXr6t5775UkvfLKK8rOzlbFihV1//33S5Jef/11HTx48IJt5N33Ok9QUJAk6ddffy0w/pVXXlFGRsaldh0AAADAZSavFpAKrgcyMjL06quvGrdntVr173//W48//riys7PVq1cvLViwwCUmKirKeSX4888/r7S0tAu2+df6BQAAAMD/nD17Vr1799bmzZslSbGxsQoODi62/MV1fN+3b19J0uzZs51j9XaOwjz22GOSpO3bt2vGjBnGzyvJPgOACU5eAgBcktjYWFksFh04cECzZ8+WJL322muqXr26kpKS1K5dO3344YcuJxydOHFCCxcu1F133aX77rvPpb1u3bpJkt59913NmjVLWVlZks7fHuLpp5/W+PHjVbly5WIaHQAAAIDi0qhRI9WqVUuS9Oijj2rjxo3Ox9auXatOnTopJSXFozYtFotmzpyp/v37KycnR/fff7/mzZvnEvPWW2+pUqVK+u2333Tdddfpq6++0rlz55yPHz58WB9++KG6dOmiZ5999hJGCAAAAJQ+drtd27Zt06RJk9SkSRPn8fZDDz2k4cOHF3t/iuP4fujQoWrWrJnOnTunzp07a9q0aTp58qTz8dTUVH333Xd6+OGHdf3111/ymP6sc+fO6tWrlyRp4MCBio2N1aFDh5yPJyUl6d///rfzJKfLoc8AYMK3pDsAALiyNW3aVH/729/01VdfacyYMerTp48iIiK0bNky3Xnnnfrtt9/08MMPy2q1Kjg4WJmZmS73mu7atatLe0OHDtVnn32m+Ph49evXT08++aRsNpvS0tLkcDjUr18/nTt3znmbOgBwYbGUdA8AAMBFslqtmj59uu666y5t375dbdq0UUBAgCTpzJkzqlixor766qt8NYQ7FotF06dPl4+Pj9566y099NBDys3N1YMPPijpfE2zZMkS3X333YqPj9edd94pHx8fBQcH68yZMzp79qyzrcjI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AO5RY5grzhojNjbWo74BAAAgP05e+hNfX1917dpV48eP15YtW3TgwAGtWLHiotrauHGj7Ha7Jk6cqOuuu07169fXkSNHXGKqVKmixMRElwP/uLg457+DgoIUERGhdevWOdfl5ORo48aNF8zdsmVLSdKOHTs86nOjRo3066+/6vTp0851a9askdVqdU4heym2bdum6OjoQh/39/eXzWZzWfysvEUBAIAHLNbiXQA3qDGoMQAAwBWOGgOXGWqMy6/G8Pf3v+S8AAAAZR3V0B+++eYbTZ06VXFxcUpISNAHH3wgu91+0Qe79erVU3Z2tt566y3t27dPH374oWbOnOkS06lTJ504cULjx4/X3r17NX36dH333XcuMf/61780btw4ffnll4qPj1f//v1drqIoSJUqVdSqVat892p254EHHlD58uX1yCOPaNu2bfrxxx/11FNP6aGHHlK1atU8auuvzpw5o40bN+qWW265pHYAAACAKwU1BjUGAAAA4E3UGNQYAAAApRUnL/0hODhYn3/+uW666SY1atRIM2fO1Lx589SkSZOLaq9FixaaNGmSXn/9dTVt2lQfffRRvvseN2rUSG+//bamT5+uFi1aaP369XrmmWdcYoYOHaqHHnpIjzzyiNq1a6fAwEDdddddbvP/85//1EcffeRRnwMCArR06VIlJyfrmmuu0d13360uXbpo2rRpHrVTkK+++kq1atXS9ddff8ltAQAAFMpqKd4FuABqDGoMAABQClBj4DJCjUGNAQAAUFpZHH+9WTFKhbNnz6pBgwb65JNP1K5du5Lujq677joNGjRI999/v0fPS43/zSjuxD+fMm4zfNE8o7gsH1/jNk35urnaJE9OcLBRnF92/vuBFyarnJ9RnK/hjyRZOeb3GPfPMevnWZ9y7oMk+fqYn3dpOp7sXLPxWCzmPyKZ5rYa7obt6enGua02m1lgAfeULzB3CU59bPraSFI5w/eG3fCbz1cefEXm5prF+fgYhSVmnDFO7WN4+xvTr/xDu+ONc7e6wDTalw3D18bua77fN/3clii7+WfH2wINv8eKwr67Hy7WfJGffVCs+YCSVFpqjBPf/WAUlzpmgnGb1T6baxR31q+8UZyPB3+43Hss2SiubrVQozhPjnfthgdVVtPjYk+OtXNzjOJyDOu6XA++N023UY7hcWyAB5eV7U02qwmO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S/9CFi9erIyMDG3evFlxcXHOZd68efr888+Vmppq1E5B/Pz8JMntOOrWrSubzaYdO3Y410VFRalChQqFbqNGjRrp119/1enTp53r1qxZ45wK1hPbtm1TdHR0oY/HxsYqLS3NZRn6p+l0AQAAAGqM/6HGuLgaY8iTT3qUAwAAAKUbNcb/UGNcXI0RGxvrUQ4AAADkV6QnL0VFRenzzz9XXFycfv31V91///0en2U/adIkzZs3T/Hx8frtt9/06aefKjw8XMHBwapXr56ys7P11ltvad++ffrwww81c+ZMl+fHxsbql19+Uf/+/bVlyxbFx8drxowZSkpKknT+/tLr1q3TgQMHlJSUVGD/hg4dquXLl+uVV17Rb7/9prlz52ratGl65plnjMcxe/Zsde/eXS1atFDTpk2dyz/+8Q8FBwfro48+8mi7/FnVqlVVoUIFLVmyRMeOHVNaWlqBcVarVV27dtXq1aud68qXL69nn31Ww4cP1wcffKC9e/fq559/1uzZsyVJDzzwgMqXL69HHnlE27Zt048//qinnnpKDz30kPM+0aZWrVqlW265pdDH/f39ZbPZXBZ/f3+PcgAAgDLOaineBcWOGuN/qDGoMQAAQDGgxij1qDH+hxqDGgMAAKCkFOnJS5MmTVJISIjat2+vHj16KCYmRq1atfKojcDAQI0fP15t2rTRNddcowMHDmjx4sWyWq1q0aKFJk2apNdff11NmzbVRx99lG96zvr16+v777/Xr7/+qrZt26pdu3b66quv5OvrK+n8lLA+Pj5q3LixqlSpku8+1tL5KV8XLFig+fPnq2nTpho5cqRGjx6t3r17G43h2LFj+vbbb9WzZ898j1mtVt11113Og+yL4evrq6lTp+qdd95R9erVdccddxQa+89//lPz5893KW5efPFFDR06VCNHjlSjRo107733Ou/zHBAQoKVLlyo5OVnXXHON7r77bnXp0kXTpk3zqI+HDx/Wf//7X/Xp0+fiBgkAAACIGiMPNQY1BgAAALyDGuM8agxqDAAAgJJkcTgcjpLuBIqPw+HQtddeq6efflr33XdfseV99tlnlZKSolmzZnn0vIzkZK/3JfFvZuMOX/ypUZzdg3vRn8u+8JS4eQJ8zc4r9CS31fCjniOzNj25EMw0t+l4TNuTzMfjK8M2/3Kv+ws36msUlmnYR4sHr7e3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H0REREREVLtYYxARERERUWPEi5eIiIiIqMFQqep2YFErKyvRHxKcnJxgZmaGjIwMg/kZGRlwc3Ordtl//vOfWLhwIb799lsEBARUG+vj4wMnJyecO3eOf1ggIiIiIjIB1hisMYiIiIiITErNB6RVhluFiIiIiKiWWVpaolu3bti/f79+nlarxf79+9GzZ88ql1u8eDHmz5+PPXv2oHv37op50tLScOPGDbi7u5uk30REREREdH9ijUFERERERA0JR14iIiIioobjPn7u89SpUzF27Fh0794dPXr0wHvvvYdbt24hPDwcADBmzBi0aNECMTExAIBFixZh9uzZ2Lx5M7y9vZGeng4AaNasGZo1a4abN2/irbfeQlhYGNzc3PDbb79hxowZaNu2LUJDQ+ttPYmIiIiIGhTWGKwxiIiIiIhM6T6uMeoTL14iIiIiIqoDI0eORGZmJmbPno309HR06dIFe/bsgaurKwDg0qVLUP9huNiVK1eiuLgYTz31lEE7c+bMwdy5c2FmZobjx49j3bp1yM3NhYeHBwYMGID58+eLHjNBREREREQPNtYYRERERETUUPDipUYoJCQEEyZMwN///vc6yZeVlYUOHTrgl19+gaenZ53kJCIiIrofTZ48GZMnT670tQMHDhj8++LFi9W2ZWNjg71795qoZ0R/DmsMIiIiovrBGoMaKtYYRERERI2LSqfT6eq7Ew3B0KFDUVJSgj179lR4LS4uDiEhITh27Bh0Oh0WLlyI+Ph4ZGVlwdvbGxMmTMCUKVMMltm0aRMWL16Ms2fPws7ODoMGDcKSJUvQvHnzCu1v2bIFo0ePxrBhw7Br165q+/nll19i+vTpSElJMbjrpra9+uqryMnJwerVq41ariA/3+R9KdLKPvJWMP2uUao2E8WZa8tMnltMekhoaMPZCfeHwi92i5u07Ognist6eaYozn7mP8S5C/8j+6HJzNVZFGfVrbM4t3VIL1FcWXaurMHSUnFuMzcXUZyuqFgUpzKTHyelX6cq4b6jK9OKc6NMeMxQy3If+fVXcequneWfDREjTktKL6WJ4szcXGXtpV0R5zb3kv2IpaqNO1O1ws9GHX7P38tWo6m33NlJP9dpPsce3es0HzUurDGqV9MaI33NRlHcsS5dxW36ecjOqRxqYfMU/3JMFGfVrYusQXP5PU66khJxrITKTFYv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XouZ/0DOMeUbDB06PySPO54syu0Q0AlXl32oGOcxdZKoTYeATuIb1W01GnGbOUePK8d1CUDepcui3HZeLVGQna3cR0dH5J47rxhn39ZH9N4A8vfHIaCTOO7so6Gi3L7xe0WxvvF7cS70ScW4tnt34tKU10S5vZYvRPaP/1WMc3wkCGdDBiv38YfdRq235HNpq9GIt09tbHNp3I2D8aLczXs/iotjJijGea//GHkXLirG2bX2Rvqna0W53V4Yh7zUS8pttvJC6oRXFONaffwuLoyKEOVuvSVWvD55aWnKcZ6eRu3f0s9absppxTh7fz/RsQooP17lnb+gGGfn01q83jfiD4lyN3+0J3JPKt/cZN/RX/y5yD17TpTb3ret+Dhdb1SsMSrDrUJERERERERERERERERERERERPWCFy8REREREREREREREREREREREVG94MVLRERERNRwqFR1OxERERERUcPGGoOIiIiIiExIpVbVaPozfvvtN4SHh6NLly4IDg7G4sWLUVxcrLjcpk2bMH78eDzyyCNo37499uzZUyHmp59+Qvv27StMr7yi/AjIPzI3KpqIiIiIiIiIiIiIiIiIiIiIiO57eXl5GDt2LLy9vfHBBx8gIyMDCxcuxJ07dzB79uxql/3iiy8AAL1798auXbuqjY2JiYGPj4/+3w4ODkb1kyMvEREREVHDcZ/fFf3hhx/C29sb1tbWePjhh5GUlFRt/LZt2+Dn5wdra2s89NBD2L17t8HrOp0Os2fPhru7O2xsbNC/f3+cPXvW6H4REREREVEVWGOwxiAiIiIiMqU6HqV1y5YtuHXrFlasWIHHHnsMTz31FKZPn44tW7YgIyNDcdmtW7fipZdeUszj6+uLLl266KdWrVoZ1U9evEREREREVAc+++wzTJ06FXPmzMEvv/yCzp07IzQ0FNevX680PjExEaNHj0ZkZCSOHDmC4cOHY/jw4UhOTtbHLF68GO+//z4+/vhj/PTTT2jatClCQ0Nx586dulotIiIiIiKqJ6wxiIiIiIhIyQ8//ICePXvC3t5eP2/QoEHQarVISEiodlm1uu4uKeLFS0RERETUcKjVdTsZYdmyZXjhhRcQHh6ODh064OOPP0aTJk0QGxtbafzy5csxcOBATJ8+Hf7+/pg/fz66du2KFStWACi/I/q9997Dm2++iWHDhiEgIADr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Y+JSX5wqyt1q5TLkpV5SjLNr5YVrH/xLMc79pfH1ut6Szw9Q/hkyde6c5FOi3A6dOuDSP6IV47zeixG16dCpg3ggClsnJ+SePqMYZ+/XTrzeFyMmi3J7x65A1v4DinFO/fqI98XM/3wjyu08dBCyDyUpxjn27IGcYycU4xw6P4Tsw0dEuR27BYq/I7K+/V4xzql/X9w4ECfK3bzPY+I2pcd9yXYEyreldL3rTT3elHc/48VLjdDw4cPrNJ+TkxNmzJCPVkNERERERA8W1hhERERERGRKrDGIiIiIGhdevEREREREDQafiExERERERKbEGoOIiIiIiExKJX/EeGPCrUJERERERERERERERERERERERPWCIy8RERERUYPBu6KJiIiIiMiUWGMQEREREZEpqdSq+u7CfYkjLxERERERERERERERERERERERUb3gyEtERERE1GBoeVM0ERERERGZEGsMIiIiIiIyKRVHXqoMR14iIiIiIiIiIiIiIiIiIiIiIqJ6wYuXGqGQkBBs3ry5zvJlZWXBxcUFaWlpdZaTiIiIGiedTlenExGVY41BREREDRVrDKL6wRqDiIiIGiy1umZTA9fw17CODB06FAMHDqz0tbi4OKhUKhw/fhzHjh3D6NGj0bJlS9jY2MDf3x/Lly+vsMyHH34If39/2NjYoH379li/fn2Vubds2QKVSoXhw4cr9vPLL79ERkYGRo0aJV63P8vJyQljxozBnDlz6iwnEREREdGDjjVG1VhjEBEREREZjzVG1VhjEBEREdUvlY63c5jErl27EBYWhtTUVHh6ehq8FhERgRMnTuC///0vYmNjcezYMTz55JNo2bIlEhMTERUVhcWLF2Py5MkAgJUrV2LmzJn49NNPERQUhKSkJLzwwgvYvHkzhg4datD2xYsX8eijj8LHxweOjo7YtWtXtf3s378/+vfvj9dee82k66/k5MmT6NatG65evQpHR0fxcgX5+aI4bS08F1JdUmLyNrUWFibNLW3PmDah1crizMzEucWxZWWmjTOGsI+3/+97cZM3P/tcFOcc+4GsQWMO1ybe5gVr5Hc53dr5pShO3ayZKK7JXwaIc9/8bKdJc7tsWS3Orc0vEOZuKmvQ3FyeOzdPlttWtt6/HD8uzt21c2dRnO5WoShOZWUpzg1LI2Lri/CYqr15U9yk2tpaFliP28dW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DLvX+IcecroOAAAAUJXQY5TscnqMR/7fYKfrAAAAAFUJPUbJLqfHmDJlitN1AAAAysq///1vxcTEKCAgoGjaLbfcosLCwkuOoS62detWZWdn65Zbbima5u3trR49eujf//63y8fp5fKM1VydOnXUv39/TZkyRZmZmRoyZIjd+6tXr9aJEyfUoUMH1alTRzt37tTEiRMVGxurJk2aSJJGjRql2bNna9KkSRo2bJi+/PJLLV26VKtWrSrKM2XKFN1yyy268sorlZWVpcTERH399ddas2ZNiWO76aablJ2drZ07d+rqq6+WdP6Z1dOmTdMdd9yh6dOnq379+vrhhx8UFhammJgYTZw4Uf369VN0dLS6d++ulStXavny5friiy+cWi8HDhzQkSNH1L179xJjfHx85OPjYzct8+zvTtUBAADVWyFXKqMKosco3uX2GPne3k7VAQAA1Rs9BqoieoziXW6PAQAA4BSPsr3H0L59+9S3b1+7aVarVSEhIdq3b1+p80lSs2bN7KY3b95c7777rn7//Xe7x/3ef//9Sk9PV0hIiG699VY9/PDDlzwOuDTceckN4uPjlZaWpri4OIWFhdm95+vrq7fffludO3dWZGSkxo0bpz59+uiTTz4pimnatKlWrVqltWvXqm3btnrllVc0f/58xcXFFcWcPHlSgwcP1lVXXaVu3brpu+++05o1a9SjR48Sx3XFFVfozjvv1OLFi4umeXt76/PPP1fdunXVq1cvtWnTRi+++KI8PT0lSXfccYdee+01zZgxQ61bt9a8efOUkJCgrl27OrVO3nvvPd18881O3xoMAAAAAD1GcegxAAAAgMtHj3EpegwAAFCRdevWrdRXSTIzM2W1Wi+Z7u/vr4yMjFLn8/b2vuTEbavVKpvNVjSvn5+fhg8frunTp2vBggW688479c9//lMPP/ywU8vHnZfcICYmpsTnk990003atGmTwxxdu3bVDz/8UOL7xT1D0MQTTzyhHj166IknnlCdOnUkSY0bN9b7779f4jwPPPCAHnjggRLfL25Z09PTi/6dl5enuXPnKjEx8bLGDAAAAFR39Bj0GAAAAIAr0WPQYwAAALhCq1at7B7XGxMTo7p16+q5557T9u3bFRUVZZTHYivp6BRV1sKFC3XttdeqTZs2ZVIvJSVF69at08iRI52eN/PESaO4UwXmH+Oc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HYqOji7xfR8fH1mtVruXj4+P03UAAED1ZbPZyvQFlAV6jJLRYwAAAHejx0BVRI9RMnoMAADgdhbL5b2qOE5ecrE6deqof//+mjJlio4dO3bJ85tXr16thIQE7dixQwcOHNCqVas0atQoxcbGqkmTJpKkUaNGad++fZo0aZJ2796tv//971q6dKnGjRtnl6uwsFAJCQm677775OXl5XBsN910k7Kzs7Vz586iaQMHDlRoaKjuuOMObdy4Ufv27dMHH3ygzZs3S5ImTpyohQsXas6cOdqzZ49mzpyp5cuX69FHH3VqvRw4cEBHjhxR9+7dnZoPAAAAqO7oMYpHjwEAAABcHnqM4tFjAACAqmrv3r0aOnSo2rVrp9jYWL300kvKy8tzOJ/NZtNbb72lrl27KioqSv3791dycvIlcSdOnNCDDz6o6OhodezYUU888YSys7OdGiMnL7lBfHy80tLSFBcXd8nzm319ffX222+rc+fOioyM1Lhx49SnTx998sknRTFNmzbVqlWrtHbtWrVt21avvPKK5s+fr7i4OLtcX3zxhQ4dOqRhw4YZjeuKK67QnXfeqcWLFxdN8/b21ueff666deuqV69eatOmjV588UV5enpKku644w699tprmjFjhlq3bq158+YpISFBXbt2dWqdvPfee7r55pvVuHFjp+YDAACojlJTUzVo0CBZrVYFBAQoPj7e4YF+165dZbFY7F6jRo2yizl06JBuvfVW1apVS3Xr1tXEiRN17tw5dy4KXIQe41L0GAAAAOboMfBH9BiXoscAAABVUUZGhu677z7l5+frjTfe0Lhx47R06VK9+OKLDud9++239frrr2vIkCGaN2+eQkJCNGzYMP36669FMfn5+Ro+fLgOHDigV155Rc8884w2bNigCRMmODVOi4170VYr27dvV48ePbR3717VqVOnTGrm5eWpRYsWSkxMVGxsrFPzZmVmunw8hYY5PaxWl9e2/feWuo5YDG8zW+jE7eE8yvGrbjrO8hyjKdPPjyRZDK4kksy3t1tuB2i4zk0/u5Jk8fY2y1lQ4PLaHjVrGtYudBwkyeLp+nN8TX/sWmrUcHltU1u3bTOODXvqb0ZxNa+71iju983fGteumzjfKK4wLd0ozqtBfePa544cM4o7/fBjRnE1Yzoa1zZdR7W632SWsIbZvsoZDSY/4vKcpt5e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Pv3006Jp+fn5+vzzz3XjjTfa5d+9e7cOHDhQNG3z5s1KT09Xly5djMfJyUsAAACoMgptZftyl8WLFysiIkLdunVTr1691LlzZ7311ltF7+fn5+vnn39WTk6OJMnb21tffPGFbr75ZkVERGjChAnq27evVq5cWTSPp6enPvnkE3l6eiomJkb/7//9Pw0ePFjPPfec+xYEAAAAqOToMegxAAAAgMpswIABql27tsaMGaMNGzbogw8+0EsvvaQBAwaoXr16RXH33XefevToUfR/Hx8fjRw5UgsWLNC7776rzZs3a8KECUpPT1d8fHxRXFxcnFq0aKEHH3xQX331lVavXq3HH39cXbt2LbrwwQSPjauGbrzxRo0aNUr33HNPmdQ7ffq0WrVqpa1bt6phw4ZlUhMAAKAyCwoKUmJiYonvN2nSxO7xFY0aNdL69esd5m3cuLFWr17tkjECF6PHAAAAqNjoMVDZ0GMAAAC4hr+/v9599109//zzGjNmjGrXrq277rpL48aNs4srLCxUQUGB3bQRI0bIZrNpwYIFSk1NVWRkpN555x01atSoKKZGjRqaP3++XnjhBY0fP15eXl7q0aOHHn/8cafGyZ2XXKR3797q2bNnse8lJSXJYrFo+/btOnPmjHr27KmwsDD5+PioUaNGGjt2rN0tuiTp66+/1jXXXCMfHx+Fh4dr4cKFdu9nZWXpkUceUePGjeXr66tOnTrpu+++czjOjz/+WCdOnNCAAQMue1mdFRwcrMGDB2vq1KllVhMAAFRPNputTF+AO9FjlIweAwAAlBV6DFQl9Bglo8cAAABVWfPmzbVw4UJt27ZNmzZt0uTJk+Xt7W0X849//ENffvml3TSLxaKRI0dq/fr1+vHHH7V06VJFR0dfkr9evXp644039MMPP+i7777TtGnTVKdOHafGaLHREbnEihUr1LdvXx08ePCSs/KHDRumH3/8Ud99953S0tK0ZMkSdejQQSEhIUpJSdGYMWN0zTXXFF35sn//fl199dUaNWqUhg8frnXr1umRRx7RqlWrFBcXJ0nq37+/duzYoTlz5igsLEz//Oc/NWvWLP30009q0KBBiePs3r27unfvrscee8x9K6MYO3fu1LXXXqujR48qKCjIeL6sPzRDLpGXZxb3hy+rKxQcOWoU59kgzOW1TRVaLEZxHpVk1+Hq5SlMSzeu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bRfmdFvttDTHcYGBSt38rVHtoJiOSt+5y2FcQOtIZRxyfGKq/5WNlHnipMM4SbLWq2v8WUvftdvxGCMjnPqOmS636WfytOGFucHdbzIap7VBmFK/dfwoy6CO7Y2+i9L572Pajp8cxgVe3cro4i+/oCCntrfxZ8hw35Kess+odkB4M+3pHOcwrsWGNS6NuxBrvM5Pn3YY5xcc7NQ6N91nuGO5Tfdr7qhtmhMVC4+NcxEvLy8NHjxYCxcutHum97Jly1RQUKCBAwcWO9/Ro0e1fPlydenSxal6nTp10pYtW/Ttt+cPPvbt26fVq1erV69eJc6zfft2ZWRk2D3bXJIGDx6s9957T6+//rp27dqlefPmqU6dOpKkI0eOqFevXurQoYO2bdumOXPm6J133tELL7xgl+Pdd99V7dq19c033+ill17Sc889p7Vr7e8M0bFjRyUlJTm1nAAAAM4otJXty8fHR1ar1e5V0i/oQ0JCFBERUerL29tbMTExSk9P15YtW4rm/fLLL1VYWKjrrrvO4Tp455131KdPH4WEhDiMTU5OVmBgIH9UqKDoMegxAABA+aPHoMeoSugx6DEAAAAqKu685ELDhg3Tyy+/rPXr16tr166SpISEBPXt21f+/v52sQMHDtRHH32ks2fPqnfv3po/f75Tte655x6dPn1anTt3ls1m07lz5zRq1Cg9/vjjJc5z8OBBeXp62j3f/Jdffil6Jnn37t0lnb8a54K///3vatSokWbPni2LxaKIiAgdPXpUkydP1tNPPy2P/97ePioqSlOnTpUktWjRQrNnz9a6devUo8f/HoMTFhamgwcPOrWcAAAA1U1kZKR69uypESNGaO7cucrPz9fYsWM1YMAAhYWFSTr/i9lu3bpp0aJF6tixY9G8KSkp+ve//63Vq1dfknflypU6ceKErr/+etWsWVNr167VtGnT9Oijj5bZssF59Bj0GAAAAH8WPQYuRo9BjwEAAFARceclF4qIiFCnTp2KbpGakpKipKSkotuWXmzWrFnaunWrPvroI+3du/eSWwE78vXXX2vatGn6+9//rq1bt2r58uVatWpVqbcyPXv2rHx8fGS56LnzycnJ8vT0LPGKiV27dikmJsZuntjYWGVnZ+vwRbcYjYqKspuvfv36l9yK2NfXVzk5OSWOLzc3V5mZmXav3NzcEuMBAAD+yGaz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8HANCQnR++67z+s/DRAcHJzln8vL3z/79+9XVdUVK1ZoiRIlcp0XFhamKSkpqnrpn8fAwMAs53zTpk1aqlQprzpe+bwrVaqky5Yty3J81apVWr58+TxnXrhwQefMmeP5001ly5bV4cOHe55HbtjxvehyubRs2bJasWLFq35cfplUb1j9/RgSEuIZEaqXXk74yj/ps3PnTi1SpIhXHYODgz0/I64mOTnZ6+9vAPAnbAw2BhuDjeENNgYbg43BxgCA62FjsDHYGGwMb7Ax2BhsDDZGQeIWwE/ExMRIxYoVJTMzU2655RaJiYnxfJQpU0YCAgK8zqxQoYIkJydneaxYsWKybNkyOXv2rNxzzz156jpo0CD58ssvZdiwYfL444/LmTNn8pQjItKwYUNZuHChiIhUrlxZNmzYkOV4UlKSREZGepVZrFgxOXLkiIiIHD9+XNLT0z2fi4gcOXJEihYt6lVmx44d5bHHHpP169dnO7Z+/Xrp16+fdOrUKdd5pUuXlh07dmR5rFy5cpKYmChr166Vhx56yKt+IiIlS5aUAwcOeD4/ePCgpKenS1hYmIiIxMfHy9GjR73K7NGjh/z444/ywQcfSJcuXeTYsWNe97rSPffcIy+//LJkZGTIXXfdJe+8846oquf4W2+9JXXq1PEqs2LFirJ48eIcjy9evFhiYmK87nru3Lksnz/33HMyfPhwueOOO+Snn37yKsvq38eradCggbz33nuyf/9+eeedd2TPnj1y++23e5VRrlw5+eOPPzyf79ixQzIzMyUqKkpERG666SY5deqUV5kul0tERNxutwQHB0t4eLjnWLFixeTEiRNe5V2Zee7cOSlTpky253Do0CGvMy8rVKiQdOvWTZYuXSqpqany97//XWbNmiVVq1bNdYYd34sxMTEyadIk2blz51U/rvU9kBOrvx8rVKggP//8s4iIrF27Vlwul/zyyy+e42vWrJFy5cp51bF06dJZMv7XL7/8IqVKlfIqEwD8CRuDjcHGYGPkBxvj/z8HNkbusDEAoOBjY7Ax2BhsjPxgY/z/58DGyB02BhzFl3dOAb6yb98+nTNnjr711lvZXlLPG08++aT+7W9/u+qxkydPasOGDfP0JxYuO3PmjD7++OMaHx+vAQEBebrz+qefftLw8HAdOXKkvvXWWxodHa0vvviizpo1S//xj39oRESE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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+QAAAJNCAYAAAC4Ob+DAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAACcTElEQVR4nOzdeXxU1f3/8fckk8m+EAwoKEuQhDUhAiKiiAhVXEAQEP2iKCDQL4pK9StYf1SUKqK21eBCFYpSF1BBBQGLVqGCUJcIFWUpARTQELbsyUxm7u+PYYZMZrJMCLkBXs/HgweZu567nXM/5557rsUwDEMAAAAAAKBBhZidAAAAAAAAzkYE5AAAAAAAmICAHAAAAAAAExCQAwAAAABgAgJyAAAAAABMQEAOAAAAAIAJCMgBAAAAADABATkAAAAAACYgIAcAAAAAwARWsxMAAGeT/v37a//+/dVOM336dN1xxx267bbb9O9//1uvv/66evXq1UApBNCQvv32W82dO1fff/+98vPzZRiGnnzySQ0bNqza+Tz5Q0VhYWFKSEhQly5dNHLkSPXv37/K+Y8ePaolS5boiy++UHZ2tvLy8mSz2dSiRQt169ZN1113nXr37l1tGgYPHqzt27crLCxM//rXv9SkSZPabzgAQBIBOQCY4qKLLlLr1q0DjrvwwgsbODXStGnTtGzZsloFAoFQeYDGxlP59emnn+r88883OzkB5eTkaOLEiSooKFD37t3VsmVLhYSEqFWrVrVeRocOHdSxY0dJUnFxsX744Qd99tln+uyzz3TbbbfpkUce8Zvn/fff18yZM1VcXCybzaa0tDQ1b95cpaWlys7O1jvvvKN33nlH11xzjZ577rmA692yZYu2b98uSXI4HPrwww81ZsyYOuwFADi7EZADgAlGjBhRY+D71FNPqaSkRC1atGigVAFoSOvXr1d+fr6uv/56Pfvss3VaxoABA3TPPfd4f7tcLv3lL3/RvHnztGjRIl111VU+T7rfeustPfroo7JYLLrrrrs0adIkxcTE+Czzv//9rzIzM7V3794q1/vuu+9Kkpo3b66cnBy9++67BOQAUAe8Qw4AjVSLFi3Url07RUZGmp0UAKfAgQMHJElt2rSpt2WGhITo3nvv1QUXXCBJWrVqlXfcrl279Mc//lGSu1XMAw884BeMS+5WOs8995x+//vfB1xHSUmJPvroI0nSnDlzFBUVpR07dmjLli31th0AcLYgIAeARuq2225TamqqNm3a5DN82rRpSk1N1dKlS7Vjxw7dd999uuyyy9SxY0dlZmZ6p1u1apXuuOMO9erVS507d1avXr107bXX6pFHHtG2bdskSfv27VNqaqqWLVsmyf3+empqqvdfxeUFsmnTJqWmpnrfZb399tt95l+6dKny8/PVsWNH9ezZUy6Xy2f+lStXeqddu3atzzi73a709HR17dpVpaWlPuOOHTumP/3pT7ruuuuUnp6ujIwMDRs2TK+88orftLWVl5enuXPnatiwYerevbvS0tJ01VVX6d577/VLW13S4NlXt912m+x2u+bOnaurr75aXbt2Vb9+/fT000+rrKxMklRQUKCnnnpKV111lbp27ar+/fsrMzNT5eXlfsuteD5s27ZNd999ty655BKlpaXphhtu0GuvvSan01nldn/00UcaM2aMLr74YnXp0kVXXnmlpk+frt27dwecvn///kpNTdW+ffu0ceNGjR07Vj179lRaWpqGDh2q999/v9r9vHr1ao0bN06XXHKJunTpossvv1wPPPCA/vvf//pN6zk/+/fvL8MwtHjxYg0bNkzdunVT9+7dNXbsWGVlZfnMs3TpUqWmpnr7arjqqqt8zsmK19OGDRs0adIkXXrppercubN69uyp3/zmN3rggQf01VdfVbsdgdR2X3rS6Lm+5s6d601fde9911ZoaKi3GXvFPiteffVVORwOdejQoVZPs3v27Blw+OrVq1VYWKiUlBRdcskluvbaayWdeGoOAKg9mqwDwGkqKytLf/jDH5SUlKQePXqotLRU0dHRktw3+JmZmbJarcrIyFDz5s1VUFCgX375Re+++64uvPBCdejQQVFRURo6dKi++eYb/fTTT37vtntu6qtyzjnnaOjQofrXv/6lQ4cO6bLLLlNSUpJ3fKtWrRQXF6fOnTvrP//5j77//nulpaV5x3/55Zfevzds2KArrrjC+/ubb75RaWmpevXqpYiICO/wn3/+WWPGjNH+/fuVmJioK664Qg6HQ5s2bdIzzzyjVatW6W9/+5vi4+NrvS+3bdumCRMmKCcnR7Gxserevbuio6P1yy+/6PPPP9eRI0d80nYyaXA4HBo3bpx++OEHXXzxxWrbtq2+/vprvfrqq9q1a5dmz56tUaNGKS8vTz179lSbNm301Vdfae7cuTp06JBmzpwZcBu2bNmiRx99VOecc4569+6t/Px8bdq0SU888YS++eYbPffcc7JYLN7pDcPQtGnT9P7778tqtapHjx5q2rSptm7dqqVLl2rVqlV6/vnn1bdv34Dre++99/TSSy+pU6dOuvzyy7V//3599913euihh3Ts2DHdcccdPtOXl5frgQce0KpVq2Sz2dS5c2c1b95ce/bs0fLly7VmzRplZmZWub7p06drxYoV6t69u/r166cff/xR69ev11dffaW///3vSk9Pl+Q+54YOHaqPP/5YxcXFuvrqqxUVFeVdzjnnnCNJWrZsmaZPny5JSktLU69evVRaWqqcnBytXLlSTZo0qTIgrSzYfelJ448//qht27b5vAdeXx2jFRYWSpJsNps3jf/85z8lSTfeeKPPuRAsT+B90003ef9/9913tXLlSj388MM+1ysAoAYGAKDBXHnllUZKSorx3nvv1Tjt6NGjjZSUFGPjxo0+wx966CEjJSXFSElJMZ555hnD6XT6jC8rKzPS0tKMbt26Gbt27fJb7r59+4z//ve/AZdZm3QFk1aPZ5991khJSTFeeukln+H9+/c3LrvsMuPiiy82rr/++lrNM2LECCMlJcWYNGmSUVRU5B1++PBhY+jQoUZKSooxderUWqe9qKjIuOKKK4yUlBTj//7v/4zCwkKf8fn5+cb69etPOg0bN270Hrfhw4cbR44c8Y7bt2+f0bNnTyMlJcW4/vrrjYkTJxrFxcXe8Vu2bDE6depkdOjQwdi/f7/PciueD48++qjhcDi843bs2GFccsklRkpKivHWW2/5zPfmm28aKSkpRq9evYwffvjBO9zlchnPP/+8kZKSYvTo0cM4fPiwz3yec7hz587GP//5T59x7733npGSkmJ0797dKCkp8Rn3pz/9yUhJSTFGjBhh/PTTTz7jVq1aZXTs2NHo2bOnkZeX5x3+888/e7ftyiuvNLKzs73jysvLjenTpxspKSnG2LFjjco86fz555/9xhmG+9xLSUkxvvrqK79xhw4dMrZu3RpwvkDqui89455//vlar8vDc80FmjcnJ8fIyMgwUlJSjOeee84wDMP46aefvPsy0DbXVnZ2tvf4V9yea665xkhJSTGWLVtW52UDwNmIJusAYILKTcM9/2677bZaL6NNmza6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/v379c4773i/Q1yR5zvE8fHxPk/yPIHazp0767TO2sxvsVh0ySWXyDAMvfHGGwoLC/MJWHv37i2LxaI33njD+7uyHj16KD09XaWlpZoxY4b33XPJ3QJgxowZkqRrr7221p1ZjRgxQueee65++OEHPfLIIyouLvYZX1hY6G1Cf6rSUB8OHjyop556yicA3bVrl1588UVJ0pgxY3ymHzt2rCTpxRdf1LZt27zDDcPQiy++qB9//FFxcXEaOXLkSaftnHPO0W233abi4mJNmjRJ27dv95vGbrfr008/1a5du056fVL152RJSYn+9re/BXxf/euvv1Z+fr5CQ0O9LQpq0pD78mS0a9dO06ZNkyTNnj1bf/rTnwLmE7t379bUqVM1a9Ys7zBP7+meTgKr4hn/+eefB9y/AABfNFkHgDNMfn6+HnnkEc2cOVMdOnTwdva1d+9e/fDDD7JYLHrwwQd93u8cMGCAXnjhBS1atEg7d+7Uueeeq5CQEPXv319XXXVVjeu8+uqrtXTpUj399NP68ssvlZiYKIvFoptuusnnneFLL71Uq1evVllZmXr16uXzaa8mTZqoY8eO+uGHH7zTBvLss89qzJgx+vTTT3XVVVepR48eKi8v16ZNm1RYWKjOnTt7g+LaiI6O1ksvvaQJEyZo6dKl+uSTT3TRRRcpKipKv/zyi3788UelpaX5pKe+01AfRo0apXfeeUeff/650tPTlZeXp02bNsnhcGjgwIG69dZb/abPysrSBx98oJtuukk9e/ZU06ZNtXXrVu3evVsRERF65pln6q0DwN/97nc6ePCgVqxYoRtvvFEdOnTQBRdcoNDQUP3666/atm2biouL9corr9TLZ/muvvpqbdq0SQ8++KAuu+wyxcXFSZLGjRunc845R7Nnz9acOXOUkpKi1q1bKywsTPv379d3330nSZo0aVKtt72h9+XJGD16tCIjIzVr1izNmzdPCxcuVFpampo3b66ysjJlZ2d7K0Wuu+46Se4vC+zdu1c2m807rCrt27dX586dtXXrVr3//vveygoAQGAE5ABwhrngggv08MMP66uvvtLOnTu1du1aSVKzZs1044036rbbbvP5lJjk7qk5MzNT8+fP1+bNm/Xll1/KMAyde+65tQrI+/Xrp1mzZumtt97Sxo0bvU+Nu3fv7heQB/rbo3fv3t5Kg6o6dLvgggu0dOlSLViwQJ988ok+//xzhYSEqG3btho0aJBuv/32aju8C6RTp0768MMP9frrr+vTTz/Vv//9b7lcLiUlJal///5+PeKfijScrPT0dN188816/vnntX79ehUXF6tNmzYaPny4Ro8e7dcJm8Vi0Zw5c9S3b18tXrxYW7duVUlJic455xwNGzZMd911V5164q6K1WrVs88+q8GDB+vdd9/V5s2btXPnTkVGRiopKUlXXnml+vfvX2/N/G+55RYVFRXpww8/1Nq1a729sA8ePFitWrXSzJkz9dVXX+mHH37Qhg0b5HA41KxZM/3mN7/RLbfcElSHgg29L0/WTTfdpCuvvFKLFy/WF198oV27dikrK0s2m03nn3++br75Zt1www3eY+Fpfn7llVcqPj6+xuUPGTJEW7du1bvvvktADgA1sBj12eUqAABoUNOmTdOyZcv05JNPnvSn9AAAQMPiHXIAAAAAAExAQA4AAAAAgAkIyAEAAAAAMAHvkAMAAAAAYAKekAMAAAAAYAICcgAAAAAATEBADgAAAACACQjIAQAAAAAwAQE5AAAAAAAmICAHAAAAAMAEBOQAAAAAAJiAgBwAAAAAABMQkAMAAAAAYAICcgAAAAAATEBADgAAAACACQjIAQAAAAAwAQE5AAAAAAAmICAHAAAAAMAEBOQAAAAAAJiAgBwAAAAAABMQkAMAAAAAYAICcgA+9u3bp9TUVC1durRO8y9dulSpqanat29fPacMAABU5il3//Of/zT4um+77TbddtttDb5e4ExCQA40Qp7C1fOvU6dOuvzyyzVt2jTl5OSYnbxTZvny5Vq4cKHZyQAA4JSrXNZX/PfMM8+YnbxTqqSkRJmZmdq0aZPZSQFMZzU7AQCqNmXKFJ1//vmy2+367rvvtGzZMn3zzTdasWKFwsPDzU5evVuxYoV27typO+64w+ykAADQIDxlfUUpKSkmpaZhlJSUaO7cubr77rvVq1cvs5MDmIqAHGjE+vbtq65du0qSRowYoSZNmuiVV17Rp59+qmuvvdbk1AEAgJNVsawHcPahyTpwGunRo4ck6eeff/YZvmvXLk2ZMkUXX3yxunbtqmHDhunTTz/1mebYsWN66qmndMMNNygjI0MXXXSRxo8fr23bttU5PTt37tTtt9+utLQ09e3bVy+++KJcLpffdJ988okmTJigyy67TF26dNGAAQP0wgsvyOl0eqe57bbb9Pnnn2v//v3eJnv9+/eXJNntdj333HMaNmyYunfvrm7duunWW2/Vxo0b65x2AAAas/379+vRRx/V1VdfrbS0NPXq1UtTpkypVR8teXl5Gj58uPr27avs7GxJ7rL0+eef18CBA9WlSxddccUVmjNnjux2e63Ss3jxYg0YMEBpaWkaPny4vv76a79palNe79u3T71795YkzZ0711vmZ2ZmSpK2bdumadOm6aqrrlLXrl3Vp08fTZ8+XUePHq1VOoHTDU/IgdPI/v37JUlxcXHeYTt37tQtt9yi5s2b66677lJUVJRWrVqlyZMnKzMzUwMHDpTkDuI/+eQTXXPNNTr//PN16NAhLV68WKNHj9ZHH32k5s2bB5WW3Nxc3X777XI6nZowYYIiIyO1ZMmSgE3ply1bpqioKN15552KiorSxo0b9fzzz6uwsFAPPfSQJGnSpEkqKCjQr7/+qunTp0uSoqOjJUmFhYV65513dP3112vEiBEqKirSu+++q/Hjx+udd95Rx44dg9+ZAAA0AoWFhTpy5IjPsMTERP3nP/9RVlaWrrvuOp177rnav3+/3nrrLd1+++366KOPFBkZGXB5R44c0dixY5WXl6e///3vatWqlVwul37729/qm2++0ciRI9WuXTvt2LFDr732mvbs2aMXX3yx2jS+8847mjFjhjIyMjRmzBj9/PPP+u1vf6v4+Hidd955PttSU3mdmJioRx99VI8++qgGDhzovU9JTU2VJG3YsEE///yzhg0bpqSkJO3cuVNLlizRf//7Xy1ZskQWi+VkdjfQ+BhnkT179hj/7//9P2Pw4MFGx44djeuuu+6klvfZZ58ZN998s5Genm706NHDGD16tPHLL7/UU2pxNnvvvfeMlJQUY8OGDcbhw4eNX375xVi9erVxySWXGF26dPE5z8aMGWNcf/31RllZmXeYy+Uybr75ZuM3v/mNd1hZWZnhdDp91vPzzz8bXbp0MebOneszLCUlxXjvvfeqTeMf//hHIyUlxdi8ebN32OHDh43u3bsbKSkpxs8//+wdXlJS4jf///t//89IT0/3SfeECROMK6+80m/a8vJyn+kMwzDy8vKMSy+91Jg+fXq16QRwdqGsx+nCU9YH+mcYgcvOrKwsIyUlxVi2bJnfcrZs2WIcPHjQuO6664yrrrrK2Ldvn3ea999/3+jQoYPx1Vdf+SzvrbfeMlJSUoxvvvmmynTa7Xajd+/expAhQ3zK4sWLFxspKSnG6NGjvcNqW14fPnzYSElJMZ5//nm/9QXa7hUrVhgpKSl+6QfOBGfVE/KdO3dq7dq1Sk9Pl8vlkmEYdV7WBx98oN///vcaO3as7rvvPhUVFenrr79WWVlZPaYYZ7vKnZu1bNlSTz/9tM4991xJ7mboGzdu1JQpU1RYWOgz7WWXXabMzEzl5OSoefPmstls3nFOp1P5+fmKiopS27Zt9cMPPwSdtrVr16pbt25KS0vzDktMTNQNN9ygN99802faiIgI79+FhYWy2+3q0aOHFi9erOzsbHXo0KHadYWGhio0NFSS5HK5lJ+fL5fLpS5dutQp7QDOXJT1ON3MmDFDbdu29Rtesex0OBwqLCxUq1atFBcXpx9++EE33nijz/Q5OTl64IEHJElvvPGGT8u31atXq127dkpOTvZ5Gn/JJZdIkjZt2qSLLrooYPq+//57HT58WFOmTPG5lxg6dKjmzJnjM219lNcVt7usrExFRUVKT0+XJG3dutX7+h5wpjirAvL+/ftrwIABkqRp06bp+++/r9Nyjh07pscee0wPP/ywbr31Vu/wq666ql7SCXh4CumCggK99957+uqrr3wKw59++kmGYei5557Tc889F3AZhw8fVvPmzeVyufT666/rzTff1L59+3ze305ISAg6bQcOHPAWkBUFuqnYuXOn/vKXv2jjxo1+FQcFBQW1Wt+yZcu0YMEC7d69Ww6Hwzu8cs+0AM5ulPU43aSlpQXs1K20tFTz5s3T0qVLlZOT41O5FKjsfPDBB2W1WrVy5UolJSX5jNu7d6927drlfXe7ssOHD1eZvgMHDkiSWrdu7TM8LCxMF1xwgd/0J1teHzt2THPnztXKlSv90lXbewbgdHJWBeQhITX3YWcYhhYsWKAlS5Zo//79at68uW677TafJ5WrVq2Sy+XS8OHDT2FqAd9CesCAAbr11lv1u9/9TqtXr1Z0dLS3A7WxY8fq8ssvD7iMVq1aSZJefvllPffcc7rpppt07733Kj4+XiEhIXriiSdO6glSTfLz8zV69GjFxMRoypQpatWqlcLDw7V161Y988wzATuBq+yDDz7QtGnTNGDAAI0bN05NmzZVaGio5s2b59fBHYCzG2U9zhSPP/64li5dqjFjxqhbt26KjY2VxWLR/fffH7Dc/s1vfqP3339fr7/+un73u9/5jHO5XEpJSfH20VKZp+XdyaqP8vq+++5TVlaWxo0bp44dOyoqKkoul0vjx48/pfcrgFnOqoC8Nv74xz/qnXfe0aRJk5Senq5vv/1WzzzzjMLDw3XLLbdIkjZv3qy2bdvq/fff10svvaScnBy1b99eU6dO1RVXXGHyFuBMFRoaqqlTp+r222/XG2+8oQkTJnhrpsPCwnTppZdWO//HH3+sXr166YknnvAZnp+fryZNmgSdnhYtWmjv3r1+w3fv3u3z+9///re3trtnz57e4YF6ia2qo5aPP/5YF1xwgebOneszzfPPPx90ugGAsh6ng48//lg33nijpk2b5h1WVlZW5VPi0aNHq1WrVnr++ecVGxurCRMmeMe1atVK27ZtU+/evYPuFK1FixaS3E/ZKz5hdzgc2rdvn89rZ7Utr6tKQ15enr788kvdc889uvvuu73D9+zZE1SagdMJnz2r4KefftLf//53Pfzww/rtb3+rSy+9VHfffbfuuOMOvfDCC94nebm5udq9e7eee+453XvvvXrllVfUsmVL/e///q927txp8lbgTNarVy+lpaXptddeU1lZmZo2baqLL75Yixcv1sGDB/2mr/ieWGhoqF/N8qpVq5STk1OntFxxxRX67rvvtGXLFp/1LV++3Gc6z9Oqiuu22+1+75lLUmRkZMAbDc/7aBWXsXnzZn333Xd1SjuAsxdlPU4XnrKvokWLFvm8clbZ5MmTNXbsWD377LM+5eygQYOUk5OjJUuW+M1TWlqq4uLiKpfZpUsXJSYm6u233/b5RNqyZcuUn58fMM01ldeeHuKrmr+y1157rcr0Aac7npBXsGHDBknuJj/l5eXe4ZdeeqleeeUV/fLLL2rZsqUMw1BxcbGeeeYZ77tkF198sa6++mq98sorfh1cAPVp3Lhxuvfee7V06VLdcsst+sMf/qBbb71VN9xwg0aOHKkLLrhAhw4d0nfffadff/1VH374oSSpX79+euGFFzR9+nRlZGRox44dWr58ecD3v2pj/Pjx+uCDDzR+/Hjdfvvt3s+etWjRQtu3b/dOl5GRofj4eE2bNk233XabLBaLPvjgg4DNzjp37qyVK1fqySefVNeuXRUVFaX+/furX79++sc//qHJkyerX79+2rdvn95++21deOGF1d5EAEBllPU4XfTr108ffPCBYmJidOGFF+q7777Thg0bauz35aGHHlJhYaEee+wxRUdHa8iQIRoyZIhWrVqlP/zhD94O3JxOp7Kzs7V69Wq9+uqrAd9jl9yt8O677z7NmDFDY8aM0bXXXqt9+/Zp6dKlfvcQtS2vIyIidOGFF2rVqlVq06aNEhIS1L59e6WkpKhnz5569dVX5XA41Lx5c61fv75W314HTlcE5BUcPXpUhmF4e5yszFNIe74BXXG6sLAw9ezZk1pznHK/+c1v1KpVKy1YsEAjR47UhRdeqPfee09z587VsmXLdOzYMSUmJqpTp06aPHmyd75JkyappKREy5cv18qVK9WpUyfNmzdPzz77bJ3S0axZM73++uuaNWuW/vrXvyohIUGjRo1Ss2bN9Pvf/947XZMmTfTyyy/rqaee0l/+8hfFxcVp8ODB6t27t8aNG+ezzFtvvVU//vijli5dqoULF6ply5bq37+/hg0b5v1u+hdffKELL7xQTz/9tFavXq1///vfdduRAM5KlPU4Xfz+979XSEiIli9frrKyMl100UX629/+pvHjx9c478yZM1VcXKyHH35Y0dHRGjBggF544QUtXLhQH3zwgdasWaPIyEidf/75uu222wJ2yFrRzTffLKfTqfnz52vOnDlKSUnRSy+95NehbDDl9axZs/T444/rySeflMPh0N13362UlBQ9++yzevzxx/Xmm2/KMAz16dNHr7zySpV95QCnO4txlvaO4Ol5dcWKFd5hb775ph577DG9+eabCgsL85unbdu2iomJ0dy5c5WZmalvv/1W0dHR3vEPPfSQvv/+e3300UcNsg0AAKBqlPUAgMaOd8gr8HRUcezYMXXt2tXvX0xMjCTpyiuvlCR9+eWX3nntdru++uorde7cueETDgAAaoWyHgDQmJxVTdZLSkq0du1aSdL+/ftVWFio1atXS3K/F9a2bVv9z//8j/7v//5P48aNU3p6uhwOh/bs2aNNmzbpxRdflOR+z/Xqq6/W//t//0/Hjh1TUlKS3nzzTR06dMivCS4AAGg4lPUAgNPJWdVkfd++fd6OWSp7/fXX1atXLxmGoTfeeEOLFy/W7t27FR0drbZt2+qaa67x+T5pcXGx/vSnP+mjjz5SYWGhOnfurAcffFDdu3dvoK0B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E0+ooKBAsbGxuuSSSzRlyhRvD+uSFBYWpldffVWzZs3S1KlTZbVaNXDgQD388MN13T4AAAAAABqloAPy888/3+/74ZV5elD36Natm9+wqjRv3lyZmZnBJgsAAAAAgNNKo+rUDQAAAACAswUBOQAAAAAAJiAgBwAAAADABATkAAAAAACYgIAcAAAAAAATEJADAAAAAGACAnIAAAAAAExAQA4AAAAAgAkIyAEAAAAAMAEBOQAAAAAAJiAgBwAAAADABATkAAAAAACYgIAcAADUya5du3TnnXeqW7du6tOnj+bMmSO73V7jfEePHtWMGTPUr18/devWTddff73eeuutBkgxAACNi9XsBAAAgNNPXl6exowZozZt2igzM1M5OTmaPXu2SktLNWPGjGrnvffee5Wdna2pU6fqvPPO07p16/Too48qNDRUI0eObKAtAADAfATkAAAgaG+//baKioo0d+5cJSQkSJKcTqdmzpypiRMnqnnz5gHny83N1aZNm/Tkk09q2LBhkqTevXvrP//5jz766CMCcgDAWYUm6wAAIGjr1q1T7969vcG4JA0aNEgul0vr16+vcr7y8nJJUmxsrM/wmJgYGYZxStIKAEBjRUAOAACClp2dreTkZJ9hcXFxSkpKUnZ2dpXznXfeebrsssv08ssv67///a8KCwu1cuVKrV+/Xv/zP/9zqpMNAECjQpN1AAAQtPz8fMXFxfkNj4+PV15eXrXzZmZm6v7779d1110nSQoNDdUjjzyiq6+++pSkFQCAxoqAHAAANBjDMDR9+nTt2bNHzz77rJKSkrRhwwY98cQTio+P9wbpAACcDQjIAQBA0OLi4lRQUOA3PC8vT/Hx8VXO9/nnn2v16tX68MMPlZqaKknq1auXDh8+rNmzZxOQAwDOKrxDDgAAgpacnOz3rnhBQYFyc3P93i2v6L///a9CQ0OVkpLiM7xjx446ePCgSkpKTkl6AQBojAjIAQBA0Pr27asNGzYoPz/fO2z16tUKCQlRnz59qpyvZcuWcjqd2r59u8/wrVu3qmnTpoqMjDxlaQYAoLEhIAcAAEEbNWqUoqOjNXnyZH3xxRd67733NGfOHI0aNcrnG+RjxozRwIEDvb/79u2rFi1aaMqUKfrggw/05Zdf6umnn9ayZcs0evRoMzYFAADT8A45AAAIWnx8vF577TU9/vjjmjx5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dch1PuPTbNRDAzfgqUNu73GJY85Th9ze45TXct51yKXxajHp5brmZqPXHiZAHXIphtKaSaxD3je/2Xsd6Op2yWPee242GXSAVIfc01+TQVz39zid8vpIut8sJj0EtyCuD+399xo6GKO1Dnl8fDx27tyJ559/HqWlpYiNjUVRURHWrFnj8zq32w2Xy+VzrLi4GIIg4PXXX8e1a9eQlZWFyspKn8RrMBjw2muvYcuWLVi7di30ej3mz5+PDRs2hNLMiBjKJDa0T7nH3mhTKATjA/+FSlRJSRpabcPxyRFuSITcyAJg/DC2I5hbvGpL3oLI1pmk4XFLIufRaBDpNYESRktd+aR+ue+WYcyFt4RZj3ck5vNQjOd8P+yidfyoLWcM33qP97hahPQbcjUaDb+FICKi0YW5aXjxehIRUbSJSB1yIiIiIiIiIhoe3JATERERERERKYAbciIiIiIiIiIFcENOREREREREpABuyImIiIiIiIgUwA05ERERERERkQK4ISciIiIiIiJSADfkRERERERERArghpyIiIiIiIhIAdyQExERERERESmAG3IiIiIiIiIiBXBDTkRERERERKQAbsiJiIiIiIiIFKBXugGRduXKFbhcLsybN0/pphAREQEALl26BJ1Op3QzRg3meiIiijZDzfWj/jfkJpMJev2o/3cHIiJSEb1eD5PJpHQzRg3meiIiijZDzfUaQRCEEWgPEREREREREXkZ9b8hJyIiIiIiIopG3JATERERERERKYAbciIiIiIiIiIFcENOREREREREpABuyImIiIiIiIgUwA05ERERERERkQK4ISciIiIiIiJSADfkRERERERERArghpyIiIiIiIhIAdyQExERERERESmAG3IiIiIiIiIiBeiVbgCJPvnkE/z1r39FbW0tLly4gEceeQQbN24c0rkdHR144YUX8Pe//x0OhwNz5sxBWVkZkpOTI9zq0Hz00UcoLy9HQ0MDUlJSsGrVKixZsmTAcy5evIh58+b5Hc/JycGePXsi1dQB1dXVYcuWLTh9+jRiY2OxaNEirF69GkajccDzBEHAq6++irfeegvXrl1DVlYWnnvuOeTm5o5Mw0MQbh/vuusuNDc3+x3/7LPPYDKZItXckDU2NqKyshK1tbU4d+4c0tPTUVVVNeh5aolhuP1TS/wOHjyIvXv34uzZs2hvb8e3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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tab_eval.visual_evaluation()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "e61a66de", + "metadata": {}, + "outputs": [], + "source": [ + "tab_eval = TabularMetrics(original_tabular_data, \n", + " random_tabular_data, \n", + " categorical_columns=categorical_features)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "fff90a49", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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585NVZjBiwP8cePGYWdnx8SJEzExMeH+/fucO3cu05xfffUV27dvp0uXLowcOZJLly6xcOFC7ty5w/z583UZM9pGZiQ8PJyxY8fSo0cPevXqRYUKFdBqtbz//vucPXuWgQMHUrduXW7evMnKlSsJCAjgzz//1I2f021vRrIzvfv37zNp0iTefvtt+vbty9atW5kyZQqNGzemfv36ADx79ozhw4eTnJyMp6cn5ubmbNq0KUstQd577z1sbW3ZuHEjEydOxNraWvc3z8r2Oz2XLl1izJgx2Nvb8+eff2JmZpblfXxGvvzyS/766y969uxJs2bN8PHxwdPTM81wly9f5vz58/To0YOqVasSFBTE+vXrGT58OLt378bc3JyWLVvi4eHB6tWree+996hTpw6A7v7w7ByHiRxQhPh/W7duVdRqtXLp0iVlzZo1ipOTkxIXF6coiqJMnDhR8fDwUBRFUTp06KB4enrqxjt9+rSiVquVv/76K9X0jh8/nqZ7yvRe9vXXXyuOjo5KQkKCrtuwYcMUtVqtbN++XdctISFBad26tTJhwgRdt/fff1/p0aNHtud1xYoVilqtVnbu3KnrptFolEGDBilNmzZVoqKidN1fnd/XUavVSoMGDZRbt26l6v7FF18orVu3VkJDQ1N1//jjj5XmzZvrlktSUlKq5aAoihIREaG0atVKmTp1aprvmjNnzmvzZHV6gYGBilqtVpydnZXw8HBd94MHDypqtVo5fPiwrlvv3r2V1q1bK5GRkbpuJ0+eVNRqtdKhQ4fX5lEURZk8ebLStGnTNN3TWzdGjRqldOzYMVW3l/8eK1euVOzs7JT58+fr+mu1WuXNN99URo0apWi12lTTd3d3V0aOHPnafCnrxp49e3TdYmNjlc6dOytqtVrx8fF5beaFCxcqdnZ2SlBQkK7bjBkzFLVane73vToNjUaj9OzZUxk+fPhrcwohXjh58qTSsGFDpWHDhsqgQYOUH3/8UTlx4oSi0WjSDNu0aVNl8uTJabp/8MEHSpMmTVL9bm/fvq00bNgw1W93+fLlilqtVkJCQrKV0d/fX1Gr1cqXX36Zqvv333+vqNVqxdvbW9cto21kelL2levXr0/VfceOHUqDBg2U06dPp+q+fv16Ra1WK2fPntV1y+q2d9iwYcqwYcMyzZSdbblarU6VMSQkRLG3t1e+//57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+D179oSLiwv2798vyvGJyDLwOmYevvvuOzRt2hTBwcGiHH/w4ME4f/487t27J8rxqWYxsSLRFY8Xv3XrFt5880107doV//jHP3SPf//99xg1ahQ6dOiAbt264Y033sCDBw/0XuPcuXOYM2cOnn76abRr1w5PPfUUPvzwQ6hUqirHtWvXLgwYMAAdOnTA6NGjce7cuVL7qNVqrFy5EqNGjULnzp0RHByMf/zjHzh9+rRun6SkJISGhgIA1qxZg8DAQL2x33FxcZg3bx769++P9u3bo1evXpg/fz4eP35sMMaYmBgEBgbi4MGDWLNmDfr06YOQkBDMmTMHCoUCarUa//rXvxAaGoqQkBDMnz8farW61OvUZBvPmzcPISEhSElJwaxZsxASEoIePXrgk08+gUajMXhOR44cgbW1Nbp06WJwXwD45ptvMHToULRr1w69e/fG4sWLy7yr+c0336B///56v8+yxtBbW1ujW7duHJpBREbjdazq1zEA2LZtG4YOHYqOHTuia9euGDVqFH788UcARW27fPlyAED//v11xy6eb6tWq/Hhhx+iR48eCAkJwcyZM/Hw4UOj2+i3335Djx49IJFIDO6bnp6Od999Fz179kT79u0xfPjwMm/CPX78GG+//TY6deqELl264J133kFcXBwCAwOxb98+vX179uypi4PMn5XYARAVe+211+Dj44M33ngDgiAAAL788kusXLkSgwcPxujRo5GRkYHt27fjpZdewoEDB+Ds7AwAiIqKgkqlwosvvghXV1dcvnwZ27dvx8OHD6s0X2bPnj1YuHAhQkJCEB4ejnv37uGVV16Bi4sLmjRpotsvJycHe/bswbBhwzBmzBjk5uZi7969mDZtGvbs2YOgoCC4u7tj0aJFWLRoEQYOHIiBAwcCgG7y8alTp3Dv3j2MGjUKnp6euHnzJnbv3o1bt25h9+7dRn3Yr1u3Dra2toiIiEBiYiK2b98OKysrSCQSZGdn49VXX0VsbCz27dsHLy8vvPrqq7rn1kYbazQaTJ06FR06dMA///lPREdH4+uvv4a3t7fel42yXLx4EQEBAbC2tjZ43qtXr8aaNWvQs2dPvPjii7hz5w527NiBv/76Czt27NC9xrfffoslS5agS5cumDx5MpKTkxEZGQlnZ2c0bty41Ou2bdsWv/32G3JycuDo6GgwDiIigNex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Wvz222+wt7fHhx9+CDc3N/z444/47bff0L17d6xbt043asGQF154Adu3b8f58+crXJje1tYW27Ztw6effor9+/cjJycHLVq0wEcffYRRo0bp9iuen/avf/0L+/fvh1QqxcCBAxEZGYkXX3yx1DUnKioKnTt3rrC4BZkPicDyV0RkYg4cOIAlS5bg6NGjRpXBrQqtVovQ0FAMHDgQy5Yt022fNWsWJBKJ7gsQERFZtvDwcDRs2BArVqyotWMcOXIEkZGR+Pbbb3UVD9PS0tC/f3/8+9//xoABA2rt2FR3OMeKiEzO8OHD0bRp03LHpFdWfn5+qfkNBw4cQGZmJrp166bbdvv2bRw9ehSvvfZajRyXiIhM39y5c/HLL7/olumoLpVKpfezRqPBtm3b4OjoqBvWCBTNBQsICGBSZUHYY0VEFi8mJgYfffQRnn32Wbi6uuLq1avYu3cv/P398d133+ktoElERFQd7733HlQqFUJCQqBWq3H48GFcvHgRc+fOxYwZM8QOj2oR51gRkcXz8vJC48aNsW3bNmRlZcHFxQUjRozAW2+9xaSKiIhqVI8ePbBp0yYcPXoU+fn58PHxwfvvv48JEyaIHRrVMvZYERERERERVRPnWBEREREREVUTEysiIiIiIqJqYmJFRERERERUTUysiIiIiIiIqomJFRERERERUTUxsSIiIiIiIqomJlZERERERETVxMSKiIiIiIiomv4PoH19ThBdYXsAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABi8AABsCCAYAAABFeYczAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd3xUZdrG8WtSSQgQ6R2Mi4gU6QiirCAioKKwUu1dxL5LMXZEdBUbNlw7WFBpoq6soiICggUVpIjGgEDonQRSmPcP3kRCEjJz5pk558z5fT+f93VJ5n7mOknm3DB3znN8fr/fLwAAAAAAAAAAAIeIsTsAAAAAAAAAAADAkRheAAAAAAAAAAAAR2F4AQAAAAAAAAAAHIXhBQAAAAAAAAAAcBSGFwAAAAAAAAAAwFEYXgAAAAAAAAAAAEdheAEAAAAAAAAAAByF4QUAAAAAAAAAAHAUhhcAAAAAAAAAAMBR4uwOAAAAAPMWLFigDz/8UD/88IO2bt2q3NxcpaamqkmTJurWrZvOP/98Va1a1e6Yxk2cOFHPPPOMRowYoZtuuikiz9m9e3dt2LBBc+fOVf369SPynMHasmWL3njjDc2fP1/r1q1TXl6eUlNTVb16dbVo0UJt27ZVv379FBsba3dUlGHatGl68803lZGRoZycHEly9M8cAAAAECqGFwAAAFFkx44duuOOO7Rw4UJJUr169dSpUyclJydr69atWrp0qRYuXKinnnpKr732mk455RSbEzvb6NGjNWPGDI0fP179+/e3O44lP/zwg6677jrt2bNHycnJatWqlapXr679+/fr119/1Xvvvaf33ntPvXr1UsWKFe2Oi1J8+eWXuvPOO5WYmKguXbooNTVVkpScnBzxLG4Y1gEAACA6MLwAAACIEnv37tXQoUP1xx9/KC0tTWPHjlX79u2LPSY3N1czZszQxIkTtXXrVpuSRpfXXntNeXl5qlWrlt1RSsjNzdWtt96qPXv26Nxzz9X999+vlJSUYo/5/fffNW3aNK66cLBPPvlEknTXXXdp4MCBNqcBAAAAIoPhBQAAQJQYO3as/vjjD9WrV09vv/120W9nHykhIUGDBg1Sjx49tGfPnsiHjEINGza0O0KZvv/+e23evFlxcXEaO3Zsqb+pf8IJJ2jkyJE2pEOgNm7cKElq1KiRzUkAAACAyOGG3QAAAFHgzz//1IcffihJGjNmTKmDiyNVr15daWlpRX8ePXq0mjZtqunTp5f6+OnTp6tp06YaPXp0mR/fu3evxo8fr+7du6tly5Y6++yz9eKLL+rQoUOSpM2bN+uee+5Rt27d1KJFC/Xq1UuTJ08u9fm6d++upk2bav369aV+vry8R8vLy9OsWbN0xx136JxzzlHbtm3VqlUr9erVSw8++KA2b95c7PHr169X06ZNNWPGDEmHv6ZNmzYt+r+JEyeWmbWgoEBnnHGGmjZtqh9//LHMTI888oiaNm2qhx56qMTnFi1apBEjRqhr165q0aKFOnfurBtvvFFLly4N6HgLbdu2TdLh7YWC3WLI6vfgyI9nZGTo1ltvVefOndW6dWsNGDBAn332WdFjf/rpJ11//fU69dRT1apVKw0aNEiLFi0q9fkyMzM1ZswYde/eXS1atFCbNm105pln6tprr9W0adMCPq7FixeradOmuuSSS5STk6PHH39cPXv2VMuWLdW1a1fdeeedJX4ejrR79249/fTT6tevn9q0aaNTTjlF5513np577rmie1EcaeLEiUU/Mxs3btSdd96pbt26qXnz5iVeT0cr/FouXrxYknTppZcW/QweXbt582aNHz9evXv31imnnKI2bdpowIABmjJlivLz80usvWPHDr3xxhu65ppr1L17d7Vq1Upt27ZV//799eKLL+rgwYPFHl/4Wt+wYYMkqUePHsVeE4UZyzpXFCp8bXXv3r3MjxcUFOjVV1/VBRdcoDZt2qhp06bFHvvHH3/onnvu0VlnnaWWLVuqXbt2GjZsmGbNmnXMrycAAADchSsvAAAAosAXX3yhgoICVa5cucSbgpGwZ88eDRo0SLt27VL79u21f/9+fffdd5owYYI2b96syy67TEOHDlVcXJzatGmjHTt26LvvvtODDz6onJwcXXvttWHNt337do0cOVKVKlXSCSecoKZNmyonJ0crV67U5MmT9dFHH+mdd94p+s325ORkXXjhhfr++++1bt06tW3btthvvTdr1qzM54qNjdUFF1ygSZMmafr06WrdunWJx+Tn5+uDDz6QJA0YMKDY5x555BG98soriomJUYsWLdSuXTtlZWVp7ty5+uKLLzR27NgSNWWpU6eOpMPfn+nTp0f0vh0rVqzQ2LFjVatWLXXu3FkbN27U0qVLNWLECD355JOKi4vTrbfeqiZNmqhz587KyMjQjz/+qKuvvlqvv/56sS3Pfv31Vw0ZMkT79u3T8ccfrzPPPFMxMTHavHmzvv32W23evDngr0mhvLw8XX755Vq9erU6duyok08+Wd9//72mTZumr776SlOmTFHjxo2L1fz222+6+uqrlZWVpRo1aqhdu3aKi4vTsmXL9NRTT+l///ufJk+erEqVKpV4vszMTF144YWKj49X27Zt5ff7ddxxxx0zY7t27SRJ8+fP17Zt29S1a1fVqFGj2Ock6dtvv9WNN96o3bt3q169eurSpYtyc3O1bNkyjR07Vl988YVeeOEFxcfHF9XMnz9f48aNU61atdSoUSO1bt1aO3bs0E8//aQJEybo888/1xtvvKGEhARJh68wuvDCCzVnzhxlZ2erV69exQZi1atXD+rrXxa/368RI0Zo/vz5at++vU444QStWbOm6PP//e9/NWrUKB08eFBpaWnq1q2b9u7dq59//lkjR47UN998o/HjxxvJAgAAAHsxvAAAAIgCy5cvlySdfPLJtty7YO7cuTrzzDM1bdo0JSUlSZJ++eUXDRw4UG+99Za++eYb9ejRQ3fffbfi4g7/FfSzzz7TjTfeqEmTJumSSy4pqguHlJQUPffcczr99NOL3oyVDr+BPXHiRE2aNEnjxo3Tiy++KEmqWrWqHn74YY0ePVrr1q3TRRddFNQb//3799ekSZP03//+V+np6UpMTCz2+Xnz5mnbtm1q3rx5sd8qf/fdd/XKK6+oUaNGevrpp3XSSScVfe7bb7/Vddddp3vvvVft2rUr8cZ6adq2bauTTz5ZK1as0JgxY/TWW2/ptNNOU8uWLdWiRQvVrl074GMK1uTJk3Xrrbfq+uuvl8/nK/rYgw8+qPHjxysnJ0cPPvigLrjggqKahx56SK+//rqeffZZvfrqq0Uff/XVV7Vv3z7deuutuuGGG4o9z4EDB7Rs2bKg8y1dulSNGjXSxx9/rLp160qSDh48qH/961+aM2eORo0apalTpxZ7nhtuuEFZWVm64YYbNHz48KKfpZycHN1111368MMP9dBDD5X65vmHH36o888/X+PGjSv2M3gsF110kS666CJdcskl2rZtm6699lp16tSp2GO2bt2qESNGaM+ePbr33ns1ePBgxcQcvsB+586duvXWW/X1119r0qRJGjFiRFFdixYtNHXq1BLDtd27d+v222/X119/rTfeeENXX321JKl9+/Zq3769lixZouzsbI0cOTIsN+zeuHGjDh06pNmzZ+v4448v9rnVq1dr5MiR8vl8mjhxos4+++yiz23YsEHXX3+9pk+frk6dOhX7uQIAAIA7sW0UAABAFNixY4ckqVq1arY8f3JyssaNG1dsANG8eXOdccYZOnTokLKzs3XnnXcWDS4k6ayzztKJJ56offv2FQ1fwiUlJUU9evQo8aZxfHy8br/9dtWsWVPz58/Xvn37jDxf48aN1b59e+3Zs0effvppic8XbrV05NUChw4dKtqO6vHHHy82uJCkDh06aPjw4crLyyv2pvqxxMTEaNKkSTrjjDMkScuWLdMLL7ygG2+8Ud26dVOvXr304osv6sCBA5aO81hatWpVbHAhSUOGDFFqaqo2bdqkzp07l3iDuXAw8e233yovL6/o49u3b5ckdevWrcTzVKhQQR06dLCUceTIkUWDC0lKTEzUvffeq6SkJP3444/64Ycfij43Y8YMrVu3TmeeeaZuvfXWYj9LSUlJeuCBB1StWjV98MEH2r17d4nnSk1N1T333BPw4CJQr7/+unbt2qVhw4Zp6NChRYMLSTruuOP073//W/Hx8XrzzTfl9/uLPnfCCSeUelVQlSpVdNddd0n660bhkXbbbbeVGFxI0gsvvFB0E/ojBxeSVK9ePY0bN06S9MYbb0QkJwAAAMKLKy8AAAAQshYtWpQ6OCm8OqBTp04lrj4o/Pyvv/6qLVu2hDuiJGnVqlVatGiR1q9fr+zs7KI3cwsKCnTo0CGtW7dOJ598spHn6t+/v7777jvNmDFD5557btHHd+zYoXnz5ikhIaHYx1esWKEtW7aoYcOGatGiRalrduzYUZKCuvdFzZo19Z///Edr1qzR559/rqVLl2rFihXavHmzMjMzNWHCBH300UeaPHmyKleubPFoSzrjjDOKDS4kKS4uTvXq1dOuXbtKHUQcd9xxSk1N1a5du7Rr166iLZJatWqlefPm6b777tNNN92kjh07lvrzFIzKlSurR48eJT5erVo1nX766frf//6nJUuWqG3btpIOXy0jSb179y51vYoVK6pFixaaN2+eli1bpq5duxb7fOfOnUvdTipU5eUq3Bbqt99+U2ZmZrGhQEFBgZYsWaIffvhBW7du1cGDB+X3+4teF3/88YfxvIHo1atXiY8dOnRIX331lSSpT58+pda1bNlSycnJWrlypQ4ePBjyzwgAAADsxfACAAAgClStWlXSX7+hHmmF91Y4WuGe+GV9vmLFipJU4ubAphVuc1PaVRBHMnXlhXT4zeQHH3xQCxcu1KZNm4q2aPrggw+Ul5enPn36qEqVKkWP//PPPyVJ69atK3GD4qMVXmkTjCZNmqhJkyZFf/7999/11ltv6c0339SqVav0xBNP6N577w163bKU9z0/1ud37dpV7Gfiqquu0vfff6+FCxfq6quvVnx8vJo2baoOHTqoT58+atWqVdD56tWrV2K4UqhwO6RNmzYVfazw+zNy5EiNHDnymGuX9v2pV69e0BkDUZhr2LBh5T52x44dRcOLzMxMjRgxotj9JI5m8vUQqGrVqpW6hdyuXbuK8pQ2+Crt8bVq1TKeDwAAAJHD8AIAACAKNG/eXLNmzdKKFStUUFBg/L4Xhw4dOubnj9yqxsrng1VenqM9/vjj+vTTT5WWlqY77rhDLVu21HHHHVe0hc/gwYO1dOnSYtvqhCo5OVm9e/fWtGnTNHPmTF1//fWS/toy6uh7aBQ+d40aNUr81v7RyrvRcyBOOOEE3X333fL5fJo8ebI+++yzoIYXkfyZSEpK0quvvqqff/5Z8+fP19KlS7V06VItX75cr776qoYOHWp08FLoyJ+HwuM9/fTTy7059ZFbURWqUKGC2XBH5Tr6BtqlSU1NLfrfN998s9asWaMzzzxTV199tU444QSlpKQoPj5eubm5atmyZVjylvcaK+vrdOTP24UXXlju8xx5c3IAAAC4E8MLAACAKHDmmWfq4Ycf1p49e/T555+rZ8+eQdUXvtG3f//+Uj+/cePGkDMGw3Se//73v5KkJ554osS9JKTDv4UeDv3799e0adM0Y8YMXX/99frll1+0evVq1a5dW6eddlqxxxZemZGamqqHH344LHlK07VrV02ePFk7d+4s9nGn/UxIh7ePKrzKIj8/X5999plGjRqlt956S7169dKpp54a8FobNmwo93NH3tC8Tp06ysjI0D/+8Q+dc845Fo/AvDp16igzM1PXXHNNwAOH33//XatXr1a1atX0zDPPFLsXjSStXbvWcp7yfm6O9XU/luOOO04VKlTQgQMHNHLkyKKrzQAAABC9uGE3AABAFGjYsKH69u0rSXr44Ye1a9euYz5++/btysjIKPpz4fYqv//+e4nH+v3+or3mI6VmzZpl5tm6dat++eWXoNYrvIFyaVv3zJ8/v8Qb94UK34gtKCgI6vkKtW/fXo0bN1ZmZqa+//77oqsuLrjgghJXHhReDfLbb78dcyufYARyJUnhEOLIN+ol898D0+Li4nTOOecUXaWyatWqoOoLB31H27Fjh+bPny/pr3uMSCq66XnhIMwpTj/9dEnB5Sp8PdSsWbPE4EI6vLVZWcp7TRSeS448vxyp8B4dwYqNjVWXLl0kOe97AAAAgPBgeAEAABAl7r77bjVq1Ejr16/X0KFD9d1335V4TG5urt5//31dcMEFxd5c7Ny5syRp1qxZ+u2334o+npeXp0cffVTLli0L/wEcofBNypdeekl79uwp+viOHTs0atQoZWdnB7VeWlqaJGny5MnFPp6RkXHM7YYK34gNZZgwYMAASdI777yjDz/8UFLJLaOkw28KjxgxQn6/XyNGjCj1+1dQUKBFixbpxx9/DOi5P//8cw0fPlwLFiwo9c3mxYsX65lnnpGkouFXIdPfg1C8+eabpb4ZvnXrVi1fvlxS6Vs1leeRRx4pdl+L3Nxc3X///crOzlarVq3Url27os8NHDhQ9erV0yeffKJHH3201PtBbN26Ve+++27QOUJx9dVXq3Llynrttdf0yiuvKDc3t8Rj/vzzT82aNavoz40bN1ZsbKx+/fVXLV68uNhjP//8c7322mtlPl95r4lWrVopJSVFv/32m2bOnFnsc//9739LvAaDMWLECMXHx+vRRx/VjBkzSt267Ndff9X//vc/y88BAAAA52DbKAAAgChRpUoVvf3227r11lu1ZMkSDRs2TPXr11fTpk2VlJSkbdu26eeff1Z2drZSUlKKfrNektq1a6cePXpo7ty5GjBggNq1a6fExEStWLFC+/bt06WXXqo33ngjYscybNgwvffee/rll190zjnnqHXr1srJydGyZctUp04dnXXWWfrss88CXm/EiBG6+eab9dRTT+m///2vmjRpou3bt+v7779Xu3btVLNmTS1durRE3VlnnaVnn31WkydP1po1a1S7dm3FxMSoe/fu6tGjR0DP3a9fPz355JNFv83eoUMHNWrUqNTHXnzxxdq4caNefvllDRs2TE2aNFHDhg1VoUIFbd26VatWrdKePXt03333qXXr1uU+t9/v19y5czV37lxVqlRJJ598smrUqKHs7GxlZmYWDQS6dOlSdE+OQqa/B6F499139cADD6h+/fpq0qSJUlJStHPnTn333Xc6cOCATj31VHXv3j2oNdu0aaNDhw7pnHPO0amnnqoKFSro+++/15YtW1StWjU98sgjxR6fnJysSZMm6brrrtNLL72kd999V02bNlWtWrV04MABZWZm6vfff1e1atU0cOBAk4d/TLVr19Zzzz2nm266SY888oheeuklNWnSRDVq1NC+ffv0+++/a926dTrllFPUr18/SVLVqlU1bNgwvfHGG7r88svVvn171axZU3/88Yd++eUX3XDDDXr++edLfb5evXpp8eLF+te//qWuXbuqcuXKkg7fVD0tLU0VKlTQTTfdpPHjx2vUqFF65513VLNmTWVkZOi3337TDTfcoOeee87SsTZv3lyPPvqoxowZo9GjR+vJJ5/U3/72Nx133HHavXu3fv31V23atEl9+vTR2Wefbe0LCgAAAMdgeAEAABBFqlWrpsmTJ+urr77SRx99pKVLl2rRokXKy8tTamqq2rRpo27duqlfv37Fbt4rSU8++aSee+45ffjhh1qyZIkqV66szp0765Zbbin1KoBwqly5st5++209/vjjmj9/vr766ivVqlVLAwcO1I033qixY8cGtd7ZZ5+tKVOm6JlnntGqVav0559/qkGDBhoxYoSuvPJKXXXVVaXWnXTSSZo4caJefvll/fTTT1q0aJH8fr9q164d8PCiVq1a6tq1a9F2OaVddXGkkSNH6qyzztJbb72lH374QfPnz1d8fLxq1Kihjh076u9//3vAb8yefvrpevnll7Vo0SL98MMPWr9+fdFVG9WqVdNZZ52lvn37qnfv3vL5fMVqTX8PQnHbbbfpyy+/1E8//aSffvpJe/fuVbVq1dSqVSsNGDBAffv2LXX7o2OJj4/XpEmT9Mwzz2jOnDnavHmzqlSpov79++vmm29WnTp1StQ0adJEH3zwgd555x199tlnWr16tX788Uelpqaqdu3auvLKK4O+34wJHTp00EcffaQpU6Zo3rx5WrZsmXJzc1WtWjXVqVNH559/fomfmTvvvFNNmzbVW2+9peXLlys2NlYnnniinnjiCfXp06fM4cWQIUO0f/9+ffDBB5o3b54OHjwoSTr//POLrnC6/PLL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Xr16qXfv3pKkt99+u/xS/27duun+++9XXFycLeqbOXOm3nzzTTkcDrndbl1wwQX629/+JsMwglrbvffeqy+++EK7d+9WSkqKkpKStHDhQtssO0/qs2rZSdL27dt19tlnq2XLlkpKSpJUehXDO++8o8cee0xNmjTRiBEjJEmLFi3SQw89JLfbreOOO07/+te/yr+tb3V9n376qR5//HHFxMTI7XarR48eGj9+vJxOZ1Dr27p1q26++WYdPnxYhmEoNTVV48ePV2Zmpi3WQU/rs3IdhP9q2keHWk37u9rq8/W9QKptP7N7927deeedys7OVlxcnO655x716NFDknx+L1Bq277tvszLjBo1SldddZX69Olj62W9ZcsWjRs3rvyWzy1atNDEiRPVokUL2y/rLVu26B//+If2798vwzB04403qm/fvravG4EXKb+7cM0aX4VrRvkqErLNH+GSi+GE5gUAAAAAAAAAALAVbhsFAAAAAAAAAABsheYFAAAAAAAAAACwFZoXAAAAAAAAAADAVmheIGJlZ2erXbt2mjBhgtWlWGLOnDlq166d5syZY3UpAAAAAAAAAOCVWKsLAOzoiSee0JNPPlnj+71799bTTz8dwooAAAAAAAAAIHrQvEDEatq0qT7++GPVr1/f53H07dtXxx13XJXX27Zt609pAAAgim3atEkvvviifvrpJ23YsEFt27bVhx9+6PV4JkyYoLlz51b73m233aZrr73W31IBAAAAwDI0LxCx4uLidMwxx/g1jr59+2rAgAEBqggAgMCaM2eO7rrrLk2ZMkVDhgyxuhx4aMOGDfryyy918sknq6SkRKZp+jSesWPHavjw4ZVe+/jjj/Xqq6/qrLPOCkSpAMIImQAAACINzQtErOzsbPXu3VuDBw/W1KlTJUk7d+7Uc889p6+++krbt2+X0+lUWlqaunbtqjvuuMPrqzRGjRql5cuXa9WqVXr66af10UcfKScnR9dff73GjRun//3vf3rnnXe0dOlSbdu2Tfn5+crIyNB5552nG264QUlJSZXG16tXL0nS4sWLa5zWL7/8Uun1/fv3a/r06frss8+Ul5enY489Vtdff71X8wEAodSuXTuvhj9yvxdNqssyOzjyG/8Oh0NJSUlKS0tTZmamzjvvPPXq1UtOp7PGz9Qlkk++9erVS3369JFUulzWrFnj03hatWqlVq1aVXrt4Ycf1rHHHqsTTjjB7zqBUCATPGfXTKho69at6tOnj0pKSnTHHXdozJgxQZ9m2S1/X3vtNXXv3j3o0wMAK61Zs0b/+c9/tGLFCu3cuVMlJSVq0qSJTjnlFF188cU6/fTTJUl79uzRu+++q59//llr1qzR1q1bJUV3jiI80bxA1CgoKNCIESO0detWnX766erTp4+KioqUnZ2t999/X6NHj/b5FlPjxo3T+vXrdeaZZ6pBgwZq0aKFJGnhwoWaPXu2unfvrm7duqmkpEQ//fSTnn/+eX3//feaOXOm4uLi/JqnUaNG6ddff9Upp5yirl27KicnR7fcckt5YAGA3fztb3+r8tqrr76qQ4cOVfseanbeeefp5JNPVpMmTSyZ/iWXXKJmzZrJNE3l5uZq06ZN+vzzz/Xhhx/qmGOO0fTp08tPovfp00fNmzev9Pnly5dr+fLl6t27tzIzMyu9d+TPkSQmJqbOYUzT1EsvvaS3335bW7duVdOmTTVq1ChdffXVNX5mx44dWrFihW6++eYAVgsEF5kQOFZngiTNnj1bJSUlMgxDs2fPDknzAgCiQUlJif71r3/plVdeUWxsrHr06KFevXopNjZWW7Zs0Zdffqn3339fN910k2688Ub99ttvmj59ugzDUOvWrZWQkKCCggKrZwPwGs0LRI2lS5cqOztbV111lf7xj39Uei8vL6/aJsKCBQu0cePGKq9fe+21io+PL/95586dev/995WSklJpuEGDBunqq6+u9M1TSXryySf1xBNPaP78+Ro4cKDP8/TCCy/o119/1bBhw/TAAw9Umi4HCgDsaty4cVVemzt3rg4dOlTte6hZ/fr1/Xq2k78uvfRSderUqdJrubm5euKJJ/TKK69o9OjRmjNnjpo2bao+ffqUX21Q5oknntDy5cvVp0+fiL3KwleTJ0/WO++8o+uvv14nn3yyfvzxR02bNk3x8fEaMWJEtZ/58MMPVVJSwi0vEVbIhMCxOhNKSko0d+5cHXXUUTr33HM1Z84c/fjjj+rcubNlNQFApHj00Uf1yiuvKDMzU48//niVq28LCws1c+ZM7d+/X5J0zDHHaObMmcrMzFRycrIuuOAC/e9//7OgcsA/dX/tC4gw9erVq/JaUlJSlQaDVNq8ePLJJ6v87/Dhw5WGGzduXJXGhVT60PDqxnvFFVdIKm2o+OO9995TXFycbrrppkqvn3nmmTrttNP8GjcAWC07O1vt2rXThAkT9Pvvv+vGG29U9+7d1a5dO2VnZ0sqvcLt1ltvLf+2aZcuXTRy5EgtWLCg1vFt2rRJN954o7p27apOnTrp6quv1vr166t8JisrS3fddZd69eqlDh06qFu3bho4cKAmT55c6TkFa9as0aRJk3ThhReqS5cu6tixoy666CI999xzKioqqnb+9uzZo6lTp6pv377q2LGjunXrpksvvVQvvviipNJ7l/fu3VtS6Ym8du3alf9v2bJl5cO0a9dOc+bMqTL+H374Qddee626deumk046SRdccIEef/zxar9x1a5dO40aNUq7d+/W+PHj1b17d3Xs2FHDhg0rn5ankpOTddddd2nIkCHavXu3nnnmGa8+D2nz5s2aOXOm/vGPf+iGG25Qz5499be//U1XX321nnrqKZWUlFT7uQ8//FCnnHKKWrZsGeKKgeAjE+yfCUuWLNG2bds0YMAADR06VJL07rvvVjtsxVoXL16sSy+9VCeffLLOPPNMPfroo+X7ublz52rgwIHq2LGjzjnnHL3wwguVxjNq1Cg9+eSTkqQrr7yyfJmU3Y4XACLBpk2b9MILLyglJUUvvPBClcaFVHqua8yYMeXnhxo3bqyuXbsqOTk51OUCAcWVF4gaXbt2VVpamp577jmtX79e55xzjrp166ZjjjlGhmFU+5np06d79O3Fjh07Vvu6aZqaPXu25s6dqw0bNujQoUOVTjjs3LnTt5lR6Tdbs7OzdeyxxyotLa3K+6eeeqrfzREAsINNmzZp2LBhOv744zV48GDt37+//Gq5hx9+WHFxcerSpYvS0tK0d+9eLV68WDfddJPuvvtujRo1qsr4tm7dqmHDhum4447T0KFDtXnzZi1atEhXXnmlPv74YzVu3FhS6S14Lr30UhUUFOjss89W//79VVBQoKysLL355psaP368YmNL/5R6++239fnnn6tr164666yzVFhYqOXLl+vhhx/W6tWr9cQTT1SqYePGjbryyiu1a9cudenSRX369FFBQYE2bNigGTNmaPTo0crMzNSVV16p1157TSeccEKlqxaOvP3SkebPn6/bbrtNTqdT/fr1U6NGjbRkyRI99dRT+uabb/T6669XuoJQkg4ePKiRI0cqOTlZgwYN0p49ezR//vzyqyeOP/54r35vY8eO1Zw5czR//nzdd999NWYtqvr2228lSeeff76Ki4vLX+/Zs6eef/555eTkVFkHfv/9d61du1b33HNPSGsFQo1MsG8mlDUqBg0apI4dO6ply5aaP3++Jk6cWOVZf2UWLlyoJUuWqE+fPurcubO++OILPfPMMzJNU/Xr19czzzyj3r17q1u3bvr000/10EMPqXHjxrr44oslSYMHD5ZUehvCwYMHly8LK69AAYBAmzNnjtxut4YPH16eSzWp7gu0QDijeYGoUb9+fb399tt6/PHH9fnnn+vLL7+UJKWnp+uaa67R5Zdf7vO4awqPBx98UDNnzlR6erp69eqltLS08iB58skn5XK5fJ5mbm6uJCk1NbXa9xs1auTzuAHATn788UfdeOONVa4yk6Tnn3++yrfM8/LyNHz4cD322GO65JJLlJCQUOn95cuX67bbbtO1115b/tqjjz6qZ555RnPmzCl//dNPP9XBgwf1j3/8Q1dddVWlcezfv7/8JJUkXX/99brvvvvkcDjKXzNNUxMnTtTs2bP1ww8/qEuXLuXv3XHHHdq1a5ceeOABDRs2rNK4t2/fLqn0mQ9XXXWVXnvtNWVmZnp8+5Tc3Fzdc889cjgceuutt8qfOXHrrbfqtttu08cff6wXXnhBN954Y6XPrV+/XiNHjtQ999xT/kyGHj166O6779bMmTM1adIkj6ZfpmXLlkpPT1dOTo6ys7O5GsAL+/btk2ma6tGjR7XvV9e8+OCDDxQbG6v+/fuHokTAMmSCPTNh3759WrRokdq2bVv+xa6BAwfqqaee0scff6xLL7202vq+/vpr/ec//yn/zLhx43T++efr1VdfVXJyst57773y3+no0aN13nnn6cUXXyxvXgwZMkRbt24tb17wwG4AkejHH3+UpBr/NgQiGbeNQlTJyMjQ1KlTtXTpUr333nu6/fbbVVJSokmTJunDDz/0ebzVfZt0z549euONN9SuXTvNnz9fU6dO1W233aZx48Zp+PDhNY6n4jcsKzp06FCln8su/du7d2+1w+/Zs8ebWQAA20pLS9P1119f7XvVnRBPSkrSkCFDdOjQIa1evbrK+y1atKjyXKBLLrlEkqodvrrbDR55q8CMjIxKJ6mk0n16WWO84pVwq1at0po1a9S1a9cqJ6kkqVmzZlVe88Znn32mQ4cOaejQoeUnqaTSh0Tfcccdio2N1dy5c6t8LjExUbfffnulh0kPHjxYsbGxWrNmjU+1lD00dt++fT59Plo1bNhQhmHozTff1LvvvlvlfxV/r2U++ugjnXbaaTV+qQGIFGSCd0KVCfPmzVNRUZEGDRpU/lpZg2H27Nk11nfRRRdVuoo9OTlZ55xzjgoKCjR8+PBKv9P09HR16dJFv//+e43HTAAQiXbv3i2p9NbkQLThygtEpZiYGGVmZiozM1OnnHKKLr/8ci1evFgXXnhhwKaxZcsWmaapnj17VvmG14oVK6r9TMOGDfXrr7+quLi40re38vPztWnTpkrDJicnq0WLFtq0aZN27dpV5dZRNU0DAMJNu3btarz8ec+ePXruuef01Vdfadu2bSosLKz0fnW358vMzKx0Mkb68+TQwYMHy18799xzNX36dE2aNElLly7VmWeeqW7dulV7cszlcumNN97QRx99pI0bNyo/P7/S/c8r1rFq1SpJ0umnn17XrPtk3bp1kqRu3bpVeS8jI0MtWrRQVlaWcnNzK90Dt02bNlVu6xEbG6tGjRpVWi4IvrLnVu3fv9+j+7b/9NNP2rx5c5VvTgORiEzwTqgyYfbs2TIMQwMHDix/rVWrVjrllFO0cuVK/f777zrmmGOqfC4zM7PKa2XHNTW953a7tWfPHk7iAQAQBWheIGps2LBBRx11VJVbPJV1sI+8z6u/MjIyJEkrV65USUlJ+UHR9u3bNX369Go/06FDB/3888/64IMPyu/fapqmpk+frvz8/CrDDxo0SE899ZQef/xxPfDAA+Wvf/PNNzzvAkDEqOnWfPv379cll1yibdu2qXPnzurZs6fq168vh8OhdevWadGiRdXenq+6h9aVNYwrPpeoRYsWmjVrlp588kl9+eWXmj9/viSpbdu2uummm9SvX7/yYW+66SZ9/vnnatOmjfr3769GjRopNjZWBw8e1GuvvVapjrIr6YJ10qXstoI1LbcmTZooKytLeXl5lZZFTQ/zi42NrfEB0XUpO0F31FFH+fT5SFVQUFB++8qtW7cqNzdXn3zyiaTSE4xHH320Lr/8ct15550aPXq0Tj75ZBUVFSkrK0vLli3T008/XWl8H3zwgerVq6fzzjsv5PMChBqZ4J1QZMJPP/2kX3/9Vd27dy8/Bipz8cUXa+XKlXr33Xc1fvz4KuOrbfnX9l5NDz4HgEjUuHFjbdy4UTt27FDbtm2tLgcIKZoXiBpLlizRQw89pM6dO6tNmzZKSUnRli1btHjxYsXHx2vkyJEBnV6TJk3Ut29fLViwQEOHDlWPHj20Z88effHFF+rRo4c2b95c5TNXXHGF5syZo7vvvltLlixRamqqVqxYoUOHDumEE07Q+vXrKw0/ZswYLVy4UG+//bY2bNigrl27KicnR5988onOOeccffHFFwGdJwCwQk0Pen733Xe1bds23XzzzRo7dmyl95577jktWrTI72kff/zxevzxx1VUVKSff/5ZX331lV5//XXdcsstatKkibp06aJVq1bp888/1xlnnKHnnnuu0q1C/vvf/+q1116rNM4GDRpIKn34azCUnewpa84fadeuXZJU48NTA2XLli3KyclRamqqWrRoEdRphZs9e/bo5ptvrvRa2c+vvfaaunfvrrvvvltHH320Zs2apaeeekpJSUk6+uijdcEFF1T6nNvt1ieffKJzzz036L9TwA7IBO+EIhPKHtS9bNkytWvXrtph5s2bp1tvvbX84eoAAM917txZy5cv13fffVd+hS4QLWheIGqceeaZ2rp1q1asWKFPP/1U+fn5atq0qfr3768xY8bo2GOPDfg0p0yZoubNm2vBggWaOXOmMjIydPXVV+uaa67RggULqgx//PHH64UXXtD06dO1YMECJSYm6uyzz9b48eP197//vcrwiYmJev311zV9+nQtXLhQa9eu1bHHHqtHHnlEhw4donkBIKKVNYF79+5d5b1A3zovLi5OnTp1UqdOndSqVSuNHz9eX3zxhbp06aItW7ZIks4555wq9zivro6TTjpJUmlT/YYbbqh1umXjc7vdHtdadpuN5cuXV3l4c05OjrZs2aKWLVvW+K3aQCm7OqB///41nmyMVi1atNAvv/xS6zCGYeiKK67QFVdcUetwDodD33zzTSDLA8ISmVC9YGdCfn6+PvroIyUkJGjAgAHVDrN69Wr98ssv+uKLL4JyhVjZFe6+XiUIAHY3ZMgQPf/885o1a5auuuqqWp9x5nK5ary9IhCOaF4gYh15YuCYY47RxIkTPfrsuHHjNG7cuDqHe/3112t9PykpSePHj6/2EumaTlr06NFDb7/9tsfTSklJ0aRJkzRp0qQq7w0ZMqTW+gAgnDVv3lyS9MMPP1T6pucHH3xQfksef6xZs0Zt2rSpckJnz549kv683WDZLTJ++OEHjRo1qny4DRs26Lnnnqsy3o4dO+qkk07S999/r7fffrvKA1p37NhRfvuQBg0ayDAMbd++3eO6+/Tpo/r162vOnDm6/PLLddxxx0kqvQ3htGnTVFxcXH5rwmDIy8vTE088oTlz5igtLU3XXXdd0KYFAGXIhOoFOxM++eQT5eXl6eKLL9bkyZOrHeabb77R6NGj9e677waleVH2wPScnJyAjxsA7KB169YaM2aMZsyYoTFjxuixxx6r8sylw4cP6z//+Y/27t2r2267zaJKgcCjeQEAAMLSoEGD9Pzzz+vBBx/UsmXLlJGRoV9++UVLly7V+eefr08//dSv8c+bN0+zZs1S165dy7+V+ttvv+mrr75SSkpKeYO4Y8eO6tixo+bPn69du3bp5JNPVk5OjhYvXqyzzz672ivtpk2bplGjRumee+7RvHnz1KlTJx0+fFi//fab1q1bp2XLlkkqbYKXndS644471Lp1a8XExGjQoEHlJ+qOlJycrAceeEC33Xabhg0bpn79+ik1NVXffvutfv75Z3Xs2FFjxozxa9mUeeedd/T111/LNE3l5eVp06ZNWr58ufLy8nTcccdp+vTpatKkSUCmBQC1IROsyYSyW0bV9qWpnj17qlmzZvr6668rNWMCpXv37jIMQ9OnT9eGDRtUv359NWjQoM4r1wAgnPz973/X4cOH9corr6hfv37q3r27jj/+eMXGxio7O1vffvut9u/fX+muHRMmTCj/77LbBFZ87ZprrtExxxwTsnkAfEHzAgAAhKVmzZpp5syZeuihh7R06VIVFxerffv2eumll5STk+P3iaoLL7xQhw8f1sqVK7Vq1Sq5XC41a9ZMI0aM0OjRo8u/XetwODRjxgxNmzZNX3/9tVavXq3WrVvrzjvv1FlnnVXtiao2bdpo7ty5mjFjhj7//HO9+uqrSkpKUuvWravcNuTf//63pkyZoi+++EKHDh2SaZrq0qVLjSeqJKlfv35KS0vTjBkztHDhQhUUFKh58+YaO3asrrnmmvJvCPur7KSVw+FQUlKSmjRpol69eqlPnz7q3bs39zYHEDJkQugzYePGjfrhhx/UokULdevWrcbhYmJidPHFF+vZZ5/V3Llzdf311/s0vZoce+yxmjJlil566SXNnDlTLpdLzZs3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8svVsGFDzZkzx+fiAADhibwAANSFrAAAeIK8KHVxvbdUy7PKASAiedW8WLlypXr27Cmn01nnsE6nUz179tSPP/7oc3EAgPBEXthHqrL5hhYAWyIrAACeIC9Kdav5ohMAiFheNS927typli1bejx8ixYttGvXLq+LAgCEN/LCPiYkLeYbWgBsiawAAHiCvPBeSYnVFQBAYHjVvIiJian14UhHKioqUkyM188EBwCEOfLCPlisAOyKrAAAeIK88I5pSlPzrK4CAALDq715kyZNtGHDBo+H37Bhg5o0aeJ1UQCA8EZehCe+oQUglMgKAIAnyAvvuN3SXl1pdRkAEBBeNS+6dOmi7777TtnZ2XUOm52dre+++05du3b1qqCsrCwNHz5cffv21dChQ2sNKNM0deWVV+rUU0/1ahoAgOAiL8JP6Te0uL8UgNAhKwAAniAvACB6edW8uPzyy1VcXKybbrpJe/furXG4ffv26eabb5bb7daIESO8Kujee+/VsGHDtGDBAl1zzTWaMGFCjcO+8soratWqlVfjBwAEH3kRfkq/oTXK6jIARBGyAgDgCfICAKKXV82L9u3b66qrrtLatWs1YMAAPfbYY/ruu++UlZWlrKwsLVu2TI8++qgGDBign3/+WVdffbXat2/v8fj37NmjNWvWaODAgZKkvn37avv27dq0aVOVYTds2KDPPvtM1157rTezAAAIAfICAFAXsgIA4AnyAgCiV6y3H5gwYYLi4+P14osv6tlnn9Wzzz5b6X3TNOVwOHTdddfp73//u1fjzsnJUVpammJjS8syDEPp6enatm2bWrduXT5cUVGR7rnnHk2ePDlgD2EyTVP5+fkBGZekgI4rFAoKCir9G+4iaX4iaV4k5icQTNOUYdj/9j6RmBfeZkW4ru9WZphdlxl1eYe6vBOsusIhL8gKz4Xb8YU37LptBlu0zrfEvFf812rhkBUSeeErO2SH3db56lBjYFBjYNi1RqvywuvmhWEYuvXWW3XJJZdo9uzZWrlypXbv3i1Jaty4sTp37qwhQ4YE9RK6J598Uuedd56OOeYYj+556AmXy6V169YFZFySAjquUMrKyrK6hICKpPmJpHmRmB9/uFwuxcfHh2x6vorEvPA1K6xc35N9+IwdMsyu+wjq8g51eSfQdYVDXpAVnrPDvjnY7LptBlu0zrfEvNtBOGSF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ImLfffeNj370oxX92JCO22+/PebPnx/jxo2L8847Lw477LBM6kg9w7bc/8aPH59xRRu53wpXSEZnWVe3K664Iq6++up46UtfGh/5yEdixowZQ1pPMa8DUniOMXiq5bEv1+urSrxPqv21ZG8ZNZwf/+FwrEr6Us+OYub8rOqtlHmo2Dl0qOob6Fw3lDV26+31f1Y1lus9wRT298HmOy+oOF/96lfjqaeeyvwz4wfqc5/7XNx9993xwQ9+MK644oqsyynZX/7yl/jFL34R73nPe7IupSy++93vxk9/+tP4yU9+EjvssENccMEFWZdEBTjllFPi0EMP7fVPc3NznHrqqXHXXXfFrbfeGueff3586EMfiqVLl2ZddnLsf6VJ6X5LNaO3rOtzn/tc3H777XHrrbfGQQcdFO9617uGvKbh8joACpHSPMXQqrbHPtUchKFUbfv9YEr1vqyEuS7F1/+bcixQOM2LEkydOjVWrlwZHR0dERGRz+ejubk5pk2blnFl27atuku9bqh985vfjF/84hfx9a9/PRobG2OHHXaIurq6WLlyZc8yS5cujWnTppV83VB785vfHPPnz48pU6ZU5OPzwAMPxNKlS2POnDkxe/bs+NOf/hQf//jH43//938r8rHp3k59fX2cffbZ8cADDwyLfYfBdeONN8b8+fN7/TN16tSYNGlS1NfXR0TEgQceGHvvvXcsWLAgk1pTfl72tv+lwv3Wv2IyOsu6IjY+nhEbf2vpjDPOiMWLF8eaNWuGtK5uhbwOYHhLeX4pl3K+vqpE1fxasq+MGo7jHo7HqqQr5f2k2Dk/K5UwD5Uyhw62cs11Q1ljRN+v/7Oecwf6nmA10LwowYQJE2LWrFlx6623RkTEvHnzYvLkycmfqrOtuku9bih9+9vfjp/97Gfx7W9/O7bffvuey1/3utfFDTfcEBERDz/8cDz99NNx8MEHD+i6wfT888/H008/3fPzL3/5yxg3blzFPj6nn356/Pa3v4277ror7rrrrth///3jU5/6VJx++ukV99i0tLTE888/3/Pzz372s9h7770r9rEhHcuXL+/5f1NTUyxcuDD22GOPTGpJ9XnZ1/6XCvfbtpWS0VnV1dHREatWrepZZt68eTFx4sTYYYcdhqSmUl4HMLwN98e+3K+vKlG1vpbcVkYNt3EPl2NVKkeq+0kpc35WUp+HSp1DB1O557qhqrG/1/9DWWO53xOsBrl8Pp/PuohK9OSTT8aFF14Yzz77bIwePTouu+yy2HPPPbMuq8fFF18cv/71r2PVqlUxbty4GD16dNxxxx3brLvU64bC8uXL41WvelXMmDEjRo8eHRERDQ0N8aMf/ShWrVoVH/vYx2LJkiVRX18fH//4x3s+S77U6wbT0qVL4/zzz48NGzZELpeL8ePHxwUXXBAzZ86s2MdnU2eeeWacffbZccwxx1TcY7N48eJ4//vfH52dnRERsdNOO8VFF10UO+2007B4bMjOBRdcEH/+85+jtrY2amtr453vfGe87nWvy6yeFJ+X29r/hlopGZpVXd/61rcyv99Kzeis6rruuuvijDPOiPb29sjlcrHDDjvEhRdeGHvttdeQ1FXq6wCGt+H82A/G66uUDbfjsEKVklHDYdwRw+tYlcqS4n5S6pw/2Mo9Nw9FfQOZQwfDYMx1Q1Vjf6//h7LGwXhPcLjTvAAAAAAAAJLiY6MAAAAAAICkaF4AAAAAAABJ0bwAAAAAAACSonkBAAAAAAAkRfMCAAAAAABIiuYFAAAAAACQFM0LAAAAAAAgKZoXAAAAAABAUuqyLgAq2YIFC+L73/9+PPDAA7FixYro6uqKHXfcMV7+8pfHCSecEEceeWRERDzwwAPxy1/+Mu6///5YunRptLS0xPTp0+Poo4+Od73rXbH99ttnPBIABkuhWfHQQw/F97///fjzn/8cK1asiNbW1pgyZUrMmjUrzjnnnNh3330zHgkAg6nQvNhSW1tb/Mu//Es89thjseuuu8btt98+xJUDMFQKzYr58+fHWWed1ed6LrvssjjxxBOHqmwoWS6fz+ezLgIqTVdXV3z2s5+Na6+9Nurq6uKwww6L3XffPerq6mLx4sVx7733xnPPPRcf+MAH4r3vfW8ceeSRsWbNmjjwwANj5syZkcvl4v77749HH300ZsyYETfccENMnDgx62EBUEbFZsU3v/nN+Pa3vx37779/TJkyJUaOHBmLFy+OX/3qV9HW1haXX355nHDCCVkPC4AyKzYvtnTVVVfF9ddfHy0tLZoXAMNUsVnR3bw45JBD4pBDDtlqfcccc0zMnDkzg5FAcZx5ASX4whe+ENdee23MnDkzvvjFL8ZLXvKSza5fv359fPe7341nn302IiLOPvvsOP7442Py5Mk9y+Tz+bjkkkviBz/4QXz5y1+OT3ziE0M5BAAGWbFZccYZZ8Q555yz1Xr+8pe/xFve8pb43Oc+F8cff3zkcrmhKB+AIVJsXmzq4Ycfjq9//etx0UUXxSc/+ckhqhiAoVZqVhxyyCHx/ve/fwgrhfJy5gUUadGiRfH6178+tttuu/jZz362zTMm2traoqGhoc/rV6xYEa94xSti9913j9tuu20wygUgA+XMioiIN7/5zfHoo4/GAw88ENttt125ywUgIwPJiw0bNsQJJ5wQEydOjOuvvz722msvZ14ADEOlZEX3mRfve9/7NC+oaM68gCL95Cc/ic7Ozjj11FP7/ain/t6MqqvbuAvW1taWrT4AslfOrHjqqafi73//e0ydOlXjAmCYGUheXHnlldHc3BzXXHONs/IAhrGBZEVTU1Nce+21sWHDhpg8eXIcfvjhm30qCKRO8wKK9Mc//jEiIg477LABr+umm26KiOjzy/cAqEwDyYqHH3447r777ujo6IilS5fGXXfdFRERl1xySVlrBCB7pebF73//+7j++utj7ty5W310CADDy0COLW677bbNPumjrq4uzjjjjPjYxz7mF2mpCJoXUKRVq1ZFRAy4U71w4cL48pe/HBMmTIh3vOMd5SgNgEQMJCsefvjh+NKXvtTz88SJE+Ozn/1sHHXUUWWrD4A0lJIXLS0tceGFF8b+++8fZ5555mCVBkAiSsmK8ePHx0c+8pF49atfHdOnT4/W1tZ48MEH4/Of/3xce+21kcvlYu7cuYNVMpRNTdYFQDVavHhxvPOd74zOzs648sorY/z48VmXBEAizjjjjHj88cfjoYceiltuuSVe8YpXxLnnnhvf/OY3sy4NgAR89rOfjRUrVsRnPvOZqKlxSA/A1nbfffd45zvfGbvvvnuMGjUqJkyYEMccc0xcf/31MX78+PjOd74TzzzzTNZlQr+80oEidX++4NNPP13S7RcvXhxnnXVWrFmzJr74xS+W5eOnAEjLQLMiImLkyJGx1157xeWXXx6veMUr4oorroi//OUv5SoRgAQUmxfz58+PG264Ic4///zYddddB7M0ABJRjmOLbpMmTYqjjz46Ojo64qGHHhrw+mCwaV5AkQ444ICIiLjvvvuKvm1342LlypXxhS98IV796leXuzwAEjCQrOjNkUceGV1dXfHAAw+UZX0ApKHY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4/zzz4/f//73Wz02m1q5cmWcddZZ0dDQENddd12MHz8+Fi9eHKeeemo899xzcfnll8cVV1wRq1evjre97W3R1tY2ZOMDXiQrKo+8kBeQBXlRWWSFrIAsyIrKIy/kxVBw5gW9+u1Dy2Jda3u/y+UjYm1re9zz8LJ49YEzBrWm7ol9xYoV8Z//+Z8xevToOOussyIi4vOf/3zss88+8aUvfSlyuVxEROyxxx7xxje+Me6+++541ateFRERl112Wc/6Ojs74+Uvf3m88pWvjPvuuy+OOuqoQa1/sOTzXbHu8fnR1fp81E2c0TP+3IhRkZs4IzpWLY51j98f9ROmDfppey0tLTFr1qzNLvvc5z4Xl1xySc/PHR0dsdNOO8Xpp58ef//732PXXXfdbPlly5bF2972tpg+fXp8+ctfjlGjRkVExJe+9KUYO3ZsfPvb344RI0ZERMQBBxwQRx99dPzoRz+Kt771rYM6NmBrsqKyyAt5AVmRF5VDVsgKyIqsqCzyQl4MFc0LenXfguaezxbsT/dnDw5maGw5EdXW1sZXvvKV2G233aK1tTX++Mc/xsc+9rHo7Hyx877LLrvE1KlT45FHHukJjbvvvjv++7//O5544olYu3Ztz7JNTU0VGxodz62K9lVLo3b7iT1h0S2Xy0Xt9hOjfdWS6HhuVdSPG9zTEkeOHBnf/e53N7tsxowZcfPNN8e1114bixYtipaWlp7rmpqaNguMp556Kt761rfGXnvtFVdffXU0NDT0XHfPPffEG97whqitre15AbH99tvH3nvvHQsWLBjUcQG9kxWVRV7IC8iKvKgcskJWQFZkRWWRF/JiqGhe0KsXWtoKCoyIjcHyQsvgnirVPRHl8/loamqKz3/+83HBBRfET3/608jn89HZ2RmXXXbZZh3tbs3NzRER8fDDD8d5550XRx99dJx77rkxYcKEyOVycfLJJ8eGDRsGtf7BlG9rja6OtqitH9Hr9bn6EdHV+Uzk21oHvZaamprYd999N7vsjjvuiAsuuCBOOeWU+NCHPhTjxo2LlStXxnvf+96t7vdHHnkknn322bjooos2C4uIjZ87eN1118V111231Xbr6+vLPxigX7KissgLeQFZkReVQ1bICsiKrKgs8kJeDBXNC3q13aiGojre241q6H/BAdh0InrZy14Wu+66a5x88snx5S9/OS64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5M4778zChQuzYsWKbLHFFtl7773z6le/Os973vPWWH7JkiX55je/meuvvz6zZ8/OyJEjs+222+awww7LO9/5zgbdCgAGUq1dcdJJJ+WOO+7Y4Lo++clP5tWvfvUgpAZgsPXm2OLJJ5/MRRddlF/+8peZM2dOWlpass022+Soo47Ka1/72owaNaqBtwSAgdKbrliwYEG+/OUv5ze/+U0WL16cCRMm5PnPf37e/e53Z/LkyQ28FVC7SrVarTY6BJTNihUr8slPfjIXX3xxmpubc9BBB+XZz352mpubM3v27Nx666154okn8u53vzvveMc7kiTz5s3LySefnNmzZ+fggw/O1KlT09bWloceeijz5s3Ltdde2+BbBUB/6m1XXHXVVZk7d+466+no6MgFF1yQESNG5Fe/+lW23HLLBtwaAAZKb/viySefzNFHH53Zs2dn3333zZ577pm2trb85je/yUMPPZSDDjooF110UUaM8EULAENFb7vioYceynHHHZdHHnkkhxxySHbaaafMmjUrN954YyZOnJjvfe972W677Rp9s6BHPnkBdfjc5z6Xiy++OFOnTs0XvvCFdXb4y5Yty2WXXZbHH388yco3nt71rndl4cKFufjii3PQQQetsXxHR8dgRQdgkPS2K44++uhu13PdddelWq3mBS94gcEFwBDU2764/PLLM3v27Jx88sn5r//6r1XLtbW15fjjj89tt92WP/zhD9l///0H82YAMIB62xXnnntuHnnkkZx55pl5wxvesGq5n/3sZ3nve9+bs88+O9/4xjcG8yZAXQwvoJdmzZqVCy+8MBMmTMiFF16YzTfffJ1lRo8enVNOOSVtbW1JVr7xNGPGjJx66qnrDC6SpLnZpggwlNTTFetzxRVXJEle85rXDEhWABqnnr6YPXt2kuTQQw9dY7mWlpYccsghmTFjRh599NGBDw/AoOhtVyxfvjw333xzNt9885x00klrLPfyl788F1xwQW6++ebMnj0722677WDdDKiLz5FCL1111VXp7OzMcccd121hrK6lpSVJ8tOf/jRJ8rKXvSzz58/Pd7/73Xzta1/Lz372szz99NMDnhmAwVVPV3RnwYIFufnmmzNp0qS88IUv7OeUADRaPX2x0047JUluuummNc5va2vLLbfcktGjR2evvfYakLwADL7edsXjjz+ejo6OTJkyJZVKZZ1lttlmmyTJbbfdNiB5oT/5c2/opT/+8Y9J0u0nKNbnL3/5S5LkzjvvzCc+8Yk1/sp24sSJ+dznPpcDDzywf4MC0DD1dEV3rrzyyqxYsSJHHXWUT+kBDEH19MVrXvOaXHvttbnkkkvyl7/8Jc95znPS3t6em266Ka2trfnsZz/rawYBhpDedsXGG2+cpqamzJs3L9VqdZ0Bxpw5c5IkM2fO7NecMBB88gJ6afHixUnSqwOCRx55JMnK7xw8+eSTc9NNN+XWW2/Nf//3f+epp57KO97xjixcuHBA8gIw+OrpirVVq9VcddVVSXxlFMBQVU9fjB49OpdcckmOOuqo3HnnnfnmN7+ZSy+9NHPnzs0rX/nK7L333gMVF4AG6G1XjBkzJvvtt18WL16c73znO2ucd/311+e+++5Lkjz11FP9GxQGgD/hg0FQrVaTJC984QvzwQ9+cNXpJ510UhYsWJALL7wwV1xxRU499dRGRQSgYG677bbMmTMnBxxwQLbffvtGxwGgIB599NGceuqpefTRR/O1r30t++67b5YuXZobbrghn/zkJ/PrX/86V111VcaPH9/oqAA0yH/913/l+OOPz8c+9rHceOON2XnnnfPQQw/lhhtuyM4775z777+/26+UgqLxyQvopa7vF3z44YdrvkzXgcO0adPWOa/rtBkzZvRDOgCKoJ6uWJsf6gYY+urpi//5n//JXXfdlS984Qs59NBDM378+EyaNCnHHXdc3vve92bWrFm59NJLByoyAIOsnq7YZZddcsUVV+TlL3957r333nzrW9/KP//5z3zsYx/LkUcemSTZbLPNBiQv9CfDC+ilffbZJ0nvftjoGc94RpKV3zu4tq7Tli9f3g/pACiCerpidU888UR+8YtfZOONN87LXvay/owGQIHU0xe//e1vM2HChOyyyy7rnNf1O3pdXwkCQPnVe2zxzGc+M5/73Ody6623ZsaMGfnJT36S1772tXnggQeSJLvvvnu/Z4X+ZngBvXT00Uenqakpl19+eR599NENLtv1w9xdP6r097//fZ1luk7beuut+zkpAI1ST1es7pprrsny5ctz+OGHZ9SoUQMVE4AGq6cv2trasmTJkm7747HHHkuSjBw5sv/DAtAQfT22WN2SJUvyq1/9KhMmTMjznve8/owJA8LwAnpp++23zymnnJLHHnss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eUPy/fznP8/UqVPzsY99bNVpd9xxR7fLvvKVr0xTU1Pe//7354ILLshzn/vcVedtsskmOfTQQ3PCCSesc7lx48b1f3CgR7qiXPSFvoBG0RfloSt0BTSKrigXfaEvBovhBd06ZM8p+dqP7klrDz+WVEkybszIPO85UwYrWpJkjz32yCtf+cpcddVVeec735m99torDz744DqT1tUtW7YsI0eOXGOHeu211w5G3AFVqYzIuJ0PTMcTi9OxePbK7xscOSrV9uXpfHJxRozdOON2PiCVyoiG5Ou631e3ofv9zDPPzPLly3PqqafmwgsvzL777pskee5zn5sHHnggu+66a5qamgY0M1AbXVEu+gJoFH1RHroCaBRdUS76gsHSmGcQhdcysinvP36fpLKyGLpT+df/e9/x+6Rl5OBvwKeeemo6OztzySWX5LTTTsuvf/3rvPe9780vfvGL3H777bn66qtz+umn5/bbb0+SPO95z8uiRYvy8Y9/PLfeemu+/OUv54c//OGg5x4ILZtvk00OeGVattoxK1qfSvuj87Ki9am0bPXMbLL/K9Oy+TYNy3bwwQfn7rvvzv/93//ld7/7Xc4777zceuutG7zM2WefnZe+9KX5z//8z9x9991Jkne/+92ZNWtW3vKWt+SnP/1p7rjjjvz0pz/NRz/60fz4xz8ejJsCrEVXlI++0BfQCPqiXHSFroBG0BXloy/0xWDwyQvW64DdtsqZbzwgn/veXVmytH3Vdw92/XfcmJF53/H75IDdtmpIvh133DGveMUr8t3vfjdvfetb853vfCdf/OIX86EPfSjt7e3ZaqutctBBB2X77bdPkhx66KH54Ac/mMsuuyxXXXVV9tlnn1xwwQWZPn16Q/L3t5bNt8nIzaak44nFqbYtTaVlTJo32bxhU+4uxx13XObMmZPLLrss3/jGN3LIIYfk05/+dI499tj1XqZSqeR//ud/0tbWllNOOSXf+ta3sssuu+QHP/hBPve5z+Xss89Oa2trJk2alP333z8777zzIN4iYHW6onz0BdAI+qJcdAXQCLqifPQFA61SrdbyUziUybJly/LPf/4zz3jGMzJ69Og+r6+tvTO33D0vt94zP0+1tmWjsS157h6T87znTGnIpBt6o7+3BxhK+nP70BWUnb6A7jm2gH/TFbB+ji3g3/RF//HJC3rUMrIpL9p327xo320bHQWAgtIVANRCXwDQE10BdPGbFwAAAAAAQKEYXgAAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAohhdDWLVabXQEaDjbAfTMdgK2A+iJbQRsB1AL2wnYDvqT4cUQNHLkyCRJa2trg5NA43VtB13bBfBv+gL+TV9A93QF/JuugPXTF/Bv+qL/NDc6AP2vqakpEyZMyMKFC5MkY8eOTaVSaXAqGFzVajWtra1ZuHBhJkyYkKampkZHgsLRF6AvoCe6AnQF1EJfgL4YCJWqz7EMSdVqNQsWLMjjjz/e6CjQUBMmTMhWW23lRROsh76AlfQFrJ+ugJV0BWyYvoCV9EX/MbwY4jo7O9Pe3t7oGNAQI0eONOWGGukLhjN9AbXRFQxnugJqpy8YzvRF/zK8AAAAAAAACsUPdgMAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAohhcAAAAAAEChGF4AAAAAAACFYngBAAAAAAAUiuEFAAAAAABQKIYXAAAAAABAoTQ3OkAR7Lfffmlra8ukSZMaHQWgR4sWLUpLS0vuvPPORkcZVnQFUDb6YvDpCqBsdEVj6AugbBrVFz55kWT58uXp6Ojo1WWq1WqWL1+earU6QKn6V5nylilrUq68ZcqalCvvYGbt6OjI8uXLB/x6WFM9XZGU63ncpWyZy5Y3KV/msuVNZE70RSPU2xVJ+Z6zZcublC9z2fIm5ctctryJrhgqhuqxhXx9I1/fyNc3PeVrVF/45EWSLbbYIklyww031HyZ1tbW3HfffZk6dWrGjh07UNH6TZnylilrUq68ZcqalCvvYGY97LDDBnT9dK+erkjK9TzuUrbMZcublC9z2fImMif6ohHq7YqkfM/ZsuVNype5bHmT8mUuW95EVwwVQ/XYQr6+ka9v5OubnvI1qi988gIAAAAAACgUwwsAAAAAAKBQDC8AAAAAAIBCMbwAAAAAAAAKxfACAAAAAAAoFMMLAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACsXwAgAAAAAAKBTDCwAAAAAAoFAMLwAAAAAAgEIxvAAAAAAAAArF8AIAAAAAACgUwwsAAAAAAKBQmhsdgPJra+/Mz2+bme9df3+eam2v6TKVJFtPGpe2jmqWLu9IpZJssenYvPzgHXLALhNXLbfgkSU5+8LbM3fRklSrSaWSbD1pfD5yyoHZarPx/Zb/13+ck5/c8mDmLXo67R2dGVGppGVkUyZsNDrbbDE+Bz9nSg7Zc0paRjatuszNf56X22bMz2NPLM0TTy1Jx08XZ1nbijVuy8F7TM4d9z6c22bMz1OtbdlobEsO2n3yqnV1XffPfvfPLHxsaZLuL/vEkuVpa+9MUsmokU3ZePya61n9tnTl6u76BtvaecaNHpkJG43K408tz1Otbeu9TUly85/n5ZY/z8n8hY9m2U8Xp3V5Z6rVaka3NGf/XbfMCS/dOX96YHF+d/e8zFm0JEuXdWTMqKaMHNmUp1vb81RrW02P5dqWtLbl4p/cm9/f+3CWtXWsur43vnLXjB/bst7bNnZUU7bepD3PfFZnxtawzn122SI7bTshd/1tUSEeK6B2Xdt/1/6ndWl7Ojs78/TyznR2VpMkTSMq2Wm7TfP8vabknn88ss5+fNyYdfcZvd2HL2ltyzeu/Ut+9+d5WdrWkVST5uYR2XaL8XnlITvmhftss8F93deunpGb/zQ37R0rkqzs2M03GZPXHvbsHLb/dmlr7/z3vmt5R5pGrMje93ZmxIim3PGXBWld3tHr+66SpNrNac/ebkJeuM82uecfj6xz25P8u3OfXJZHn1yWp5d1ZMWKFRlRGZGxY5ozsmlElrV1Zuzo5kzebFw22WhU/jbrkcxd9HRWrJiTVJKxo5pz8HOm5M2H77bG/nx9NtTRG7pv6+3iJa1t+cbV9+b2v8xP55ULMnqUroCyW7svljy9PK3LO9LesXJPWEmy0biWvGbaszJuTEvu+MuCVa9rx45uzlYTx2TbTTvWeX3Zm/1M177s2pv/kbkPL0lHZ7VX+8QFjyzJR79+W+YuenrVaWNGNeX4l+6cVz5vxyRZY19ZrVYzflQ1z763Mw8tfDpzH34y7Z29u98qSUaNTNrakxWrnd7cVMlBu2+V9o5qnl7W3u2x1c1/npeb/zQ3f5/zeJYsbU/lX7d12y03yqiRTZn/aOtaxw1teXLJsqyozs2KatLUVMm40SNzwG5brfP6f31qPX5YWz190dbemRv/MCfX/ubhPPWjh1OpVLLFpmPzkgO3S3PTiNx538P6AlhlSWtb/u/Ku3Pzn+b263ormZPjXvLsvOawnRu2j+luH/qcZ07I/PlP56d/+nNal3eu8R7Uhnqjax1jWpqzrK0jcxYuyfL2znXeu1n9mG5k04gs7+jIktaOtC5rT0fniowYsfJYL0nGjRmZrSf1/B5U0v/vGa2vl7reRyvKe4a1qlSr1bWPIYedww47LElyww031HyZB3/8rSz/89UZ1XXCc1+THacd3//hejDjHwvzoS/f2i/rqlSSTca1ZPdnTcqDcx7P/EeeXjUw2GLCqCxrr+aJJW39cl0bMqqlKUcfNCF/+GdH/jb7ifUuN3WHifnUu57fp+u6fcb8/O+3/5DlbT2/oh43ZmTef/w+qVar+ez37srTS2sb1CQr78Ou+7JaXbmuVz7vGbn6N/+o6brXWV9WvvnTlemA3bbK7TPmr8rV3fW9//h9svszNs59992XqVOnZuzYtd9i71/d5anlNo1qaUolybI67pdarX6/re7Sn96b79/wwHov97oX75QTXz51w/f16Oa8/4R9V627p3V2WfuxWjvb6urZZ9F3dXXFjd9Nbr0i7UlGJg3rit5qbW0dtH1F15sqV//273lo/pIBva7eam6qZMyo5mw5cdyqNwV+9rt/5h9znljnDfjeWrUf/9c+Y/VuWd8+fPX9Qi37ltEtTfl/J+7X631dkoyoJCsa+Aqx67YPVCd07c/Xp6fXB+u7b2vp4u727wPRFYm+aIR67/N1+mLPo/LdRTvlthnze7WezTYZlbGjm7NgcWvaO2vfiLfYdEy223KjtC7vWGPQOn7syoP+R59YlrmLl+TxJ5enraMjHXVukk2Vlfu+Ff/aNpqbRmTUyBEZO7olG40dmeamEXn0yaV5fEnbqsFqklVvQHe92Z4kX7t6Rm7587x/5U1GjWzKIXtOySlH7r7eN4zX7rfe/hHTGn/AtNowde0/sLnzrwvz/V/en4cfXVrfHbWW1V9f9mY/U+uxzvr2if/vC7/JX2c9tt7LdT2Gqz9Wg2ntY6uf3PLPXh2j1aKnvqj1+GFt9fRFLY9n1+sLxxbFV3dfFOS9qPUZzOOIetSTr6srfvSbBzJ7wdM9X2CY+fCbD+zxNWl/6+n9pu7+YCpZf2/U8p5VX2zoPbn+Pg6oZX31vmfYqL4o3PDinHPOyY033pi5c+fmRz/6UaZO7f6Fwg9+8IN8/etfz4oVK3LQQQflIx/5SEaOHFnXdfb2zn/w3GOS/OtFwVrn7XjmlTVf7/W3PZgv/uCempdnXbtsv2n+990vqOuyt8+Yn3MuuqOuy65vRzjYKv/6f6+d9uz84MYHkup6dtD/+n8fPH7PjMsjA/5C4vYZ83PuxXesN08RVCrJmW88IAfuPjlJ7YXxvOdMzu/umb/B29a17r899FhN61zjsv/6f6tnW5sDjHJ1RbJuX/SmKxqhtbU1v/v9Pbn8t49lwWPLGx1n2Fjvi+x//b+u/UKt+6su//2m3u/rhoNjD3t2TnrFruuc3pvXB6vftz113/r27/U8JrV0RaIvksHvi7oG3ecekxVJKqs9carVpKMj+X9L3tDrDKz/DePV37S658EnevVHTAP15nitKr14zX/mGw9Ikl4d66y9T+xpcDGcrK8vat1/r335evqi3mNXxxa1KcOxRdJ/70UNpK797DOftVN+95fFufLGB/Lok8tW/VHKM6ZsklHNI/LgvCfy5NNt3f6xTCXJiKbKqk80U3yrvyYeaGV4v6k7lW7ek+vv44B6j/Vqfc+wUX1RuK+Nmj59ek455ZSccMIJ611m9uzZ+fznP58f/vCH2XzzzfP2t7893//+9/P6179+wPOt/mZU8q8NpfrvCd1fP3KMg4xB9NdZj2XBI0t6/RVSbe2d+cx3/1j39RZlB9n1/Pv+DQ9scKBSzcoD4i9f9Ze898gtBzRTW3tnPvu9u4pfJNXkc9+7K5d8ZIu0tXfWvIO/5e4a/gKymnzmO39I6/Le/1li12PVla3IH91rpLJ1RXfnr36Acf+sxfngF24Z6FjZaOzITJowJk1NIzJv0VN5etnAfcKJ3utpH/65792V//t/E3r9gvSz37sr3+rlvm44+P4ND+SoFz5rna8E7M3rg677tut/b6j7utu/L2ltq+sx0RW1K0NfrOj6o/W13olqbk7+d/y3HFvU4fJf/i3VarXbN5yT5M77FuZ/v/Pnmtf39NL2fP+Xf+uveHWp9uI1/2e/+8devw5ffZ+44JElBher6a4verP/Xv3ytRwrrb2PT1L3sau+qE3RuyLp/fFFb13zm7/l61ffV/fl1zVnnVNal3XkLw8+0uMlq4nBRcl8+jt/yGVnv3zA9zGleb+pO2u9J9ffxwH1rm/1dQ7Ge4b1KNwPdu+///7ZaqsNf9zouuuuy7Rp0zJp0qRUKpUcf/zx+fGPfzzg2R688bur/nfXm8ZdW0vlXwcbzc3JxNw44Fn4t4994/ZeX+bmP89L67Lef1d3kfW0464meXpZR+59qHVAc9z853l5eml74YukmmTJ0vbccve8XPyTe/t93fUMLla/fFc2uleWrtiQkz/wnhz+gatz+AeuHpTBRZI81dqeB+c9mQdmP25wUTJd+4Xzv/OHXl/26QHa1w0Fl/x0zfukt68Puu7bWrtv7f17Xx4TXVGbovdF1+CistbgwrFF333/hgeypHXdr7xt76zm/66c0YBE/aPW1/z1HOt07RPPvrD3x1dD3dp90dv9d9fl6+mLvh676oueFbkrktqPL2pZbklrW951/o2rjkO6/q9/BxcMN0uXdw7KPqYs7zd1Z+335Pr7OKCvx3qD9Z5hPQr3yYtazJ8/P1tvvfWqf2+99daZP7933we7tmq1mtbWHh6gW6/417Ldn911kHHGuDk5zdfgDZo5C5f0/Nit5ZY/r/tXAMNBpZL8dc6yLF3aP9+/251b/jxnwL8vsL9UKsnNf5qTBzbw2yqN0pXtwKmbrXNetVpNZe13OVhHo7ti/etY+V9dQW9VKslfZ9b3l7BF3dc12u0zFuRNr/j3Nl3P64Ob/7TyMrV23+r79zv+sqDX17e+dXVHX9Smv/uipq5IsvzXV6RlA78F7Nii7755zT055Yh/f/3L0qVLc+9DrX36I5OhrGufOHdRsX6DqgjW7ove7r+7Lt+bY6WufXx/cGzRdw07tkh6PL7osvymK3L4T4r3OxMMDxt6TdpfyvR+U3dWf0+uv48D+rq+tfN1p1F9UcrhxUBoa2vLffdteNI8PklzDRvIiMJ9nmVoq1bT42O3tocXPz4wYQquWk2WLl+RmTNnDth1PLz48dIUSbWaLFz8RFqXDfwP0fdWV7buntttbW0ZNWpUN5dioNXcFd2cvvZ2oSvorWo16eis70dRi7qva7TWZWtu0/W8Pli4+IlUU625+1bfv/f1MdlQVyT6olFq6YqPfmdOzt+otvXpi/rdNmNenvfsNU/765xljQlTAl37xLK8lh9Ma/dFb/ffXZfvzbFS1z6+2g9/Y+zYophq6Yuk++OL7p5HI8ygaKANvSbtL2V6v6k7q78n19/HAf1xrNfTe4aN6otSDi8mT56chx56aNW/586dm8mT+/bDMC0tLev9UaYus3/ep6tggFQq6fGxW9uWf2rLrIULByhRcVUqyZhRI7LDDjtkzJgxA3IdW/6pLQ8tWliKQqlUki023yRPLH0iy9uL9aPEXdm6e263bOjPNFmlUV2xYK2uKMO2QDlUKklz04i0d/R+gFHUfV2jjR295jZdz+uDLTbfJElq7r7V9+9jRy/q02Oyoa5I9EWt+rsvaumK7r4LnP7XuWLEGo/F0qVL0/rL4XcMUKuufWKlMsfrl7Ws3Re93X93Xb43x0pd+/gkfT52dWzRd406tkjWPL6wbVJUG3pN2l/K9H5Td1Z/T66/jwP6ur6183X3nmGj+qKUw4vp06fn+OOPz7ve9a5svvnm+e53v5tXvvKVfVpnpVLp9pfU19Cekt5jQ9s2W4zv+bFby/P23CZ33Dv8Dlyq1WSXbUZnzJgxvb7PalWm+7ZaTQ7Za5tsuvGYXHfbrEbHWUNXtu4eJx/rrk3DumI1ZX1RRTFVq8kuO2yae/7e8w8drq2o+7pGO3D3rdbYpuvpsEP22ibVamq+3Or79wN226pPj8mGuiLRF7Xq777obVcwcEaPal7nsRg7yg8Wr0/XPnHrSeMzZ6Gvjlrd2n3R2/131+V70zNd+/jedExP63JsUT/HFrBhG3pN2l/K9H5Td1Z/T66/jwP6ur618xWpLwr3IeSzzjorL3jBC7JgwYK85S1vyUte8pIkyZlnnpkbbrghSbLtttvm3e9+d44//vi85CUvycSJE/O6171uQHO95gNXD+j6qd9Zbzmw15c5ZM8pGTt6aE2ietqFVJKMG92cXbcb2DI5ZM8pGTdmZI95Gq2SZPyYkXnec6bkja/ctd/X3ZcD49Wz0b2idsXqHFzQn7r2Cx88Yd9eX3bcAO3rhoKTX7HmfdLb1wdd922t3bf2/r0vj4muqE0Z+oKBc8BuW65z2i7bjG5Akv5T62v+eo51uvaJHzml98dXQ93afdHb/XfX5evpi74eu+qLnpWhKxxbUGRjRjUNyj6mLO83dWft9+T6+zigr8d6g/WeYT0K9+7txz72sW5PP/fcc9f497HHHptjjz12MCIlSXzJQjFN3WFittpsfK8v1zKyKR84Yd98/Ju313W9laQfvnm07yr/+n/HHrZTvn/D31Kpdp+ra7l3HLN7RlYXD2imlpFNef/x++Sci25fb55CqCTvO36ftIxsSsvIprzuxTvl8l/+rceLHbLnlNxy97xkQ7etknzg9fvlbw89VtM617roGtnoXlG7oouDC+qxvm5Zfb8wcZMxNe+vury/jn3dcPC6F++U8WPX/Ohzb18fvH+1fXVP3dfd/n382Ja6HhNdUbui9wUDa+03nJNk1+3G5ro/Plm6H+2u9OI1//v/NejuzbHO6vvErTYbn6k7TMx9Mx/te/AhoLu+6M3+e/XL13Ks1N0+vt5jV31Rm6J3hS8Boeg++Pr9BmUfU5r3m7qz1nty/X0cUO/6Vl/nYLxnWI/CffICRrU05fgXbJadtt1kg8tN3WFiPvWu59d9PQfstlX++00HZHRLbTvY8WNG5sNvPjD//aYDMm7MyF5dV9cnq7r+O37MyBz74p1qvu511vev/44bMzL//aYDc+LLp+bMN/4719rX17XcvrtMquv6euuA3bbqNs+GdC0yuqWp7vulVuP/dX8csNtWq0478eVTc+xhz97ApVYeeJz+hv03fF+Pbl617lrW2WXtx2r1bJRLe3ujE1AGq/bjo5vX6Zb17cO79gu17ltGtzTlw2/u/b4uafwPPnbd9oHqhNe9eKec+PLuv5O3ltcH3d236+u+nvbvugIGRndvOCfJyKZK3vmaPRqQqH5dry9rfc1/wG5b9epYp7t94qfe9fzssv2mG7xcpZKMbG7cWwprH1uN7+UxWi021Be1Hj+sffl6+qLWx7OrvvXFEOP4ggJb+zXxQKvl/ab1HcqsrzcG+tuQxq/nPbn+Pg6odX2Nfs+wtyrVqr8PPeyww5Jk1ccBu3P4B67O+Rt9K801jLs7OpIPPvWG/oo3JFWSbL3FuLR3VNO6rGPlD81MHJtXHLxD9t95Yv7x979l6tSpeXLpinzsG7dnzsIlqVZXbljbbDE+Z73lwLo+cdGdtvbO3HTXnPz45gczb/HTaW/vzIgRlbSMbMqE8aOzzRbj87w9p+R5z5myaqrZ1t6ZW+6el1vvmZ/HnliaJ55ako5qc5a1rVjjtjx398n5/X0P59Z75uep1rZsNLYlz91j8qp1dV33T2/5ZxY+tjRJ95d9YsnytLV3JpVKRo1sysbj1lzP6relK1d319fa2pr77rtv5Y+EDsJ3Ma+dZ9zokdl041F57Mnleaq1bb23KUluuXtebv7TnMxf+FiWdTSldXlnqtVqRrc054DdtszxL9k5f/774tzy53mZu2hJWpd1ZMyolX9Z/PTS9jz5dFvaO3p+LNe2pLUtl/z03tzxl4ezrK1j1fWd/Ipd1zgAXvu2jR3VlK03ac/RL9k7EzbZqMd17jt1izx7mwm562+Lun2sNqSWfRb9r9b7/f6PHqMrhqnVPznRNKKSnbffNIfsOSX3/OORdfbj40avu8/oaR++tiWtbfnmj/+SW/40L0vbOpJq0tw8IttuMT6vev6OOXTvbTa4r/v6NTNy811z0/avHwCvVJLNJ4zJa6c9O4ftv13a2jv/ve9a3pGmESuyzy5bpTJiRO6YsSCtyzv6dB+tftpO203Ioftsk3v+8cg6tz3Jvzv3yWV57MllWbKsIytWrMiIyoiMG9Oc5qYRWdbWmbGjmzN5s3GZsPGo3D/zkcxd9HRWrFh5JWNHN+d5z5mSN71qt27f0Fzbhjp6Q/dtbx/HLkta2/LNa+7JbTPmpXPFiIwe1beuSPRFI9R6nzu2GFjre8N59dfC9zz4RM7/9h+yrK3nT2CMHzMyr3jeM/LTW/6ZJUv7713ESpKNxrXkNdOelfFjW3L7jAWrXteOHd2crSaOybabdqzz+rI3+5mufdk1v/1H5i5cko6Oaq/2iQseWZKzL7wtcxY+veq0MaOacsL0nfOKg3dMkjX2ldVqNeNHVbPTDpPy0MNPZ87CJ9Pey7qoJBk9MlnenqxY7fTmpkoO2n2rtHdU8/Sy9m6PrW65e15+e9fc/H3u41nS2p4RlWTMqOZst9VGaWluyoJHW9c4bljS2pYnlyzLimolK6pJU1Ml40aPzIG7b7XO6//1qfX4YW319EVbe2d+cduDueY3D+SpZSu/f3yLiWPz0gO3S3PTiPz+3ocdW5REb+53xxcUTSXJcS99dl4zbeeGfaqru33ons/cNPPmz8+Cp0amdXnnGu9Bbag3utYxpqU5y9s7MvvhJVne3rnOezerH9ONbBqR5e0deXppR55e2p6OFSsy4l/HesnKgcDWk9Z8D2p978n193tG6+ulrvfR6n3PsFF9YXgRw4sulUqyybiW7PHsSfnHnMczf/HTqwYGW246KkvbqnliSds6l1n9GVTJyjdOpu6waT5wwr6ZuMm6v07fk8F+g72vypS3TFmTcuUdzKwOMBrD8GL4Gdk0IqNHNWXLzcatelPg1rvnr/GGyNhevsHRpUz7t6R8eROZE33RCI0eXmy2yaiMHdOcBYtb095R+2HelhPHZNstNkrr8o41Bq3jx6w86H/k8WWZt3hJHntyedo6OtJR5zcuNY1Yeeyw4l/HGM1NIzJq5IiMG9OS8WNHpnnEiDz25NI8vqRt1WA1Wbns6m+2J8nXr5mRW/40L8vbV4YZNbIph+w1Jaccsft698drb2O9/SOmNf6AabVh6tp/YPOH+xeuWmdHx4o0N4/I1pPG55XPe8YGh5895S2DsmUuW95EVwwVhhcMtkqSMaObc8ietf8xz9qKvs+Ur2+KOrzwtXlD0MjmSs479eDsvP3mq04r+gYCACMqyS47TMzpJ+3Xq+H3YHbcSw7YfkDXD7A++0/dIu8/Yd+63mwYCI0+vnjfcfvkfcft06d1tIxsyksO2L7mfXvLyKa8aN9t86J9t93gcr1ZJ8CGnHzW1fmvIfSF7yMqyfZTNs5jTy7Lk0vasqKbOXslyYimSjo7i/m31vUes9Si0d0KRWR4UTATNx6VT77zkH77SiQABs+Dc4v9w5YbjR2ZSRPGpKlpROYveipLlvXuT2eL9sYZwHBy1inPbXQEAAbZo08n2ajHxQppRCXZbJMxmTRhTDbZaFSvvvpyoBgOQPkYXgygaz99ZKMjADCI3vOZ3+b8fjq42HjcyHz6PS9oyDDbi3oAABjetpw4Op965wsK+4loYHgwvACAgth4VPLt/zH4BgAABs+0fSfnfScc0OgYAOswvACABtt6s9H5wv97cUM/Qg0AAAwtH/vPA7P3zls1OgZA3QwvAKDBvvpf0xsdAQAAGCJ8jTkwVIxodAAAAAAAoO/G+TNlYAgxvAAAAACAIeB7n/SpC2DoMLwAgAbykW4AAACAdRleAAAAAAAAhWJ4AQAAAAAAFIrhBQAAAAAAUCiGFwAAAAAAQKEYXgAAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAohhcAAAAAAEChGF4AAAAAAACFYngBAAAAAAAUiuEFAAAAAABQKIYXAAAAAABAoRheAAAAAAAAhWJ4AQAAAAAAFIrhBQAAAAAAUCiGFwAAAAAAQKEYXgAAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAohhcAAAAAAEChGF4AAAAAAACFYngBAAAAAAAUiuEFAAAAAABQKIYXAAAAAABAoRheAAAAAAAAhWJ4AQAAAAAAFIrhBQAAAAAAUCiGFwAAAAAAQKEYXgAAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAohhcAAAAAAEChGF4AAAAAAACFYngBAAAAAAAUiuEFAAAAAABQKIYXAAAAAABAoRheAAAAAAAAhWJ4AQAAAAAAFIrhBQAAAAAAUCiGFwAAAAAAQKEYXgAAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAohhcAAAAAUDATc2mamhqdAqBxDC8AAAAAoGDOGFdNpdLoFACNY3gBAAAAAAUzwrt2wDBnNwgAAAAAJbZiRaMTAPQ/wwsAAAAAKKlqNfnE09MaHQOg3xleAAAAAEBJdXYmj2abRscA6HeGFwAAAAAAQKEYXgAAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAohhcAAAAAAEChGF4AAAAAAACFYngBAAAAAAAUiuEFAAAAAABQKIYXAAAAAABAoRheAAAAAAAAhWJ4AQAAAAAAFIrhBQAAAAAAUCiGFwAAAAAAQKEYXgAAAAAAAIVieAEAAAAAABSK4QUAAAAAAFAozY0OsLaZM2fmjDPOyGOPPZbx48fnE5/4RJ797GevscyKFSvyyU9+Mr/97W/T1NSUCRMm5Jxzzsn222/foNQADDZ9AUBPdAUAtdAXAMVUuE9enHXWWTn22GNz3XXX5T/+4z9yxhlnrLPMjTfemD/+8Y+5+uqrc+211+a5z31uPvOZzzQgLQCNoi8A6ImuAKAW+gKgmAo1vHjkkUcyY8aMHHHEEUmS6dOnZ8GCBZk1a9Y6y7a1tWX58uWpVqtZsmRJttpqq8GOC0CD6AsAeqIrAKiFvgAorkJ9bdT8+fMzadKkNDevjFWpVDJ58uTMmzdvjY/hTZs2LbfffnsOOeSQjBs3LltuuWUuvfTSPl13tVpNa2trn9axtv5eX18sXbp0jf8WWZmyJuXKW6asSbnyDmbWarWaSqUy4NdTZI3qi6HeFV3KtO0l5cublC9z2fImMif6Yih1RVK8vrCNDbyy5U3Kl7lseRNdMRD0Rf8p+jYlX9/I1zdlz9eovijU8KJWM2bMyAMPPJDf/OY3GT9+fM4///x85CMfyfnnn1/3Otva2nLffff1Y8r0+/r6w8yZMxsdoWZlypqUK2+ZsiblyjsYWdva2jJq1KgBv56hoL/7Yrh0RZcybXtJ+fIm5ctctrzJ8M6sL2pThq5IitsXw3kbGyxly5uUL3PZ8ia6ohEa0Rfj61hvEfqi6NuUfH0jX9+UNV+j+qJQw4vJkydn0aJF6ejoSHNzc6rVaubPn58pU6assdyPfvSjHHTQQdl4442TJEcddVTe/OY39+m6W1paMnXq1A0sMafX69zw+gbX0qVLM3PmzOywww4ZM2ZMo+NsUJmyJuXKW6asSbnyDmbWlpaWAV1/GTSqL4Z6V3Qp07aXlC9vUr7MZcubyJzoi+J2RTIU+sI2NvDKljcpX+ay5U10xUAocl/Mvrb3621kXxR9m5Kvb+Trm7Lna1RfFGp4sdlmm2W33XbLNddck6OPPjrXXXddttxyyzU+ppck2267bW666aa8+c1vTktLS371q19lp5126tN1VyqVjB07tk/rWFt/r68/jBkzppC5ulOmrEm58pYpa1KuvIORdbh/rDtpXF8Ml67oUqZtLylf3qR8mcuWNxnemYd7XwylrkiK2xfDeRsbLGXLm5Qvc9nyJrqiP+mL/lf0bUq+vpGvb8qar1F9UajhRZKcffbZ+dCHPpQLLrgg48aNy3nnnZckOfPMMzNt2rQcdthhef3rX59//OMfOfLII9Pc3JxJkybl7LPPbnByAAaTvgCgJ7oCgFroC4BiKtzwYscdd8zll1++zunnnnvuqv/d0tKSc845ZzBjAVAw+gKAnugKAGqhLwCKaUSjAwAAAAAAAKzO8AIAAAAAACgUwwsAAAAAAKBQDC8AAAAAAIBCMbwAAAAAAAAKxfACAAAAAAAoFMMLAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACsXwAgAAAAAAKBTDCwAAAAAAoFAMLwAAAAAAgEIxvAAAAAAAAArF8AIAAAAAACgUwwsAAAAAAKBQDC8AAAAAAIBCMbwAAAAAAAAKxfACAAAAAAAoFMMLAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACsXwAgAAAAAAKBTDCwAAAAAAoFAMLwAAAAAAgEIxvAAAAAAAAArF8AIAAAAAACgUwwsAAAAAAKBQDC8AAAAAAIBCMbwAAAAAAAAKxfACAAAAAAAoFMMLAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACsXwAgAAAAAAKBTDCwAAAAAAoFAMLwAAAAAAgEIxvAAAAAAAAArF8AIAAAAAACgUwwsAAAAAAKBQDC8AAAAAAIBCMbwAAAAAAAAKxfACAAAAAAAoFMMLAAAAAACgUAwvajQxV6WpqdEpAAAAAABg6DO8qNEZ45akUml0CgAAAAAAGPoML2o0wj0FAAAAAACDwlvyA2DFikYnAAAAAACA8jK86GfVavKJpw9sdAwAAAAAACgtw4t+1tmZPJqdGx0DAAAAAABKy/ACAAAAAAAoFMMLAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACsXwAgAAAAAAKBTDCwAAAAAAoFAMLwAAAAAAgEIxvAAAAAAAAArF8AIAAAAAACgUwwsAAAAAAKBQDC8AAAAAAIBCMbwAAAAAAAAKxfACAAAAAAAoFMMLAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACsXwAgAAAAAAKBTDCwAAAAAAoFAMLwAAAAAAgEIxvAAAAAAAAArF8AIAAAAAACgUwwsAAAAAAKBQDC8AAAAAAIBCMbwAAAAAAAAKxfACAAAAAAAoFMMLAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACqVww4uZM2fmuOOOy/Tp03PMMcfkgQce6Ha5+++/PyeddFJe/vKX5+Uvf3muv/76QU4KQCPpCwB6oisAqIW+ACim5kYHWNtZZ52VY489NkcffXR+/vOf54wzzsiVV165xjJLly7Nqaeemk9+8pPZb7/90tnZmSeeeKJBiQFoBH0BQE90BQC10BcAxVSoT1488sgjmTFjRo444ogkyfTp07NgwYLMmjVrjeV+/OMfZ6+99sp+++2XJGlqasrEiRMHPS8AjaEvAOiJrgCgFvoCoLgK9cmL+fPnZ9KkSWluXhmrUqlk8uTJmTdvXrbffvtVy/39739PS0tL3vrWt2bBggXZeeedc8YZZ/SpNKrValpbW/t8G1bX3+vri6VLl67x3yIrU9akXHnLlDUpV97BzFqtVlOpVAb8eoqsUX0x1LuiS5m2vaR8eZPyZS5b3kTmRF8Mpa5IitcXtrGBV7a8Sfkyly1voisGgr7oP0XfpuTrG/n6puz5GtUXhRpe1KqzszO/+93v8v3vfz9bbLFFPvOZz+SjH/1ovvCFL9S9zra2ttx3333rPX98Hevc0PoaZebMmY2OULMyZU3KlbdMWZNy5R2MrG1tbRk1atSAX89Q0N990VNX1KOIXdGlTNteUr68Sfkyly1vMrwz64valKErkuL2xXDexgZL2fIm5ctctryJrmiERvRFWd+LKvo2JV/fyNc3Zc3XqL4o1PBi8uTJWbRoUTo6OtLc3JxqtZr58+dnypQp6yx34IEHZsstt0ySHHHEEXnLW97Sp+tuaWnJ1KlT13v+7Gt7v84NrW+wLV26NDNnzswOO+yQMWPGNDrOBpUpa1KuvGXKmpQr72BmbWlpGdD1l0Gj+qKnrkjm9HqdReqKLmXa9pLy5U3Kl7lseROZE31R3K5IhkJf2MYGXtnyJuXLXLa8ia4YCEXui7K9F1X0bUq+vpGvb8qer1F9UajhxWabbZbddtst11xzTY4++uhcd9112XLLLdf4mF6SvPzlL88VV1yRJUuWZPz48bnpppuyyy679Om6K5VKxo4d26d1rK2/19cfxowZU8hc3SlT1qRcecuUNSlX3sHIOtw/1p00ri+GS1d0KdO2l5Qvb1K+zGXLmwzvzMO9L4ZSVyTF7YvhvI0NlrLlTcqXuWx5E13Rn/RF/yv6NiVf38jXN2XN16i+KNTwIknOPvvsfOhDH8oFF1yQcePG5bzzzkuSnHnmmZk2bVoOO+ywTJkyJW9961tz3HHHpVKpZMstt8zHP/7xBicHYDDpCwB6oisAqIW+ACimPg8vHn300fz973/PwoUL09HR0e0yr371q2te34477pjLL798ndPPPffcddbZm/UC0Fj6AoCe6AoAaqEvAIaHuocXy5Yty8c//vFcffXV6ezs7HaZrl8ht2MHGL70BQA90RUA1EJfAAwvdQ8vzjnnnFx55ZXZeeedM3369EyaNCnNzYX7FioAGkxfANATXQFALfQFwPBS9x7++uuvz+67757LL788TU1N/ZkJgCFEXwDQE10BQC30BcDwMqLeC3Z2duaAAw5QFgBskL4AoCe6AoBa6AuA4aXu4cUee+yRWbNm9WcWAIYgfQFAT3QFALXQFwDDS93Di/e85z255ZZb8qtf/ao/8wAwxOgLAHqiKwCohb4AGF7q/s2LvffeO9/4xjdy6qmnZtddd80uu+yScePGrbNcpVLJO97xjj6FBKC89AUAPdEVANRCXwAML3UPLx577LF85jOfyRNPPJFbb701t956a7fLKQyA4U1fANATXQFALfQFwPBS9/DinHPOyR/+8IcceuihecUrXpEtttjCDyYBsA59AUBPdAUAtdAXAMNL3cOL3/72tznggANywQUX9GceAIYYfQFAT3QFALXQFwDDS90/2F2tVrP77rv3ZxYAhiB9AUBPdAUAtdAXAMNL3cOLffbZJ/fff39/ZgFgCNIXAPREVwBQC30BMLzUPbw47bTTcs899+Syyy7rzzwADDH6AoCe6AoAaqEvAIaXun/z4sILL8zOO++cc889N5deeml23nnnjBs3bp3lKpVK/ud//qdPIQEoL30BQE90BQC10BcAw0vdw4sf/vCHq/73rFmzMmvWrG6XUxgAw5u+AKAnugKAWugLgOGl7uHFDTfc0J85ABii9AUAPdEVANRCXwAML3UPL7beeuv+zAHAEKUvAOiJrgCgFvoCYHip+we7AQAAAAAABkLdn7z40Y9+VPOyr371q+u9GgBKTl8A0BNdAUAt9AXA8FL38OKMM85IpVLZ4DLVajWVSkVhAAxj+gKAnugKAGqhLwCGl7qHF+edd163pz/11FO599578+Mf/zjTpk3Li170orrDAVB++gKAnugKAGqhLwCGl7qHF0cdddQGz3/d616Xk08+Occff3y9VwHAEKAvAOiJrgCgFvoCYHgZsB/s3nvvvTNt2rR8/vOfH6irAGAI0BcA9ERXAFALfQEwtAzY8CJJpkyZkvvvv38grwKAIUBfANATXQFALfQFwNAxYMOLarWaO++8M6NGjRqoqwBgCNAXAPREVwBQC30BMLTU/ZsXv//977s9vaOjIw8//HCuvvrq3HPPPXn1q19d71UAMAToCwB6oisAqIW+ABhe6h5enHTSSalUKus9v1qtZp999skZZ5xR71UAMAToCwB6oisAqIW+ABhe6h5evOMd7+i2MCqVSjbZZJPsscce2XPPPfsUDoDy0xcA9GS4dcXEfCtNTY1OAVA+w60vAIa7uocX73rXu/ozBwBDlL4AoCfDrSvOGJds4A+HAViP4dYXAMPdgP1gNwAAAOsa0YujsBUrBi4HAAAUWd3Di/vvvz9XXHFFlixZsuq0ZcuW5SMf+Uie//zn5yUveUm++93v9ktIAMpLXwDQE13RvWo1+cTTjU4BUBz6AmB4qXt48ZWvfCWf//znM27cuFWnfeYzn8nll1+ep59+OvPnz8/HPvax3HLLLf0SFIBy0hcA9ERXdK+zM3k0b2h0DIDC0BcAw0vdw4u77747Bx544KofSuro6MhVV12V5zznObn11ltzww03ZOLEifnWt77Vb2EBKB99AUBPdAUAtdAXAMNL3cOLxx57LJMnT17173vuuSdLlizJcccdl1GjRmXLLbfMYYcdlr/+9a/9EhSActIXAPREVwBQC30BMLzUPbxoampKW1vbqn/fcccdqVQqOfDAA1edNmHChDz22GN9SwhAqekLAHqiKwCohb4AGF7qHl5svfXWuf3221f9++c//3m22WabbL311qtOe/jhhzNhwoQ+BQSg3PQFAD3RFQDUQl8ADC91Dy+OPPLI/PWvf81rX/vavP71r89f//rXvOpVr1pjmfvvvz/bb799n0MCUF76AoCe6AoAaqEvAIaXuocXJ554Yl72spdlxowZ+cMf/pAXvOAFedvb3rbq/AceeCB//etfc9BBB/VLUADKSV8A0BNdAUAt9AXA8NJc7wVbWlryuc99LkuWLEmSjB8/fo3zN9tss/zoRz9a46N7AAw/+gKAnugKAGqhLwCGl7qHF13WLoouEydOzMSJE/u6egCGCH0BQE90BQC10BcAw0OfhxdJsmLFiixevDgdHR3dnj9lypT+uBoASk5fANATXQFALfQFwNDXp+HF1VdfnW9+85v5xz/+kc7Ozm6XqVQquffee/tyNQCUnL4AoCe6AoBa6AuA4aPu4cU3vvGNnH/++Wlubs5+++2XSZMmpbm5Xz7IAcAQoi8A6ImuAKAW+gJgeKl7D3/ZZZdlyy23zPe+971stdVW/ZkJgCFEXwDQE10BQC30BcDwMqLeCz766KN56UtfqiwA2CB9AUBPdAUAtdAXAMNL3cOLHXbYIU8++WR/ZgFgCNIXAPREVwBQC30BMLzUPbx44xvfmBtuuCFz587tzzwADDH6AoCe6AoAaqEvAIaXun/z4qijjsojjzyS4447LieccEJ22WWXjB8/vttl999//7oDAlBu+gKAnugKAGqhLwCGl7qHF0myZMmSLFmyJF/4whc2uNx9993Xl6sBoOT0BQA90RUA1EJfAAwfdQ8vPv/5z+eCCy7IxIkT84pXvCKTJk1Kc3OfZiEADEH6AoCe6AoAaqEvAIaXuvfwV155ZXbYYYdcccUVGTduXH9mAmAI0RcA9ERXAFALfQEwvNT9g91PPvlkXvjCFyoLADZIXwDQE10BQC30BcDwUvfwYqeddsrChQv7MwsAQ5C+AKAnugKAWugLgOGl7uHF2972ttxwww35y1/+0p95ABhi9AUAPdEVANRCXwAML3X/5sWTTz6Zgw8+OMcdd1yOPPLI7LLLLhk/fny3y7761a+u92oAKDl9AUBPdAUAtdAXAMNL3cOLM844I5VKJdVqNVdccUWSpFKprLFMtVpNpVJRGADDmL4AoCe6AoBa6AuA4aXu4cV5553XnzkAGKL0BQA90RUA1EJfAAwvdQ8vjjrqqP7MAcAQpS8A6ImuAKAW+gJgeKn7B7sBAAAAAAAGQt2fvJg3b17Ny06ZMqXeqwGg5PQFAD3RFQDUQl8ADC91Dy+mTZu2zo8idadSqeTee++t92oAKDl9AUBPdAUAtdAXAMNL3cOLV7/61d0WxlNPPZW//vWvmTNnTvbff/9ss802fQoIQLnpCwB6oisAqIW+ABhe6h5efOITn1jvedVqNd/85jdz4YUX5n/+53/qvQoAhgB9AUBPdAUAtdAXAMPLgPxgd6VSyVve8pY861nPyqc+9amBuAoAhgB9AUBPdAUAtdAXAEPPgAwvuuy+++657bbbBvIqABgC9AUAPdEVANRCXwAMHQM6vJg9e3Y6OjoG8ioAGAL0BQA90RUA1EJfAAwddf/mxfqsWLEiDz/8cK666qrccMMNee5zn9vfVwHAEKAvAOiJrgCgFvoCYGiqe3ixyy67pFKprPf8arWaTTbZJKeffnq9VwHAEKAvAOiJrgCgFvoCYHipe3ix//77d3v6iBEjsskmm2T33XfPMccck80226zucACUn74AoCe6AoBa6AuA4aXu4cWll17anzkAGKL0BQA90RUA1EJfAAwvvf7B7q985Sv5zGc+k/b29vUu09bWls9+9rP52te+1qdwAJSXvgCgJ7oCgFroC4DhqVfDi9/97nf5whe+kAkTJmTkyJHrXa6lpSUTJkzIZz/72dx22219DglAuegLAHqiKwCohb4AGL56Nbz40Y9+lI033jgnnnhij8u+/vWvzyabbJKrrrqq7nAAlJO+AKAnugKAWugLgOGrV8OLu+66KwcffHBaWlp6XLalpSUHH3xw/vjHP9YdDoBy0hcA9ERXAFALfQEwfPVqeLFw4cJsu+22NS+/zTbbZNGiRb0OBUC56QsAeqIrAKiFvgAYvno1vBgxYsQGfxxpbe3t7Rkxote/CQ5AyekLAHqiKwCohb4AGL56tTffYost8sADD9S8/AMPPJAtttii16EAKDd9AUBPdAUAtdAXAMNXr4YX++67b2677bbMmTOnx2XnzJmT2267Lfvvv3/d4QAoJ30BQE90BQC10BcAw1evhhevf/3r09HRkXe/+9159NFH17vcY489lve85z3p7OzM8ccf36tAM2fOzHHHHZfp06fnmGOO2eB0vVqt5g1veEP222+/Xl0HAANLXwDQE10BQC30BcDw1dybhXfbbbecfPLJueSSS/LKV74yxx13XA488MBstdVWSZKHH344t956a77//e/n0UcfzZve9KbstttuvQp01lln5dhjj83RRx+dn//85znjjDNy5ZVXdrvsxRdfnO222y733ntvr64DgIGlLwDoia4AoBb6AmD46tXwIknOOOOMjBo1Kt/4xjfy1a9+NV/96lfXOL9araapqSlvfetb8973vrdX637kkUcyY8aMfPOb30ySTJ8+PR//+Mcza9asbL/99mss+8ADD+SXv/xlzjvvvPz85z/v7c0AYIDpCwB6oisAqIW+ABieej28qFQqef/735/XvOY1ufLKK3PXXXdl8eLFSZLNN988++yzT44++uhst912vQ4zf/78TJo0Kc3Nzauua/LkyZk3b94ahdHe3p4Pf/jDOffcczNiRK+++Wq9qtVqWltb+2VdXfp7fX2xdOnSNf5bZGXKmpQrb5myJuXKO5hZq9VqKpXKgF9PXw3FvhjqXdGlTNteUr68Sfkyly1vInNSjr7QFbUrWl/YxgZe2fIm5ctctrzJ8OyKRF/0RiP7oujblHx9I1/flD1fo/qi18OLLtttt13e97739WeWmn3pS1/KS17ykjzzmc+s6QebatHW1pb77rtvveePr2OdG1pfo8ycObPREWpWpqxJufKWKWtSrryDkbWtrS2jRo0a8OvpL0OpL3rqinoUsSu6lGnbS8qXNylf5rLlTYZ35jL1xXDriqFybJEM721ssJQtb1K+zGXLmwzPrkj0RS2K0BdF36bk6xv5+qas+RrVF3UPLwbC5MmTs2jRonR0dKS5uTnVajXz58/PlClT1lju97//febPn59vf/vb6ejoyJIlSzJt2rRcccUVmThxYl3X3dLSkqlTp673/NnX9n6dG1rfYFu6dGlmzpyZHXbYIWPGjGl0nA0qU9akXHnLlDUpV97BzNrS0jKg6y+DRvVFT12R9P4gpkhd0aVM215SvrxJ+TKXLW8ic6IvitsV5T+2SGxjg6FseZPyZS5b3kRXDAR90X+Kvk3J1zfy9U3Z8zWqLwo1vNhss82y22675ZprrsnRRx+d6667LltuueU63zH4ne98Z9X/njNnTl796lfnxhtv7NN1VyqVjB07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f//7VZer97yBzHvSSSdl2rRpq+7fiy++uOF53/zmN+fwww/PkUcemRNOOCH33ntvkmI+bymmoj7mOqP/s5epO5Ly9UdPmYvYIYkeoXZFfGyL3hVJ+fqibF2RlK8vytgVib6gdo1+bAdinzAQrrzyyuy888755S9/WahsbW1t+djHPpaXvvSlOfzww/PBD34wSXG255tuuilHHXVUjjzyyLzqVa/KD3/4wySNu/+K3vPd5dvQNpIM7n25vvuvy9rbyWDnq1mVupx00knVK6+8slqtVqs/+9nPqkcffXRD87zoRS+q3nvvveucvqGcg3kb7rjjjur8+fPXyVlvvoHMvr6s67uPG5l12bJl1V//+tfVFStWVKvVavXSSy+tnnjiidVqtVo944wzql/4wheq1Wq1+uc//7n6/Oc/v9rW1tan8wYy74knnlj9xS9+0e3lGpX3iSeeWPW/r7/++urhhx9erVaL+bylmIr6mOuM/s9epu6oVsvXHz1lLmKHVKt6hNoV8bEteldUq+Xri7J1RbVavr4oY1dUq/qC2jX6sR2IfUJ/mz17dvV1r3td9dhjj121zRcl27nnnlv92Mc+tur+W7hwYbVaLcb2vGLFiur+++9fve+++6rV6sr7cffdd68+9dRTDbv/it7z3eXb0DZSrQ7uc3F991+12v12Mtj5amV4UYfFixdX995772p7e3u1Wl25gR988MHVmTNnNixTd0/EDeVs1G1YPWe9+QYre60HFUXI2uXuu++uvuhFL6pWq9XqXnvttaoIq9Vq9ZhjjqnecsstfTpvIPNu6GCiCHmvvPLK6hFHHFH45y3FUeTHXGcMXPYydke1Wr7+WDtz0TukWtUjrF9RH9uydMXaWcuwjZW1K6rV8vVF2bqiWtUXrF8RH9v+2Cf0p87OzurJJ59cveeee9bY5ouQ7emnn67uvffe1aeeemqN04uyPa9YsaJ6wAEHVO+4445qtVqt3nfffdVDDjmkunz58obff0Xv+Q39EcLq20i12pjn4tr51redNCpfT5oH5/MdQ8v8+fMzadKkNDevvPsqlUomT56cefPmZfvtt29YrtNOOy1Jsscee+SDH/zgBnNutNFGDb8N9eZrZPa17+OJEycW6n7+1re+lWnTpuWxxx5Le3t7Jk2atOq8rbfeOvPmzav7vIHQlbfL+eefn89//vN55jOfmQ984APZdtttG573tNNOy+23354k+drXvlbK5y2NUdSu6KIzBi970bsjKV9/rJ65SxE7JNEj9KzIfVG2rkjK2xdl6IqkfH1Rlq5I9AU9K2Jf9HWf0N8uuuii7LPPPtl9991XnVaUbA899FAmTJiQr371q/nd736X0aNH513veldhtudKpZLPfvazeec735mxY8fmiSeeyJe+9KU8/fTThbj/upRt37h6DxXludjddlKkfGvzmxdDxGWXXZZrr702V111VTbddNOcfvrpjY405BT9Pv7qV7+ahx56KB/4wAcaHaUma+f91Kc+lZ///Oe55pprst9+++Wtb31rgxOu9KlPfSo33XRT3vve9+b8889vdBzoF0Xfnw0lZbivy9YfSXk6JNEjlFcZ9l9DRVnu67L1RZm6ItEXlE/R9gl/+9vfcv311+ftb397o6N0q7OzM3Pnzs2znvWsXHXVVfnv//7vvPe9701nZ2ejoyVJOjo68pWvfCVf+tKX8qtf/SoXX3xxTjvttMLkK6OibSNJ8beT7hhe1GHy5MlZtGhROjo6kiTVajXz58/PlClTGpap67pHjhyZk08+OXfeeecGcxbhNtSbr1HZu7uP+3I7+tM3vvGNXH/99fn617+eMWPGZNNNN01zc3MWLVq0apm5c+dmypQpdZ83kHmTlfdjsnL6feKJJ2b27Nl57LHHCpE3SY466qjcfvvt2WqrrUr1vKVxivyY64zBy17k7kjK1x/dZU6K3yGJHmH9ivrYlrErknL2RdG7IilfX5S1KxJ9wfoV6bHtr31Cf7rzzjszd+7cTJ8+PdOmTcuf/vSnfPjDH87PfvazhmdLVj5+I0aMyOGHH54k2XXXXbPNNttk7ty5hdie77vvvixcuDD7779/kuQ5z3lOttxyy9x///2FuP+6lKXnu+uhIm8n3/nOdwqRrzuGF3XYbLPNsttuu+Waa65Jklx33XXZcsstG/YxvdbW1jz55JOr/v2Tn/wku+666wZzFuE21JuvEdnXdx/35Xb0l4suuig/+clPctFFF2XjjTdedfrLXvayfO9730uS3H333Xn44YdXlVC95w1U3o6OjixevHjVMtddd10233zzbLrppg3L++STT+bhhx9e9e9f/vKXmTBhQqmetzRWUR9znTF42YvcHUn5+mN9mYvYIYkeoXZFfGzL2hVJ+fqi6F2RlK8vytQVib6gdkV5bPt7n9BfTjjhhNx888258cYbc+ONN2avvfbKxz/+8ZxwwgkNz5YkEydOzHOf+9zcfPPNSZLZs2dnzpw52XfffQuxPU+ePDkLFy7MP/7xjyTJrFmzMnv27DzjGc8oxP3XpQz7xvVtI0mxt5Mi5OtOpVqtVgf8WoagBx98MB/60Ify+OOPZ9y4cTnvvPOy8847NyTL7Nmz8653vWvVR7m22WabnHnmmdlmm202mHMwb8NZZ52VX//611m8eHEmTJiQcePG5Re/+EXd+QYye3dZv/nNb673Pm5k1gULFuTQQw/Ntttum3HjxiVJWlpa8oMf/CCLFy/Oaaedljlz5mTkyJH58Ic/nIMOOihJ6j5voPJecsklOfHEE9Pe3p5KpZJNN900H/rQh7LLLrs0LO/cuXPznve8J8uXL0+lUsnEiRNz+umnZ+rUqYV83lJMRXzMdcbAZC9TdyTl648NZS5ihyR6hN4p2mNbhq5IytcXZeuKpHx9UbauSPQFvdPox3Yg9gkD5aSTTsrJJ5+cF7/4xYXJNnv27PzXf/1XHn/88VQqlbzjHe/I9OnTC7M9//jHP84FF1yQSqWSarWa//zP/8zhhx/esPuv6D3fXb5LL710vdtIMrh9s777b3WrbyeDna9WhhcAAAAAAECh+NooAAAAAACgUAwvAAAAAACAQjG8AAAAAAAACsXwAgAAAAAAKBTDCwAAAAAAoFAMLwAAAAAAgEIxvAAAAAAAAAqludEBoOhmzJiR73znO7nzzjuzcOHCrFixIltssUX23nvvvPrVr87znve8JMkjjzySK664In/5y18yY8aMzJ07N0ly//33b3D9d999d774xS/mrrvuSkdHR3baaae88Y1vzCte8YoBv20A9J+B7Iurr746f/jDHzJjxoz87W9/S3t7e84777wcffTRg3LbAOgfA9UVDz/8cH72s5/lN7/5TR588MEsXrw4m2yySfbZZ5+ccsop2XPPPQftNgLQdwP9XtTqvva1r+XTn/50kuTyyy/PXnvt1e+3B+pleAHrsWLFinzyk5/MxRdfnObm5hx00EGZNm1ampubM3v27Nx000255ppr8u53vzvveMc78ve//z2f+cxnUqlUsv3222fMmDFZunTpBq/jtttuyymnnJKWlpa88pWvzLhx43L99dfnfe97XxYsWJA3v/nNg3RrAajXYPTF5z//+cydOzebbrpptthii1UHJQCUw0B3xaWXXpqvf/3r2W677fK85z0vEydOzKxZs/LLX/4yv/zlL/PpT3/aH0cBlMBgHFus7m9/+1u++MUvZuzYsWltbR3AWwb1MbyA9fjc5z6Xiy++OFOnTs0XvvCFbLfddmucv2zZslx22WV5/PHHkyTPfOYzc9lll2Xq1KkZP358Xvayl+Wf//znetff0dGRD3/4w6lUKvn2t7+dqVOnJkne8Y535DWveU0+85nPZPr06dl6660H7DYC0HcD3RdJcs4552T77bfP1ltvvcZfRgFQDgPdFc95znNy6aWX5oADDljj9DvvvDNvfOMb89GPfjQvfvGL09LS0u+3DYD+MxjHFl3a29tzxhlnZOrUqdl+++1zzTXX9PfNgT4zvIBuzJo1KxdeeGEmTJiQCy+8MJtvvvk6y4wePTqnnHJK2trakiSbb755t8utz2233ZaHHnooRx999KrBRZJstNFGedvb3pYzzjgjP/zhD/POd76z7zcIgAExGH2RJAcffHC/5AVg8A1GV7z0pS/t9vT99tsvBx54YG6++ebcf//92WOPPeq7EQAMuME6tujy1a9+NQ888EB++MMf5sILL+xTdhgofrAbunHVVVels7Mzxx13XI8lUO9fL91xxx1JkkMOOWSd87pO+/3vf1/XugEYHIPRFwCUW6O7orm5eY3/AlBMg9kXf/nLX/LVr34173znO/OsZz2rT+uCgWR4Ad344x//mCQ56KCDBuw6Zs6cmSTZfvvt1zlv0qRJGTt2bGbNmjVg1w9A3w1GXwBQbo3sinnz5uV3v/tdJk2alJ122mnQrx/g/7N33/FR1Pkfx9+TTQIpCIQaiiCedLuA3RP0UFRUVAR711PPcvrTKJZDRbg7bNfU07N7ihUQPVHx1FMpthNQ5NAYpISOQApsspnfHzGRJJts3+93dl/Px0OB3cnMeyYz89mZz84MwpeseuH3+3XjjTeqf//+uuiiixI6LSBWfPUCCGLDhg2SpC5duiRsGmVlZZJqbxMVTH5+vrZt25aw6QMAYpeMegEA8DZTtaKqqko33HCD/H6/rr/+evl8vqROHwAQmWTViwceeEAlJSV65ZVXqA2wHldeAAAAAACQQmpqalRUVKRPPvlEY8eO1UknnWQ6EgDAAl988YUee+wx/frXv+aKPHgCzQsgiLp7C65duzZh08jPz5ekZq+uKCsra/aqDACAHZJRLwAA3pbsWlFTU6Obb75Zs2bN0ujRozVx4sSkTBcAEJtE14vq6moVFRWpX79+uuSSSxIyDSDeaF4AQey3336SpHnz5iVsGr1795akoM+1WL9+vSoqKoI+DwMAYI9k1AsAgLcls1bU1NTopptu0quvvqrjjz9eU6ZMUUYGh/0A4AWJrhcVFRUqKSnRkiVLNHjwYPXr16/+v1dffVWSdPrpp6tfv3565513EpIBiBSfYoAgxowZI5/Pp2nTpmnTpk0tDuv3+6OaxpAhQyRJH374YZP36l6rGwYAYKdk1AsAgLclq1bUNS6mT5+uUaNG6Q9/+AP3MgcAD0l0vcjOztapp54a9L+6L9gOHz5cp556qrp37x7NLABxR/MCCKJXr1666KKLtHnzZl100UVasWJFk2F27Nihxx9/XH/+85+jmsZBBx2knj17atasWVqyZEn969u2bdNDDz2krKws7k0LAJZLRr0AAHhbMmpF3a2ipk+frmOOOUZ//OMfaVwAgMckul60bt1akyZNCvrfvvvuK0m69NJLNWnSJA0YMCDm+QHiIdN0AMBW11xzjXbs2KEnnnhCxx57rIYNG6a+ffsqMzNTK1eu1Mcff6wff/xR11xzTf3PFBUV1f99/fr1TV67+OKLtfvuu0uSMjMzddddd+miiy7SmWeeqeOOO055eXl66623tGrVKt14443q0aNHcmYWABC1RNcLSXrxxRf12WefSZL+97//1b+2YMECSdL++++v0047LWHzCACITaJrxV//+le9+uqrys3NVe/evfXggw82yXDUUUdxMgoALJeMYwvASxzXdV3TIQCbLVq0SM8995w+/fRTrV27VjU1NerUqZP23XdfnXLKKTr44IPrh+3Xr1+L43rqqac0bNiwBq8tXLhQf/rTn/TFF1+ourpaffv21fnnn69Ro0YlZH4AAImRyHpRVFRUfx/aYE4++WRNmTIl9pkAACRUompFqDohSZMnT9aYMWNinwkAQMIl+lxUY3V1ZNq0adpnn33iMQtAXNC8AAAAAAAAAAAAVuGZFwAAAAAAAAAAwCo0LwAAAAAAAAAAgFVoXgAAAAAAAAAAAKvQvAAAAAAAAAAAAFaheQEAAAAAAAAAAKxC8wIAAAAAAAAAAFiF5gUAAAAAAAAAALAKzQsAAAAAAAAAAGAVmhcAAAAAAAAAAMAqNC8AAAAAAAAAAIBVaF4AAAAAAAAAAACr0LwAAAAAAAAAAABWyTQdAIkVCARUVVVlOgZgRFZWlnw+n+kYgCdQL5DOqBdAeKgVSGfUCiB81AukM+pFfNG8SFGu62rNmjX68ccfTUcBjGrXrp26du0qx3FMRwGsRL0AalEvgOZRK4Ba1AqgZdQLoBb1In5oXqSoumLRuXNn5ebmsrEg7biuq4qKCq1bt06SVFhYaDgRYCfqBdId9QIIjVqBdEetAMJDvUC6o17EH82LFBQIBOqLRYcOHUzHAYzJycmRJK1bt06dO3fmsj2gEeoFUIt6ATSPWgHUolYALaNeALWoF/HFA7tTUN19BXNzcw0nAcyr2w643ybQFPUC+Bn1AgiOWgH8jFoBNI96AfyMehE/NC9SGJfnAWwHQDjYTgC2AyAUthGA7QAIB9sJwHYQTzQvAAAAAAAAAACAVWhewHp//vOf1a9fv/r/hg0bpvHjx+v9999PyPTOPvtsXXrppQkZdypr/Huq++/4448P6+eHDx+uO+64I8EpAaQqaoV3UC8AmES98AZqBQCTqBXeQb1IfTywGyH5qwL68MvVmre4VNsq/GqTm60DBxfq0L27KTsrOQ+dad26tZ588klJtQ+8eeihh3TZZZfp2Wef1X777ZeUDAht59/Tzq8BSH3UCkSCegGkL+oFwkWtANIXtQKRoF6kNpoXaNH8xaW67/kvVF5ZJceRXFdyHGnuolL9ffoi/Xb8fho6qGvCc2RkZGifffap//fee++tI444QtOnT6do7MR1a1S9ZYNcf6Wc7Bxltu0ox0neBVaNf08A0gO1wnuoFwBMoF54C7UCgAnUCu+hXiCRaF6gWfMXl2rSEwskt/bfbqM/KyqrdNfj8zXhvKEaNrgwqdm6dOmigoICrV69uv61L774Qvfdd58WLlwon8+nX/7yl7r55pvVoUOH+mGmTp2q999/XytXrlR+fr6GDBmioqIide7cOan5E8G/YaXKl85X1YZVqqn2KyMzW1kduyuv3zBld+xhLFdFRYWmTp2qjz76SGvWrFGHDh106KGH6v/+7//Upk2bZn9u8+bNuuiii+S6rh599FEVFBTou+++09SpU7VgwQIFAgENHTpUt9xyi3bdddckzhGAnVErvId6AcAE6oW3UCsAmECt8B7qBRKNZ14gKH9VQPc9/4Xk1teMJtyf/nf/81/IXxVIYjqpvLxcW7ZsUY8etTvCL774QmeffbbatGmj++67T3feeacWLVqkyy+/vMHPbdy4UZdeeqkefvhhTZgwQatWrdLZZ5+t6urqpOaPN/+Gldqy4HX51xQrI7eNsjp0U0ZuG/nXFNe+vmFl0rJUV1c3+G/79u0KBAK69tpr9cgjj+jqq6/WJ5980uR3s7P169frnHPOUXZ2tp588kkVFBRoxYoVGjdunLZs2aIpU6Zo6tSp2rRpk8477zz5/f6kzR+An1ErvId6Qb0ATKBeeAu1gloBmECt8B7qBfUiGbjyAkF9+OVqlVdWhRzOlVRWWaWPFq7Wkfv3TGimuh37unXr9Mc//lF5eXk655xzJEn33HOPBg8erL/85S9yHEeS1LdvXx1//PF6//33dcQRR0iSJk+eXD++QCCgfffdV4cffrjmzZunQw89NKH5E8V1a1S+dL5qKrcqs2PP+vl3WuXK6dhT1RtWqHzpAmV16Jbwy/YqKio0aNCgBq/94Q9/0MSJE+v/XV1drR49euiMM87Q999/r912263B8KtXr9Z5552n7t27669//atyc3MlSX/5y1/Utm1bPf7442rVqpUkab/99tOIESP04osv6swzz0zovAFoilrhLdQL6gVgCvXCO6gV1ArAFGqFt1AvqBfJQvMCQc1bXFp/b8FQ6u49mMii0XhH5PP59Le//U19+vRRZWWlPv/8c91www0KBH7uvPfu3VuFhYVatGhRfdF4//339eCDD2rZsmUqKyurH7akpMSzRaN6ywZVbVgl3y4d64tFHcdx5Nulo6o2rFT1lg3KapfYyxJbt26tZ555psFrPXv21PTp0/XEE09o+fLlqqioqH+vpKSkQcH44YcfdOaZZ6p///564IEHlJ2dXf/eRx99pFGjRsnn89V/gNhll100cOBALV68OKHzBSA4aoW3UC+oF4Ap1AvvoFZQKwBTqBXeQr2gXiQLzQsEta3CH1bBkGoLy7aKxF4qVbcjcl1XJSUluueee3TjjTfqtddek+u6CgQCmjx5coOOdp3S0lJJ0sKFC3X55ZdrxIgRuvjii9WhQwc5jqOxY8dqx44dCc2fSK6/UjXVfvmyWgV938lqpZrARrn+yoRnycjI0J577tng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eXODed++fbtWrFihjz/+WL/5zW+StpyiqZmJXmbBMrW0XklK+LrV3HJqbr2SzCynltardu3aGd0GkRxPPfWUXnjhBTmOI0m66KKLdOKJJxpO1TzTNSsWofZLXtH486gX+P1+TZkyRR9++KFatWqlfv36aerUqaZjheX999/X/fffr5qaGgUCAV144YU6+eSTTcdqVqofWyMxbF8/Wvr8ZoIXtrNoPgsnixfOkdl6jLyzdDkP1ywX1jr77LPdl19+2XVd1/3Xv/7ljhkzxnCi2C1YsMAtLS11jzzySPfrr7+ufz1V5nX79u3ue++959bU1Liu67pPP/20e9ZZZ7mu67pFRUXun/70J9d1XffLL790DzvsMNfv9xvLGq0tW7bU//2tt95yTzjhBNd1U+d36Lquu2LFCvf00093x44d67799tuu66bO7w9mmd5OWtpHnXXWWfXre7I1rgl1TC+vOo8++qh76aWXuq6b3OUUTc1M9DILlqml9cp1E7/MmltOza1XrmtmOTW283rluma3QSTHxx9/7G7dutV1XdddvXq1O3ToUHf58uWGUzXPln1wNELtl7wg2OdRL5g0aZJ7xx131C/7devWGU4UnpqaGnfIkCHukiVLXNetXf6DBw92t23bZjhZ81L92BqJYfv60dJnJxO8sJ1F81k4WbxwjszWY+SdpcN5uJZw2yhLbdy4UYsXL9bo0aMlSSNHjtSaNWu0fPlyw8liM2TIEHXt2rXBa6k0r61atdIRRxxR/426vffeW6tWrZIkvfnmmxo3bpwkaa+99lLnzp31ySefGMsarV122aX+79u2bZPjOCn1O6ypqdEtt9yiW265RdnZ2fWvp8rvD+bYsJ20tI+yjQ3Lq85LL72kU089NenTjbRmJmOZBctker0KlqklppZTY6bWK5hz0EEH1X9zr7CwUJ06dVJpaanhVMHZtA+Ohun9Uqya+zxqu4qKCr300ku69tpr65d9p06dDKcKn+M42rZtmySprKxM7dq1s3r5p/qxNeKP9SNyXtjOIv0snExeOEfmhc8MqX4eLhSaF5YqLS1Vp06dlJlZe2cvx3FUWFio1atXG04Wf6k8r0899ZSGDx+uzZs3q6qqqsGH9+7du3t2Hm+44QYdccQReuCBB/SHP/whpX6Hjz/+uPbbbz8NHjy4/rVU+/3BDBu3k7p9VJ2pU6fq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e+45zZw5UytXrpTruurWrZuOPfZYnXXWWWrTpk2Tn/n+++91//33a968eaqsrFTv3r01btw4jR8/Xo7jxG9BAACaZXut2Nkbb7yha6+9VpJ077336rjjjothzgEAkbC5Xpx99tlasGBB0Dzdu3fXu+++G8OcA9GheYG0deqpp2rWrFl6+eWXWywYs2bN0vbt23XSSSdp7dq1uuqqq5Sbm6uDDjpIw4cP17Zt2/Tvf/9bEydO1AcffKAHH3ywwcmio446St27dw867scee0wVFRU67LDDGrw+ZcoUPf744+rUqZNOOOEEZWZm6v3339dNN92kZcuW6cYbb4zPQgAAhJSselFVVaVzzjlHX375pQYMGKCTTz5ZkjR//nzdf//9ev311/Xiiy8qJyen/me+/fZbjRs3Ttu3b9exxx6rzp076/3339fEiRP13Xff6dZbb03cggEA1LO5Vuxs/fr1mjhxonJzc1VRURHfhQAACMkL9eLKK69s8lqoxjiQMC6Qpmpqatzhw4e7/fv3d1etWtXscKeeeqrbt29fd+HChe6aNWvcZ555xi0vL28wTHl5uTtmzBi3b9++7htvvBHW9BctWuT27dvXPf744xu8vnDhQrdv377u0Ucf7W7evLnBNE455RS3b9++7ueffx7+jAIAYpKsevH666+7ffv2da+44oom4/71r3/t9u3b13311VcbvH7mmWe6ffv2dd97773613bs2OGeccYZ1AsASCKba8XOLr30UvfII490p0yZ4vbt29edNWtWZDMKAIiJzfXirLPOcvv27Rv9zAEJwDMvkLYcx9GYMWNUU1OjV155Jegwy5Yt08KFC9WvXz/tueee6tKli84880zl5uY2GC43N1fnn3++JOmTTz4Ja/ovvfSSpNqu+87mzJkjSTr33HPVrl27BtO47LLLJEnPP/98WNMAAMQuWfVi5cqVkqTDDz+8yfh/+ctfSpI2bdpU/9r333+vTz75RMOGDdMRRxxR/3p2drauvvpqSdILL7wQ4dwCAKJha63Y2SuvvKJ///vfmjRpUpNpAgCSwwv1ArAJzQuktTFjxigjI0OvvPKKXNdt8n5dIWncYAgmM7P2LmzB7jPY2Pbt2zVr1ixlZ2frxBNPbPDehg0bJEk9evRo8nN1r82bNy/kNAAA8ZOMerHHHntIkj744IMmP/Pee+/JcRwNGzas/rW6+9EeeuihTYbff//9lZubG3ZDHQAQOxtrRZ3S0lLdfffdOv3003XQQQeFnhkAQMLYXC+k2mewPvTQQ3riiSc0f/581dTUhMwBJArPvEBaKyws1CGHHKL//Oc/mjdvXoMP8tXV1Zo5c6ays7M1evTokON6+eWXJQU/idTYm2++qW3btum4445rcHWFJLVv317Sz13yndW9tmbNGlVWVjZ7L1sAQHwlo1788pe/1FFHHaW3335bJ510koYOHSqp9r60K1eu1J133qlBgwbVD19SUiJJ6tWrV5Np+Hw+9ejRQ99++62qq6vrD2oAAIljY62QJNd1NWHCBOXn5+uGG26IdTYBADGytV7Uuf766xv8u3fv3po6dar23HPPiOYTiAeuvEDaq+tk193Gqc57772nDRs2aMSIEU0aDI1NmzZNH3zwgQ488MAGt+5oTl1xOe2005q8V3dJ31NPPaWtW7fWv15ZWam///3v9f/etm1byOkAAOIn0fXCcRz9+c9/1sUXX6xvvvlGTz75pJ588kl98803Ovroo3XwwQc3GL6srExS8w/Py8vLU01NjcrLyyOZTQBADGyrFZL03HPP6aOPPtKdd96p/Pz82GYQABAXNtaLESNG6OGHH9YHH3ygL7/8Um+88YbOOeccrVixQhdccIFWr14d20wDUeBreEh7I0aMUEFBgd555x1t27at/iRQc8+kaOzf//637rzzTnXv3l1//OMfQ05v+fLl+uSTT9SjRw8deOCBTd4fMmSITjzxRM2YMUOjRo3S8OHDlZWVpffff1+BQEBt2rTRtm3blJFB7xEAkinR9aKyslK//e1vtXDhQt17773138CaO3euJk2apA8++EAvvPBC0NsKAgDsYFutWLFihf74xz/qlFNO0WGHHRbPWQUAxMC2eiFJ5513XoNx7L777vVX7v3tb3/TY489pltuuSWW2QYixtlPpL2srCydeOKJ2r59u1577TVJ0vr16/Wf//xH3bp1C9qNrvP+++/rqquuUocOHfTkk0+qc+fOIaf38ssvy3VdnXLKKXIcJ+gwU6ZM0YQJE1RQUKBXX31VM2fO1J577qlnn31WgUBAmZmZatu2bXQzDACISqLrxUMPPaR3331Xd9xxh0aNGqX27durffv2GjVqlCZOnKiNGzfqoYceqh++7tuzzV2JV15eLsdxlJeX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idKjvr7e/cc//uHG43HXdV33T3/6k3vmmWcaTpV+y5Ytc0899VR30qRJ7quvvmo6TlpNmzbNvf7665u3gTVr1hhOhHSzbd63dT62fb60cR6zdX6Jx+PumDFj3MWLF7uu2/TY7bHHHu7WrVvTnuWdd95xq6qq3G9961vuokWLmn9uej9oK5ft+wAyi+lt3E+27sdd1dE+X15e7v7mN79xXdd1P/zwQ/fQQw91I5GIsazJ2Lx5c/PfX3nlFfe4445zXTfzn7dt2npdkA3PG+yQzv0kmTnW73zJzoep2ueSmb9S8ZwlOs+k6vHYcdvYJt2PR3vvfdKdY3v333+/e9FFF7mum97npqP3Wya2ET9w5IVFDjroIHXv3l2SVFpaqn79+qmqqspwqtRav369Fi5cqOOPP16SNGHCBK1atSonvk2Yn5+vww8/XI7jSJL23ntvrVixwnCq9IrH47r66qt19dVXKxwOm46TVrW1tXryySd1+eWXN28D/fr1M5wK6WbTvG/zfGzzfGnjPGb7/OI4jrZu3SpJqq6uVq9evYw8dmPGjNHAgQNb/MyG/aCtXDbvA8gsNmzjfrJ1P+6qjvb5l19+Waeddpokaa+99lL//v3t+nakBz169Gj++9atW+U4TlY8b1L7rwuy4XmDeeneTxKdY1ORL9n5MFX7XKLzVyoek2TmmXTOQel+PNp775PuHDt68skndcopp0hK/3PT3vstW7aRRIVMB0Db3nrrLW3evFl77rmn6SgpVVVVpX79+ikUatoUHcdRaWmpVq5cqWHDhhlOl16zZs3SuHHjTMdIqwceeED77bef9thjD9NR0u6LL75Qr169dPfdd+utt95St27ddNlll+mggw4yHQ2GmJ73M2k+tmm+tHEes3l+cRxHM2fO1A9/+EMVFhZq8+bNuvPOO61p/GTKfmDTPoDMkinbeFdk4xi37fMbN25UY2Nji4b04MGDtXLlSoPpknPllVdq/vz5kqR77703a563tl4XZNPzBrNs2E86ytC9e/eU5/MyH6Z6n0tk/krFY5LoPJOOx0OS9txzT11xxRVpfzzae+/T0X2lelt9//33tWXLFn3zm99M+3PT3vutmpoaY9tIV9G8SKNTTz1VlZWVbf7u2WefVWlpqSTp008/1ZQpUzRz5kwVFhamMSFMufvuu/XFF1/owQcfNB0lbf773//qlVde0cMPP2w6ihGxWEwrVqzQ17/+dV1xxRVatGiRzj33XL344ovq27ev6XjwCfO+/2yaL22dx2yeX6LRqO666y7deeedGjNmjD766CNdcskleu6551RSUmI0W6awaR8AkHrb7/P19fWm4/jmpptukiQ988wzuuWWW/TjH//YcKKus/V1AZAtbJkPTc5fts0zDz/8sAYNGqTGxkbdfvvtuuqqq9I+n7f33ufee+9Na47tPfnkk5o4cWJzcySd2nu/9eyzz6Y9i19oXqTR448/3ukyn332mS6++GL96le/0ujRo9OQyqzS0lKtXbtW0WhUoVBIruuqqqpKgwYNMh0tbf7whz/olVde0YMPPqiCggLTcdLmvffe04oVKzRhwgRJ0tq1a/XZZ59pzZo1Ov300w2nS73S0lIFAgEdd9xxkqTdd99dQ4YM0X//+1/jHy7CP5k072fCfGzbfGnrPGbz/LJ48WKtWbNGY8aMkdR0SPKAAQO0ePFifeMb3zCaTbJ/P7BtH0DmsX0b90M2jXHHfb6goEChUEhr165t/nbkihUrMnJs25x44om69tprNXDgwIx/3tp7XXDZZZdl3fMGM2yY3zrKUFxcnLJ8icyHvXv3Tss+52X+8vsxSWaeSeXjsW0deXl5+t73vqcJEyakfRtp773PihUrjGyrNTU1+utf/6onn3xSkjp8/FPx3LT3fuvTTz81vs8ki2teWOTzzz/X97//fV1//fVWvIFPhz59+mjUqFF67rnnJElz5szRgAEDMurQ4K544IEH9OKLL+qBBx5oce7EXHD66afrjTfe0N/+9jf97W9/0z777KMbbrghJxoXklRSUqKDDjpIb7zxhiRp2bJlWr58ub72ta8ZToZ0smnet30+tnG+tHUes3l+KS0t1Zo1a/T5559LkpYuXaply5Zp5513Npysic37gY37ADKPzdu4X7JljO3t80cddZT+/Oc/S5I++ugjrV69uvkDikywZcsWrV69uvnfr732mnr16pUVz1tHrwsy/XmDHWzYTzrKkKp8ycyHqdjnkpm//H5Mkp1nUvF41NbWasuWLc3/fvHFF7X77runfRtp773P/vvvn/ZtVZJeeukl7bbbbi3ee6Xzueno/Va6txG/OK7ruqZDoMm5556rhQsXtuhsXXHFFTr00EMNpkq9iooKTZkyRZs2bVJRUZGmT5+uESNGmI6Vcqv+n707D5OjLtcG/HRmMiELEBJCCAkSEQJhkX0TFAlojiDIohBWd3HD/QAeFEVFUFFE8Qie44K4gYBs+oHsILIpCESWw2KQQEISCEvWycz090ecmJCZTM/WXTNz39cFSXqqq96qrvo9XfVOd82enb333jsbb7xxhg8fniRpaGjIb3/72xpXVhvHHnts3v3ud2e//fardSlV8/TTT+e//uu/8uKLL6ZUKuVjH/vYit+gYGAo2rhf1PG4r4yXRRrHijy+XH311Tn//PNTKpVSLpfzoQ99aMVvSlXTqaeemptvvjnz5s3LyJEjM3z48Fx33XU1Pw7aquvCCy/sE8cAfUOt9/GeVNTjuLvWlHvz5s3LiSeemJkzZ2bw4MH54he/mN13373GFVfumWeeySc/+cksXbo0pVIpo0aNykknnZTJkyf3+dft1VZ+X9DXXzeKo5rHSVfG2J6ur6vjYW8cc10dv3rzNat0nOmN7fH000/nhBNOSHNzc5JkwoQJOeWUUzJhwoSqb4/2zn1q8bpMmzYt73rXu3LYYYeteKzar01751vVrqOnaF4AAAAAAACF4mujAAAAAACAQtG8AAAAAAAACkXzAgAAAAAAKBTNCwAAAAAAoFA0LwAAAAAAgELRvAAAAAAAAApF8wIAAAAAACgUzQsAAAAAAKBQ6mtdANTKZz/72Vx99dX59re/nbe//e3tTrdgwYLsueeeGTx4cG6++ebcfvvtufHGG/PAAw9k9uzZSZLNNtsshxxySI444ojU1dWtNo8lS5bk17/+da688srMnDkz5XI5G220Ud72trflmGOOydprr93msu+666787Gc/y9/+9re88sorGT16dLbZZpuccMIJ2XLLLXtmQwCwRkXNi7vuuivHHXfcGmvfeOONc/3113dxzQGoVDWz4qWXXsp5552X66+/PrNmzcqIESOy66675oQTTsjmm2/e5nL/8Y9/5Lvf/W7uvPPOLF68OBMnTsy0adNy5JFHplQq9cxGAKBDRc6LG2+8Mbfffnv+/ve/55FHHsnixYvz8Y9/PCeccELPbQDoJM0LBqx3vvOdufrqq3PppZeuMTCuvvrqLFmyJAcffHCee+65fOITn8iwYcOyxx57ZMqUKXnllVdy00035bTTTsutt96aH/7wh6ucACxbtizHHXdc7r///kyePDmHHHJIkuUXnb773e/m97//fX77299m6NChqyz3hz/8Yb773e9mgw02yH777Zf11lsv8+bNy7333ptHH31U8wKgSoqaF+PHj8/HP/7xNmv585//nHvvvTd77bVXD24JANpTrayYP39+pk2blhkzZmSHHXbIvvvum7lz5+baa6/NrbfemgsuuCDbbbfdKst8/PHHM23atCxZsiRve9vbssEGG+SWW27JaaedlieeeCJf/OIXe227ALCqIufFT3/609x9990ZMWJENthggzz11FO9th2gYmUYoFpaWspTpkwpb7nlluVnnnmm3ene+c53lidNmlR+4IEHyrNnzy7/4he/KC9cuHCVaRYuXFg+9NBDy5MmTSr/4Q9/WOVnv//978uTJk0qf+xjH1tt3h/5yEfKkyZNKv/ud79b5fHrrruuPGnSpPJHP/rR8uLFi1d73rJlyzqxpgB0R5Hzoj1vf/vby5MmTSpPnz69oukB6J5qZcVpp51WnjRpUvmMM85Y5fF77723PHny5PL+++9fbm5uXuVnRx99dHnSpEnlm2++ecVjS5cuLR911FHlSZMmle+9996urjYAnVTkvLjnnnvK//jHP8otLS3lq6++ujxp0qTy9773vW6uMXSPe14wYJVKpRx66KFpaWnJZZdd1uY0jz32WB544IFsscUW2XbbbTN27NgcffTRGTZs2CrTDRs2LO9973uTJPfcc88qP5s5c2aS5E1vetNq83/zm9+cJHnhhRdWefzb3/52hg8fnjPPPDNrrbXWas+rr/ehKYBqKXJetOWBBx7I//3f/2Xy5MnZeuutO5wegO6rVlbccMMNGTRo0Gpf4bHDDjtkn332yeOPP5677757xeP/+Mc/cs8992S33XbL3nvvveLxhoaGfPKTn0ySXHzxxV1fcQA6pah5kSQ777xzJk6c6OsEKRTNCwa0Qw89NIMGDcpll12Wcrm82s9bg+Sd73xnh/NqbSi8+nsGW79H8NZbb13tOTfffHNKpVJ22223FY898sgjefLJJ7Pnnntm2LBhueWWW/KjH/0oF154YR555JHKVw6AHlPEvGjPb3/72yTJu971rg6nBaDnVCMr5s2bl/XWWy/Dhw9f7TkTJkxIktx5550rHmu9MNXW1wjutNNOGTZs2GoXvADoXUXMCygqv77NgDZu3Ljsueeeue2223LnnXdmjz32WPGzpqamXHnllWloaMhBBx3U4bwuvfTSJKufGLz5zW/Ofvvtl+uuuy4HH3xwdt111yTLv8N85syZ+epXv7rKb8ZOnz49SbLuuuvmyCOPzP3337/K/A488MB8/etfT0NDQ9dWGoBOK2JetGXRokX5/e9/n7XWWisHHnhgZ1cTgG6oRlast956ef7557Nw4cLVLki1foJvxowZKx5r/fsmm2yy2jLq6uoyYcKEPP7442lqavLpboAqKWJeQFH55AUDXmsn+5JLLlnl8Ztvvjnz5s3Lvvvum5EjR65xHhdddFFuvfXW7L777qt8HDtZ/pHA73//+/ngBz+YRx55JBdccEEuuOCCPPLII3nLW96SN7zhDatM3/qVIJdddllefPHFXHDBBbn33nvzu9/9LjvssEOuuuqqnHPOOd1cawA6q2h50ZZrrrkmCxcuzFvf+tass846nVtBALqtt7PijW98Y1paWnLuueeu8vj999+fm2++OUnyyiuvrHh8wYIFSZK11167zWUNHz48LS0tWbhwYYfrBkDPKVpeQFH51QoGvH333TejRo3K9ddfn1deeWXFG/vWAOnoY3o33XRTvvrVr2b8+PH51re+tdrPFy9enM985jN54IEH8p3vfGdFR/2OO+7I6aefnltvvTUXX3zxio/ttbS0rPjz7LPPXvFbtltttVV+8IMfZL/99ssvf/nLfPKTn/TpC4AqKlpetKXSWgDoHb2dFZ/85Cdz22235Sc/+Un+9re/Zfvtt8+cOXNy7bXX5nWve10effRR31UO0AfIC6iMT14w4A0ePDjveMc7smTJklx11VVJkrlz5+a2227LRhtttMbfdL3lllvyiU98IqNHj84FF1yQDTbYYLVpzjvvvNx44435yle+kv333z/rrbde1ltvvey///457bTT8vzzz+e8885bMX1rYG244YarfT3I6NGjs/3222fx4sV54oknemL1AahQ0fLi1Z588sn89a9/zSabbFLRvTEA6Hm9nRUbbrhhLr300rzzne/MzJkzc+GFF+b+++/PJz7xiXz4wx9OsvycodWIESOStP/btQsXLkypVGrzO9EB6D1FywsoKs0LyOof17viiivS1NS04iZKbbn55pvz8Y9/POutt15+/vOfZ+ONN25zuttuuy1J2ryQtPvuuydJHnrooRWPvfa1r03S/ke7Wx9fsmRJh+sFQM8qUl68mk9dABRDb2ZFkowdOzann356brvttkyfPj3XX399PvShD6345aZtttlmxbQTJ05Mkjz11FOrzae5uTkzZ87MhAkT3O8CoAaKlBdQVJoXkGSzzTbL9ttvn7///e955JFHctlll6VUKuXQQw9tc/qbb745J5xwQtZdd938/Oc/b/MGeK2WLVuWJJk/f/5qP2u9v8XKX/+03XbbZa211srMmTOzdOnS1Z7TGjLjx4+vfAUB6BFFyouVNTU15Yorrkh9fX0OOeSQzq4WAD2oN7OiPc3Nzfn973+f+vr6vPWtb13x+C677JIk+dOf/rTac/76179m0aJFK6YBoLqKlBdQVJoX8C+tHe/TTjstTzzxRN7whje02SC45ZZbVgmL1t9mas8OO+yQJDn33HNX3M8iWR4Y3/ve95Ks+lu2w4cPzzve8Y4sWrQo//3f/73KvC6//PI8/vjj2Wmnndr8WCAAva8oebGy1hv7velNb8qYMWO6sloA9KDeyoply5at9gnslpaWfOMb38g//vGPHHPMMRk7duyKn2266abZZZddctddd+WWW25Z8XhjY2POOeecJMm73vWurq4mAN1UlLyAoiqVy+VyrYuAIliwYEHe+MY3ZtGiRUmSs88+O/vvv/8q0zzxxBM5+OCD09jYmAMOOGDFVzytbPz48at0yZ999tkcfvjhmTt3bjbffPMVX/1xxx135PHHH8/EiRNz8cUXZ911113xnPnz52fatGmZMWNGdt1112yzzTaZMWNGbrrppqyzzjr51a9+lc0226w3NgMAHShSXrT68Ic/nJtuuik//OEPM2XKlJ5cXQC6oLeyYvbs2TnggAOy5557ZsKECVm2bFn+9Kc/5cknn8yb3/zmfP/731/tU3qPPfZYjjzyyCxZsiT7779/xowZk1tuuSWPPfZYjjnmmHzxi1/shS0AQCWKlBfXX399rr/++iTJzJkzc88992TLLbfM5MmTkyxviH/oQx/q0fWHjmhewEo+//nP57LLLsvIkSNz2223rTaQ33XXXTnuuOPWOI9dd901F1544SqPPffcc/nRj36U2267Lc8++2xKpVLGjx+fKVOm5Pjjj2/zQtSLL76Yc889N9dff33mzZuXddddN3vuuWdOOOGENX6nIQC9r0h58dxzz2WfffbJ6NGjc/PNN6eurq77KwhAt/VGVixY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foMR2eI16+XlhY0rzgN6al9pXNacm++dmf/3539kzvzFSZIN1huWt71hYofv2de0Dydp8/374LpBWdrUlAWLmrJo6bI0NzVlxLB5WWf4kKzVUJ91RjRk58ljkyR/efi5Nt/7r/xzx05xVTLG9cdxsKfXaeVj9LkXFqW5uTkbjn4pB+z1uk6fVzMwPPrUvPzXD+9I47KWbs+rlKS+rpTmcjnlla5Pbb7xyOy53fhs89q1c/8/Fubqe/+WWS8sXnH9afyYEdl16w2TrD6Wr3wNqm5QKfNfWZKFS5pSLpc7fD/enrbep283aYP8+YFZ+b9/rn5uMmrdoV3eJq8+xoevNTgj1x6yyrW69q5R3fmXp3ttvOsv42k11qPI26o716OKvF5rUiqXy5Vfbeun9t133yTJDTfc0K35LFq0KA8//HAmT56cYcOG5cl7rk7++NMsS5JlybyW+vxg4YF5JWt3v+gKlEpJuZysNbiUTxy+Xd644ya5a/qsnP2b+7Jw8bKuzzdJRztN6zTDhw7OZ47cMbtuvWGnlr1WQ13+85idV4TZmnQ0345qad1OrX+uPF13dXU5r96Xam3leh588qUe33Zd2U612kZrqnXlY62r86hkG/bUmEXndGe79+b++rFvXpN/Prd0lcfWziv58PDfZcygf3/EsiXJ3PKI3J0t83zjupnVtE5eaBmRcko9Wk9vmDxxVL55whs7nO7CPzyUi294bI3TvPqYq68flKamzp+4HbHfpBzztskr/r2m43pNBtcPyrKmll7NorZUUm9naypadlVLb613T7xXkRfV151t/uSNv87Smy/JoEFJS0ty5sIJeSFTulRHd8eS1v16YUbne5dMz9LG5janW9N79jXtw0Ma6lJKsqSd+faU1vOAntoetR7f+lMdlYxx5XK5w2m2ee06fWqb9PR56F3TZ+Vbv/xrl47RVrKiNnpru6+8L85++Obkmh+vuCb1cnlQfrZo3zzdsmGfOAfoyKvfj7enreOuI3ttt1FOOm6XTtdUybLaGsd+d929uerul7JwSVOvnBd0ZuwpStasbOX3Jf/9u4d69VpeJduqVtnTnetRffnconBfG/W1r30tU6ZMyRZbbJGHH3643el++9vf5q1vfWv222+/fOELX8iyZV2/GN8bnjz9sLRc89PlF0bKSX19smFDU74y8nf58oiLqlJD6yC5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hS98IQ0NDSse7++vN72rmsdOUd6LdnX87I1jrbPjWW9tk66ML9Uce6q9TRYtWpRLLrkkn/70p1fsJ2PGjKn5udPK7/mr/dqUSqW88sorSZIFCxZk5MiRaWhoKMw+Qu0U4T2Ya1Kd55pU8a5HtVfTmtRiG71af74epXnRQ2bNmpUxY8akvn75N3GVSqWMGzcuzz77bM1q+vnPf54pU6as+PdZZ52VAw88MJ/61Kfy9NNPV62OE088MQceeGD+67/+Ky+88EJhttW9996bl19+OW9+85tXPFarbbSmbVKU7fXq/SmpzfZ69f6UFOP4a2t/Smq3T1EcRdg/a2UgrnvrWDl//vwsW7YsY8aMWfGz8ePH97t1P/HEE7P33nvnnHPOyTe/+c0B8Zr/9Kc/zY477phtttlmxWMD5fWm99T62CnCe9FKxs/ePNY6M5711jbp7PjS22NPZ87jemOb/POf/8zIkSNz3nnn5dBDD81RRx2VO+64o6b768rv+av92pRKpZx99tn5+Mc/nn322SdHHXVUvvGNb2ThwoU120cojlrnSFtck1oz16QqV5TrUUkxr0n19+tRmhf91HnnnZd//vOf+exnP5sk+eY3v5lrrrkmV155ZXbeeeccf/zxVanjF7/4Ra666qpcdtllWW+99XLSSSdVZbmVuOSSS/KOd7xjxeBSq23UF7x6f0pqs7360v6U2KdgoGlrrOzvvvnNb+aWW27Jpz71qZx11lm1LqfX/d///V/++Mc/5iMf+UitS4F+pQjjZ63Hs6KNL0V4393c3Jxnnnkmm222WS677LJ84QtfyKc+9ak0NzdXvZZWbb3nr5ampqb88Ic/zLnnnpubbropP/vZz3LiiSfWdHtAe1yT6phrUpUpyvWopLj7U3+/HqV50UPGjRuXuXPnpqmpKUlSLpcza9asbLTRRlWv5cc//nH++Mc/5n/+538ydOjQFfUly7t/xxxzTJ5++unMnz+/12tpXf/Bgwfn3e9+d/7yl78UYlstXLgw/+///b8cdthhKx6r1TZqXXZ726TW26ut/am15qS626ut/am1llpuo7b2p9a6ktrsUxRHrffPWhpI6/7qsXK99dZLfX195s6du2KaZ555pl+ue7L8BnB33XVXNtxww379mv/lL3/JM888k6lTp2bKlCn529/+li9+8Yv5f//v/w2o15ueV+vxspbvRTszflZjbK1kPOuNbdKV8aU3t0dnz+N6Y5uMGzcugwYNyoEHHpgk2WqrrTJhwoQ888wzNdlfX/2ev9r76sMPP5w5c+asuNn261//+owdOzaPPvpoTY8ZiqHWObIy16Q65ppUZYp0PSop5jWpgXA9SvOih4wePTpbb711rrzyyiTJtddem7Fjx2aTTTapah0//elP8/vf/z4//elPV3x3a1NTU+bNm7dimmuvvTbrr79+1ltvvV6tZdGiRXn55ZdX/Pv3v/99ttpqq0Jsqz/84Q/Zcsst87rXvS5J7bZRqzVtk1pur7b2p6Q226u9/Smp/fH36v0pqf0+RXHUev+spYGy7u2Nlf/xH/+R3/zmN0mSBx54IM8999yKCw593csvv5znnntuxb+vv/76jBw5st+/5kcddVT+9Kc/5cYbb8yNN96Y7bffPl/96ldz1FFH9evXm95X62OnVu9FuzJ+9vSx1pXxrDe2SVfHl94Ye7pyHtcb22TUqFHZY4898qc//SlJ8vTTT2fmzJnZaaedarK/tvWev5qvzbhx4zJnzpw88cQTSZKnnnoqTz/9dF772tdWfR+heGqdI61ck6qMa1IdK9L1qKS416QGwvWoUrlcLte6iP7iySefzOc///m8+OKLGT58eM4444xsscUWVVv+7Nmzs/fee2fjjTfO8OHDkyQNDQ254IILcswxx2TZsmUplUpZb7318vnPfz5bbrllr9bz9NNP54QTTljxMdYJEybklFNOyYQJE2q+raZNm5Z3vetdKzqTixYtqto2OvXUU3PzzTdn3rx5GTlyZIYPH57rrrtujdukt7dXWzVdeOGFbe5Pv/3tb3t9e7VVz09+8pN296ekNtvouuuuS7L6/pRUd5+i+Go95lVDV8a2/qC97P3tb3+befPm5cQTT8zMmTMzePDgfPGLX8zuu+9e44p7xjPPPJNPfvKTWbp0aUqlUkaNGpWTTjopkydP7vev+cqOPfbYvPvd785+++3Xr19vqqNax05R3ot2dfzs6WOtq+NZb79elY4vvTH2dPU8rje2ydNPP53/+q//yosvvphSqZSPfexjmTp1ak1em7be81f7tbn66qtz/vnnp1QqpVwu50Mf+lAOPPDAqtdBMdX6PZhrUpVzTWrN9dTyelR7NdXymtRAvx6leQEAAAAAABSKr40CAAAAAAAKRfMCAAAAAAAoFM0LAAAAAACgUDQvAAAAAACAQtG8AAAAAAAACkXzAgAAAAAAKBTNCwAAAAAAoFDqa10A1MpnP/vZXH311fn2t7+dt7/97e1Ot2DBguy5554ZPHhwbr755tx+++258cYb88ADD2T27NlJks022yyHHHJIjjjiiNTV1a02j5deeinnnXderr/++syaNSsjRozIrrvumhNOOCGbb775KtPOnz8/f/zjH3PTTTflsccey3PPPZfhw4dn2223zbvf/e688Y1v7NkNAcAaFTUvkuScc87Jfffdl3/84x+ZP39+hg4dmvHjx+eggw7KEUcckaFDh/bchgCgXUXOilf7wx/+kE9/+tNJku985zs54IADurjWAHRWkfPi2GOPzd13391mPePHj8+NN97YxbWGriuVy+VyrYuAWrjjjjvynve8J294wxvy05/+tN3pfvOb3+RLX/pSpk2bluOOOy77779/hg0blj322COvfe1r88orr+Smm27KnDlzss8+++SHP/xhSqXSiufPnz8/06ZNy4wZM7LDDjtk++23z9y5c3Pttdemvr4+F1xwQbbbbrsV0//617/Ol7/85WywwQbZY489Mnbs2MyePTt//OMfs2TJkvznf/5nPvCBD/TqtgHg34qaF0my6667ZpNNNsnmm2+e0aNHZ+HChbn77rvz2GOPZcstt8xvfvMbDQyAKihyVqxs7ty5efvb357GxsYsWrRI8wKgyoqcF63Ni49//OOr1bP22mvnPe95T49tB6hYGQaolpaW8pQpU8pbbrll+Zlnnml3une+853lSZMmlR944IHy7Nmzy7/4xS/KCxcuXGWahQsXlg899NDypEmTyn/4wx9W+dlpp51WnjRpUvmMM85Y5fF77723PHny5PL+++9fbm5uXvH4n//85/INN9ywymPlcrn8xBNPlHfaaafy1ltvXZ49e3ZXVxuATipqXpTL5fKSJUvarOVzn/tcedKkSeVf/OIXnVlVALqoyFmxsuOPP768zz77lM8888zypEmTyldffXUX1haAripyXhxzzDHlSZMmdXMNoWe55wUDVqlUyqGHHpqWlpZcdtllbU7z2GOP5YEHHsgWW2yRbbfdNmPHjs3RRx+dYcOGrTLdsGHD8t73vjdJcs8996zysxtuuCGDBg3KCSecsMrjO+ywQ/bZZ588/vjjq3wsb4899siUKVMyaNCqh+emm26a/fffP8uWLct9993X5fUGoHOKmhdJMmTIkDbr+Y//+I8kyVNPPVX5igLQZUXOilaXXXZZbrrpppx++umrLROA6ugLeQFFonnBgHbooYdm0KBBueyyy1Ju4xvUWoPkne98Z4fzqq9ffguZV3/P4Lx587Leeutl+PDhqz1nwoQJSZI777yzonpbl9H6JwDV0dfy4pZbbkmSir77HICeUeSsmDVrVr7+9a/niCOOyB577NHxygDQa4qcF0ly1VVX5bzzzsvPfvaz3HXXXWlpaemwDugtroAyoI0bNy577rlnbrvtttx5552rvJFvamrKlVdemYaGhhx00EEdzuvSSy9Nkuy1116rPL7eeuvl+eefz8KFC1cLjZkzZyZJZsyY0eH8FyxYkGuvvTZDhgzJTjvt1OH0APScoufF//zP/2TJkiV5+eWXc++992b69OnZa6+9cvDBB3diLQHojqJmRblczimnnJIRI0bkxBNP7MqqAdCDipoXrT73uc+t8u+JEyfmrLPOyrbbbtthPdDTfPKCAa+1k33JJZes8vjNN9+cefPmZd99983IkSPXOI+LLroot956a3bffffsvffeq/zsjW98Y1paWnLuueeu8vj/Z+++49uq7++PnyvZcjwycPYiQRRCIOwRNm1Cyx4FCgmUUUbZswznSwtNISSUPcoeZZdZQgI/AoRRmpKEESApIQWME7L38Lak+/vD2NjxkK6kq8+90uv5eFCKfaV7LMv3SPete+8XX3yh999/X5K0adOmuDmvv/56rV69Wueee6622GKLuMsDANLLy33xyCOP6N5779WTTz6pefPm6eijj9bdd9+t/Px8Bz8hACBVXuyK5557TjNmzNANN9ygkpKSJH4qAEC6ebEvRo8erQcffFD/+te/9MUXX+iNN97Qaaedph9++EFnnnmmli5dmsRPCqSGIy+Q80aPHq3S0lK988472rRpk7p27SrppwKJd5jee++9pxtuuEEDBw7ULbfc0ub7l156qT788EM99thj+vzzz7XLLrto5cqVmjZtmrbeemstWLBAlmV1uo7bbrtNU6dO1QEHHKDzzjsvyZ8UAJAKL/fFrFmzJEmrVq3SzJkzdeutt+rEE0/Uo48+qn79+qXyYwMAHPBaV/zwww+65ZZbdPzxx+uAAw5I408KAEiF1/pCks4444xW/7311ls3H7l333336bHHHtMf//jHFH5qwDmOvEDOy8/P1zHHHKPa2lpNmTJFUuPOnw8//FADBgzQvvvu2+FtP/jgA11yySXq2bOnnnjiCfXp06fNMv369dPLL7+sE044QYsXL9ZTTz2lL774QpdccknzIKJnz54druPOO+/UQw89pL333lv33ntvm/MYAgAyw+t9IUm9e/fWUUcdpXvuuUfffvutJk2alMJPDABwymtd8X//93/q2rWrxo0bl+afFACQCq/1RWfGjBkjSfrss8+c/phAyjjyAlDjRPvxxx/XSy+9pJNPPlmTJ09WJBJpvohSe95//31dfPHF2mKLLfTkk09q8ODBHd5/3759NWHChDZfv+eeeyRJI0aMaPd2d955p+6//37ttddeeuCBB9SlS5ckfjoAQLp4tS82t9NOO6l79+6aPXt2QssDANLHS10xf/58bdq0SXvssUe793XFFVfoiiuu0Lhx49p84hYA4C4v9UVnevToIcuyVF1dndDyQDoxvAAk/exnP9Muu+yizz//XF9//bVeeeUVWZal4447rt3lm8qie/fuevLJJzVkyBDH64xGo3r99deVl5enX/3qV22+33Jw8dBDD6mwsNDxOgAA6eXFvmhPVVWVNm3apN69ezteHwAgNV7qimOPPVY1NTVtlv/qq6/01VdfaeTIkRo8eLC23XZbx+sEAKTGS33RmS+//FK2bWvgwIGO1wekiuEF8KMTTjhBn3/+ucaPH6/vvvtO++23X7sb5g8++KBVWQwdOrTT+21oaFA0Gm111EQsFtPNN9+s77//XmeccYb69u3b6jZ33XWX7r//fu2xxx568MEHGVwAgId4pS9++OEHde3atc2F/BoaGnTTTTcpFou1uXAfACAzvNIVHZ2b/J577tFXX32lk046SUcccURyPyQAIGVe6YuO3lusWLFC48ePlyQdddRRyf+gQJIYXgA/Ouyww3TTTTc1n8OvvYsjfffdd7roootUX1+vvfbaS6+//nqbZQYOHNhqSr5mzRodccQR2m+//TRo0CA1NDTo3//+t8rLy/Xzn/9cf/jDH1rd/pVXXtF9992nvLw87bTTTnr00UfbrGOvvfbSyJEjU/2RAQBJ8EpffPzxx7r++uu1++67a/DgwerRo4dWr16t//znP1q+fLm23nprXX755Wn+6QEAifBKVwAAvM0rffHxxx/rz3/+s/bYYw8NGjRI3bp10+LFi/XBBx+ourpaRx11lI455pg0//RAfAwvgB+VlJTo0EMP1SuvvKIePXro4IMPbrPM6tWrVV9fL0ntloXUOFhoWRglJSUaPXq0PvvsM73//vvKy8vTtttuqxtvvFHHH398m/MYLlmyRJIUiUT02GOPtbuOiy66iOEFABjilb7YbbfddNJJJ+mTTz5pPqd5cXGxtt56a5166qk65ZRTOHIPAAzxSlcAALzNK32x/fbb69BDD9V///tfzZ07V9XV1eratat22203HX/88Tr88MPT+FMDibNs27ZNhwAAAAAAAAAAAGjCxzIAAAAAAAAAAICnMLwAAAAAAAAAAACewvACAAAAAAAAAAB4CsMLAAAAAAAAAADgKQwvAAAAAAAAAACApzC8AAAAAAAAAAAAnsLwAgAAAAAAAAAAeArDCwAAAAAAAAAA4CkMLwAAAAAAAAAAgKcwvAAAAAAAAAAAAJ7C8AIAAAAAAAAAAHgKwwsAAAAAAAAAAOApeaYDwF3RaFQNDQ2mYwBG5OfnKxgMmo4B+AJ9gVxGXwCJoSuQy+gKIHH0BXIZfZFeDC+ylG3bWr58udavX286CmBUjx491K9fP1mWZToK4En0BdCIvgA6RlcAjegKoHP0BdCIvkgfhhdZqqks+vTpo6KiIv5YkHNs21Z1dbVWrlwpSerfv7/hRIA30RfIdfQFEB9dgVxHVwCJoS+Q6+iL9GN4kYWi0WhzWfTs2dN0HMCYwsJCSdLKlSvVp08fDtsDNkNfAI3oC6BjdAXQiK4AOkdfAI3oi/Tigt1ZqOm8gkVFRYaTAOY1/R1wvk2gLfoC+Al9AbSPrgB+QlcAHaMvgJ/QF+nD8CKLcXgewN8BkAj+TgD+DoB4+BsB+DsAEsHfCcDfQToxvAAAAAAAAAAAAJ7C8AKed88992jYsGHN/4wcOVJjx47VBx984Mr6Tj31VJ177rmu3Hc22/z31PTPkUcemdDtR40apb/85S8upwSQregK/6AvAJhEX/gDXQHAJLrCP+iL7McFuxFXfUNU//5iqWbOW6ZN1fXqWhTS3iP6a/+dByiUn5mLznTp0kVPPPGEpMYL3jzwwAM677zz9Mwzz2i33XbLSAbE1/L31PJrALIfXQEn6Asgd9EXSBRdAeQuugJO0BfZjeEFOjVr3jLd8Y85qqppkGVJti1ZlvTR3GV66NW5umLsbtprh36u5wgEAtpll12a/3vnnXfWQQcdpFdffZXSaMG2Y4psWC27vkZWqFB53XvJsjJ3gNXmvycAuYGu8B/6AoAJ9IW/0BUATKAr/Ie+gJsYXqBDs+Yt04S/z5bsxv+2N/t3dU2Dbnx8lq49Yy+NHNE/o9n69u2r0tJSLV26tPlrc+bM0R133KEvv/xSwWBQP//5z/V///d/6tmzZ/Myt956qz744AMtXrxYJSUl2nPPPVVWVqY+ffpkNL8b6lcvVtWCWWpYvUSxSL0CeSHl9xqo4mEjFeo1yFiu6upq3XrrrZoxY4aWL1+unj17av/999dVV12lrl27dni7devW6eyzz5Zt23rkkUdUWlqq7777Trfeeqtmz56taDSqvfbaS3/84x+15ZZbZvAnAtASXeE/9AUAE+gLf6ErAJhAV/gPfQG3cc0LtKu+Iao7/jFHsps7ow37x/+58x9zVN8QzWA6qaqqShs2bNCgQY0bwjlz5ujUU09V165ddccdd+iGG27Q3LlzdcEFF7S63Zo1a3TuuefqwQcf1LXXXqslS5bo1FNPVSQSyWj+dKtfvVgbZr+u+uXlChR1VX7PAQoUdVX98vLGr69enLEskUik1T+1tbWKRqO6/PLL9fDDD+vSSy/Vxx9/3OZ309KqVat02mmnKRQK6YknnlBpaal++OEHjRkzRhs2bNCkSZN06623au3atTrjjDNUX1+fsZ8PwE/oCv+hL+gLwAT6wl/oCroCMIGu8B/6gr7IBI68QLv+/cVSVdU0xF3OllRZ06AZXy7VL3Yf7Gqmpg37ypUrdcstt6i4uFinnXaaJOm2227TiBEjdO+998qyLEnStttuqyOPPFIffPCBDjroIEnSxIkTm+8vGo1q11131YEHHqiZM2dq//33dzW/W2w7pqoFsxSr2ai8XoObf36roEhWr8GKrP5BVQtmK7/nANcP26uurtYOO+zQ6mt//etfNX78+Ob/jkQiGjRokE4++WR9//332mqrrVotv3TpUp1xxhkaOHCg/va3v6moqEiSdO+996p79+56/PHHVVBQIEnabbfdNHr0aL344os65ZRTXP3ZALRFV/gLfUFfAKbQF/5BV9AVgCl0hb/QF/RFpjC8QLtmzlvWfG7BeJrOPehmaWy+IQoGg7rvvvsUDodVU1Ojzz77TFdffbWi0Z8m70OHDlX//v01d+7c5tL44IMPdP/99+ubb75RZWVl87IVFRW+LY3IhtVqWL1EwW69msuiiWVZCnbrpYbVixXZsFr5Pdw9LLFLly56+umnW31t8ODBevXVV/X3v/9dCxcuVHV1dfP3KioqWhXGokWLdMopp2i77bbTXXfdpVAo1Py9GTNm6PDDD1cwGGx+AdGtWzdtv/32mjdvnqs/F4D20RX+Ql/QF4Ap9IV/0BV0BWAKXeEv9AV9kSkML9CuTdX1CRWG1Fgsm6rdPVSqaUNk27YqKip022236ZprrtGUKVNk27ai0agmTpzYaqLdZNmyZZKkL7/8UhdccIFGjx6tc845Rz179pRlWTrxxBNVV1fnan432fU1ikXqFcwvaPf7Vn6BYtE1sutrXM8SCAS04447tvra22+/rWuuuUYnnXSSLr/8cvXo0UOrVq3ShRde2OZxnzt3rtavX69rr722VVlIjecdfOKJJ/TEE0+0WW9+fn76fxgAcdEV/kJf0BeAKfSFf9AVdAVgCl3hL/QFfZEpDC/Qrq5FIUcT765FofgLpqDlhminnXbSVlttpRNPPFF/+9vfdM0118iyLJ177rk6+OCD29x2iy22kCS98847Kikp0Z133qlAoPGQtSVLlriaOxOsUKECeSHZDXWyCorafN9uqFMgGJIVKjSQTnrzzTc1fPhw/eUvf2n+2uzZs9td9ogjjlAwGNQVV1yhBx98UPvss0/z97p3766DDjpIJ598cpvbFRcXpz84gLjoCn+hL+gLwBT6wj/oCroCMIWu8Bf6gr7IFIYXaNfeI/rro7nLElrWtqV9duzvcqLWdtxxRx1xxBF65ZVXdNFFF2mXXXZReXl5m0lrS7W1tcrPz291ONuUKVMyEddVed17Kb/XQNUvL5fV4jyDkho/DbBxtUL9tlZe915G8jU97i119rhfe+21qqur0wUXXKBHHnlEu+++uyRpn3320TfffKPtt99ewWDQ1cwAEkNX+At9AcAU+sI/6AoAptAV/kJfIFPcvWIKfGv/nQeouDBfVpzlLEklhfnab6cBmYjVygUXXKBoNKonnnhCV199td5//31ddtllevvttzVr1ixNnjxZ11xzjWbNmiVJ2m+//bRq1SrdcMMN+uijj3Tffffpn//8Z8Zzp5tlBVQ8bKQChd0UWf2DYnXVsmNRxeqqFVn9gwJF3VQ8bC/XL5DUkX333Vdffvml/va3v+k///mPJk6cqI8++qjT24wfP16/+tWv9Pvf/15ffvmlJOmSSy7RwoULddZZZ+mNN97Q7Nmz9cYbb+jPf/6zpk6dmokfBcBm6Ap/oS/oC8AU+sI/6Aq6AjCFrvAX+oK+yBSGF2hXKD+oK8buJlnqsDisH//n8rG7KZSf+eljOBzW4Ycfrueee07bbLONnn32WVVXV2vcuHH6/e9/r/vuu09dunTRkCFDJEkHHXSQrrzySk2fPl3nn3++PvnkEz344IMZz+2GUK9B6r7XEQr1CytWvUkNa5cqVr1JoX5bq/ueRyjUa5CxbGPGjNGZZ56pp59+WhdddJGWLVum2267rdPbWJalm266SQceeKDOPvtsff311xoyZIhefPFF9ejRQ+PHj9dZZ52lW2+9VTU1NRo2bFiGfhoALdEV/kNf0BeACfSFv9AVdAVgAl3hP/QFfZEJlm0nejkc+EVtba2+//57bbXVVurSpUtK9zVr3jLd+Y85qqxpaD73YNO/SwrzdfnY3bTXDv3SlBypsu2YIhtWy66vkRUqVF73Xsam3F6Rzr8HINuk6++DrvAf+qIt+gJoH+8tchdd0RZdAXSM9xa5i75oi75IH655gU6NHNFfT1zfRzO+XKqP5i7Tpup6dS0KaZ8d+2u/nQYYmXSjY5YVUH6PPqZjAMgxdIX/0BcATKAv/IWuAGACXeE/9AXcxPACcYXyg/rF7oP1i90Hm44CAPAougIAkAj6AgAQD10BoEluH8MDAAAAAAAAAAA8h+EFAAAAAAAAAADwFIYXAAAAAAAAAADAUxheZDHbtk1HAIzj7wCIj78TgL8DIB7+RgD+DoBE8HcC8HeQTgwvslB+fr4kqbq62nASwLymv4OmvwsAP6EvgJ/QF0D76ArgJ3QF0DH6AvgJfZE+eaYDIP2CwaB69OihlStXSpKKiopkWZbhVEBm2bat6upqrVy5Uj169FAwGDQdCfAc+gKgL4B46AqArgASQV8A9IUbLJvjWLKSbdtavny51q9fbzoKYFSPHj3Ur18/XjQBHaAvgEb0BdAxugJoRFcAnaMvgEb0RfowvMhy0WhUDQ0NpmMARuTn5zPlBhJEXyCX0RdAYugK5DK6AkgcfYFcRl+kF8MLAAAAAAAAAADgKVywGwAAAAAAAAAAeArDCwAAAAAAAAAA4CkMLwAAAAAAAAAAgKcwvAAAAAAAAAAAAJ7C8AIAAAAAAAAAAHgKwwsAAAAAAAAAAOApDC8AAAAAAAAAAICnMLwAAAAAAAAAAACewvACAAAAAAAAAAB4Sp7pAF6wxx57qL6+Xr179zYdBQDiWrVqlUKhkD755BPTUXIKXQHAb+iLzKMrAPgNXWEGfQHAb0z1BUdeSKqrq1MkEjG2ftu2VVdXJ9u2jWXoDPlSQ77UkK+tSCSiurq6jK0PjdzqCq88x8lBDj/k8FIWP+SgLzIvka7wynMnEWR1B1ndQdbk0BVm1NXVqaGhwRPPgY546XnaET9klPyRk4zpkc0ZTfUFR15I6tOnjyRp+vTpRtZfXV2t+fPna/jw4SoqKjKSoTPkSw35UkO+tkaPHp2R9aA1t7rCK89xcpDDDzm8lMUPOeiLzEukK7zy3EkEWd1BVneQNTl0hRl9+vRRXV2dpk6davw50BEvPU874oeMkj9ykjE9sjmjqb7gyAsAAAAAAAAAAOApDC8AAAAAAAAAAICnMLwAAAAAAAAAAACewvACAAAAAAAAAAB4CsMLAAAAAAAAAADgKQwvAAAAAAAAAACApzC8AAAAAAAAAAAAnsLwAgAAAAAAAAAAeArDCwAAAAAAAAAA4CkMLwAAAAAAAAAAgKcwvAAAAAAAAAAAAJ7C8AIAAAAAAAAAAHgKwwsAAAAAAAAAAOApeaYDADDjlfe+1uNTF7T4ymJJ0u+OHKbjfrFd3NsvX1Op8Y/M0pJVlbJtybKkgb1LdP3ZI9WvZ0nc26/dUKNbn/lUXy9cp2g0pmAwoO2GbKErT9ldpd0L496+viGqf3+xVDPnLdOm6np1LQpp7xH9tf/OAxTKD8a9vWl+zw8gdXMWLNf1D8+Sbf/0NcuSxp8zUrsO69fh7ZLdfiaz3Wm5rkg0przg0oTWlWpHOFFZXa+/v/6VPv5qhWrrI+oSytOe2/fVGUdsr5KiUIe3y+R2ONl1JfuzAcgtCxau1v/d/5HqG2LNXwvlB3TT+fto2JBeSd3nvO9W6o8PzlQ02lRSixUMWrrx3L01Yus+SWdte79K+X6btrEzvlisFavXq+/n9dpv50E59bqavgDgVe9+XKE7/vFFm69fPmZnjdpzaEL30bbnFjvquVT3P0mpv3fwwj4gv/YlwwsgjWw7pto1i7VxzvuqW/qtrFhEVvfeyo8Va2N1haobahSNxmTHIvp45ueqj1haGO2tuQ2DZSuokBVRcXG+br9urCSpYf1KRdYuky0pv7S/8nv0kWU1HjB18rjJ2lTfNkPXkPTsxGM6zXnUHyZ3+L3Hpy7Q41MXaMptHd/HVXf/S18vXLfZzy4tXlmpc26aruFDS/XXiw/o8PaTnpitGV8ua/W1WCSmud+t0el/eUv77zxA15y2Z4e3nzVvme74xxxV1TTIstS8Y+yjucv00KtzdcXY3bTXDh3v+DPN7/kBE+rqNmrFlEcU+f5zqb5WKipWoHsv5Zf0Un7Pfsov6qGibfdQqLS/LCug3147WRtq295P9y7S0xM63r5decd0LVhc2eIrjYPdYYNKdOvlozu8ndMX5cdd85oaInabr9u2dN1DsxTKC+jlm49q8/1kt5/JbHfaW1dDAutKtSOceOqNr/TC9G9afa26NqJpMxdq2syFOungbfXbw4a3uV0mt8PJrivZnw1AevzthU/05qwlzf+dp4hGhhbogC1Wa0BJRIFgUIGibgp066lApFa2gsrv2V8FA7ZWIJCvQH6BAgVdZNfXywqFZNfX64p7Z6raDmldrFi2LDV1TEDS5E5ee3dm7B9fV2VNpM3X6xtiuvLuGepalK9nbzjc0X3+ZtwU1dbH2nw9GrU17r6PVBgK6oWJRzrO6sb9treNXbRqpWZ/tTJnXlfTFwA6ko7BQWf7jzrbb9TRbRv7dL4apkzVh1PrNWTbsEK9B8uKxWTX1ypQUKT83oMVKu2nvMISXXbvRwrVb9J2Vp025RVoY6xQvQOVki1NvHe9igvzdcdF+8gKFSqve6/mfWZNNn9PY8lW19hGra5Yo8tvXKjtR2yja07fq9OfI9X3Dl7YB+TnvrRs2277ztmgG2+8Ue+++66WLFmiV199VcOHt1+yL774oh5++GHFYjHtvffeuv7665Wfn5/UOkePbtwZMX369KRzp6K6ulrz58/X8OHDVVRUZCRDZ8jXaN26cq2776rm/25o/p9GUTVufPLz2p6PzZZktfzvzf7qora00S7UimgPbbILVRUL6cg9+6hh1SJFaxp3ogUKS1S45Q7qttuvdPzET+Pm7ahEOiueRO6jvZ1S7dluyBa65ZID23y9vZ1h7dlvp/4qO32vNr/fWfOWacLfZ0t24+O6OevH/7n2jL00ckT/uOtJldPnXzrym95meUE2dYVXtrGeyvHWW9riv081f62hQQoGG7exm2v1tfwuKhw6Qn/6eIBWxHp0up72tm+JbB/TcbuOBheby8+z9PT1Bzf/Xu5+cZ6j7WeTZLY7TrfVTVLtiEQ0PVe/WJynf/6rIu7yJ47eRqcevn3zf6erRxL5m0l2Xe3tiOroZzv+50M7zEFfZL4vEnnMvbK9TUSuZV227HPVPHaDGhpaf92WlLdZD7XXSc0CeVIwX1YwKAWCsiSt2VSvGjukNbGuqoj00tz6Ldt0VbydQJvraHCxuZLCPD134xEJ3WdHA4bNdQkF9OLEtkP2TN6v194XOJGuvy0nfdGyC1uiK8y9t6irq9Nbb73l2e2rHzrADxklMzmdvkdpL2Mi9/Hsn/fUqruvktT6k2MNDY3b5pbbZ1tSflAKbNah7XZqIKhNkTzZthS0YrLtxttZiimiPEXtxhvV2iFttLpqt51/pvxeA1U8bKRCvQZJavuepm9gvXYMLVLf4EblK6oGBbUi2k15W+2uC89uf9DvtGu8uA8rXRlM9YXnrnlxyCGH6Nlnn9XAgQM7XOaHH37QXXfdpWeeeUZvv/22Vq9erRdeeCGDKZEL6uo2qvzOK1Q+4XiVTzi+1eDCtqU8W8rL++mfgjwpFJQsu+1woqVYO98LWlKPQI36BterQHXaOX+RVn3xH0VrKhUs7qFAcQ/ZdbWq+t/Hmnz37eobWB83f3sl88p7Xyfyo3e4/PI1lQntlJKkrxeu0/I1la2+tnZDTUI7wyRpxpfLtHZDTauv1TdEdcc/5nS4wZV+/Lot3fmPOapviCa0rkzxe34voSv86Y0Z3+qoP0xu888bM76VJJW//bSW33GqurcYXNg/bms72knUanvbUKtNCz7ViUUfxd1Obr6NTHSwm+rt5ixYntDgQpIaIra+/Ga1JGndptqktp/JbHeS3Van2hFO1NTHEhpcSNIL079RZXXjoYqZ3A4nu67K6vqEdkRJP/5sNe0cholm9EX2a+qSk/70tv787GKd9Ke3m7+WiIULZze/3q957Ibm3mn5T347PdTpRwBjEamhVnZtlezaSlVXVirPiirfiqg0UKmf5a3QgV2+btNVTj5ktGDh6oQGF5JUWRPRgoWr4y4377uVCQ0YJKm2PqZ5361MaFk37pfX1Un0RTV90RG6Atkm2fc2nX2vmzaqrPhJ/bXrk7q1xT8r7rxYmw8ubP3Un6EW/xTktR1cNC3f5muxqIqtOhVZdQoqqpAVUb4iyldUBVad8hVRF6tB3QLVKrE3aUNVneqXl2vD7NdVv3pxm/c0fQPrdWCXrzUouFZVsZBWxLqqKhbSoOBadV34oVZ9/22bDKl2jRe6ygsZUuW54cWee+6pfv06P0xl2rRpGjVqlHr37i3LsjR27FhNnTo1QwmR7cq/eEvlE47Xklt/J1UtbPP9RI9Vam852259BEZLlqRugRoNyFunPCsqy7K1ekO1rLyQAvkhBbuWatnaGvULNk6KrQ43Oz85eVzrsml9jYv4Nl9+/COzHN3+L4+2Xv7WZ+IfMdLSbc+2Xv7fXyxVVU1D3J/cllRZ06AZXy51tD63+T2/l9AV/nPUHybr/lf+2+73nn9lmr6+/nhp9j8l/bSddLq9bTz81tagvLXaKbQw7nbyt9c2biOvvMPZJ0ealn/34wpHt3v34wpd/5Cz7ehNT86RJN3z4jxHt2vafiaz3Ul2W51qRzjxzufrHS3/xBtfScrsdjjZdf399a8crecfb3+XXMAcQV9kt3g7Zzr7/qJFH6t8wvGKPn1z89ecnpKg8+UbvxuNRhVTY7dZkoKKKWDFVGLVasfQD2266pgEdzhdfc8MR1kTWf6PD850dJ9/SnB5N+6X19XO+6KpC9EWXYFsksx7lM217M9SzdYtJU9qfI9X1S/UOIRoOeBvOgVRK+ko1B+/FrCkgGIK/njCxQYFFJRUYEVVbYcUVUAlgTqVf1OhvJ6DFKvZqKoFs3Xr058035UlWzuGFqnYqtXyWHfVKiRbAdUqpOWx7iq2avXuP1+TbbcetKfaNV7oKi9kSJUvr3mxbNmyVhPxgQMHatmyxD4h2BHbtlVdXZ1qtKTU1NS0+rfXZGu+t2ZV6NGpP31SpVSLNK7kfeWFOp7qJbP97eyI8s0FJHWzahVRUHXKV9COKlpfKyuv8SJrVXZIhWrQlnlrtEWgSmtjnV/0dFO9Un5et7z9klXOPiW7eGVlq9sn+oncJvMr1rX6/c74YnH7xdgOy5L+/flijRze09E6nXLy/EtXftu2ZXV6rgJI/ukKr2xj3cxx0p/e7vB7t5Q82epFb9NT2+lJLZsHGJLyrKiG5S/Tp/Vbd7qd3FDbuI1rfY2L+BYsbty2tXf+2M44XV76qXf+t2i9o9vNr1in6urqpLY7yWyrq6urU+6IRNXU1Oh/S9q5oEknZs1brt8dntzj0VGPxPubSXZds/+7PP4NWvh4/krtt02fdnPQF4lJd1/E6wqvbPcT4eWsnXVLS0f9YbKev+GXrb62/I5T21847S/2G+8wz7JVYwcUsiKqsUMqseq01i5R3+CGNq/pY0rs9Xt7R3PHWz7e/ba8iHYiItHEXhe5cb9efF/gRDr+tpz2RVMXbo6uSIwb7y0kb25fm3i5A5r4IaOU2ZzJvEfZe4c+bTKWapbGlSzo9Ch4tzWtNti8fluBH/fYWZatPNmKKKh8RdXVqlZ91UapsLtqVlRoxQ+1koolSVsEqtQ3uFHrY0VqW9yW1ttF6rphmTYt/0F53Xs3fyeZrtlpaOMpt7yyDyudGUz1hS+HF26or6/X/PnzjWaoqKgwuv54sinfn59d3Oq/W+48az6Uqr2/xyTe0NhW8/+Ny5IUsGKSHVTMthS0bNXWVMsONp54N2oHZFtSSBEVWA2d39mPUn1et7x9MjsTW94+Ek3scPGWyzf9XisqKrRi9XpHn8ReuXpDxv6uE3n+pSt/fX29CgoKHCZEOrjZFV7ZxqY7x+wFGzr8Xqtt74+cbmbbY0kqtOoT2k4m+/vM9GuGiMO9VJFoTPPnz09qu5PMtnr+/Pkpd4QT9QmeeqtJdW190o9HvIwd/c0ku67qWmen9aipa+gwB31hRqJd4ZXtfiLSlfXbJTV65oM1rbb1lqRTDuqpnw0sTPh+Nn8tH89Jf3pbfz658fzXxW/epDw5+4BRZxL5JGOTH99qKCBbMVnq0sFrerc6xo37NZXVy+8LnEjlb8tpXzR14eboCrP80AVkTB+v5my5bah4/XXdUjLZ8dAi1fdxnd3eavV9u/mzA5Zs2T/uJwsqpnVrVsnOL1Swaq3yYqVqGl4UWA3KV1R1HewGr7fzFFSNvlvwlWJd+zR/PZmu8do+rHRmMNUXvhxe9O/fX4sWLWr+7yVLlqh//9QuahIKhTq8KJPbampqVFFRoaFDh6qwMPEX7ZmSbflafkqrVEs1ruSd9jfKdtuvJbMxbtrItt7Yts+WFLMbp8gBq3GD3KWwqPnIi6BVLUtSvfJUZyd2YbDWz2tnb/Q2v71lLXa0c8qyWt8+L7hUDZHEd4rlBQMaOnRo8++3b696LVq1MuGJcZ9e3V3/u3by/Ov7eXryh0KhZOPmFL90hVe2sW7l+POz7X8ytr3BhSTnh6y1w5ZUY4cS2k42/j6T3TY6v12y8gKWGhx8cjUvGNDw4cOT2u4sWbva8bZ6+PDhKXdEompqahTKW6q6hsRXVtQllPTj0VHGeH8zya6rqMsq1TXUxb/RjwoLGp/n7eWgLxKT7r6I1xVe2e4nIp1Zfzv+nXav+WNLevqDNcrPs/T09QcneG/Jbbc7POKiRRan4lVWy+83VVxMlgKy1aBgu12V2LYxtdf1mbtPd+43ndtzE9Lxt+W0L5q6cHN0RWLceG8htd/fXuGHvvJDRin5nGeOf1tV7VzeqDhPeuz6X7b9hqRkt7k1NTVa9cDvFZKU4O6mVjbvu1Ruv/l9tL4/66fTDMuSZTWeTiqqgLbo2VuyLNkFliKBkPTj5Rvq7Hw1KKgCRVSrttu8kBVRVEFtPWz7VkdeJNM1XtuHlc6+NNUXvhxeHHLIIRo7dqwuvvhi9erVS88995yOOOKIlO7TsiwVFRWlKWFyCgsLjWfoTDbka7oorNTJjrMW0rAPzZGYpI12FxUoqgKrQVV2gYKhLs2Tjy6qV1QBLYr01LpYcUL3mervrOXtB/Yu0eKViZ8WZFCfkla3327IFpr73ZqEbz986BbNxV5YWKj9dh6k2V8ldmFA25b232VQxp6ziTz/0pWfw7oT47eu8Mo2NtEcnZ1HfMptx3R620S2v8myJDXYQS1o6J/QdjLZxzzTv6ttt+yh/36f+Omchg/dQkVFRUltd2rqoo631UVFRSl3hBPbDuyiT79N/JRTI0f0S/rxiJexo7+ZZNe11w79NG1m22tudWTP4X06zEFfJCbdfZFoV3hlu5+IVLMed81r7Q4uWmqI2Prt+Hf0ys1HJ72ezsQbXLij8UV8xLYUVEy1dr7yFdUGu1CFVoN+iLb/mt6t50W8+w0GLUeneMoLJvZcd+N+vfy+wIlU/rac9kVTF26OrkiMG+8tJH90ARnTx0nOzt5vVUUaP5gb731XopYv/lR68U7P7SRuao6oLQUlSZZisiVLsm1LEdtSvhVVTJY22UUKFXdTZM1ihfptrb6De2tl+VpJ0rpYsVZEu2lQcK2Wx/K1+ailh1WtSPfB6tpvsCzrpxPJJ9M1XtuHlc4MpvrCcxfsvu6663TggQdq+fLlOuuss/TLXzZOEq+99lpNn954gczBgwfrkksu0dixY/XLX/5SpaWlOumkk0zGhk80XSw24R1n6Th/SYJ3aUvaGCvU0sgWithB2bYly5bsSL1iDXWKblqjPNlaHumhufVb/nipImeKHU7PSzYbql5/9khHt7/urNbLX3nK7o5u/4eTWy+//84DVFyYn9An3EoK87XfTgMcrc9tfs/vJXSFWalcILVvYKZrgwtbjS9iF0d66sv6IUltJ73q4t+McLR80/Yzme1OstvqVDvCiYN36eFo+dMP315SZrfDya7rjCO2d7SeMb/cOrmAOYK+MG/OguVxBxdNGiK25ixwdh7/RNxS8mTa7zO+xr/+mN14dm77x3+ishSzA6q0u2hu/WBPddWN5+7taPkbElzejfvldbXzvmjqQrRFV8Br4r3fcrpcZ24peVJ68U5Jmf3wblw/honZUkwBRWXJlpSvmKKS6uygiqx6BRVTZaxA4W2GKLJmsQJF3VQ8bC9d+ds9mu/KlqW59Vuqyu6ifoEN6mLVK6CYulj16hfYoCq7i0b9+uhWgwsp9a7xQld5IUOqvDZU01/+8pd2vz5hwoRW/33iiSfqxBNPzEQkZBk3P/EbT0dv26K2tNEu1PJoD9WpQF80DFGRVasBeesVrVovSQoUdtX/olvog9pttSLWI6H1dd1s+HDnVaN1zk3TE857x5WjW/13v54lGj60VPMr1sa97fChperXs/WFcku7F2r/nQfo318sjXv7/XceoNLuha0u1hfKD+qKsbvpxsdnNQ522rmd9eP/XD52N4Xyg3HXk0l+z+8ldIU5Tl5Ib/5JIEu2ri75n2uDizo7T/9r6KfXa3ZLeDspScMGlTi6aPewQY3btsvH7OzogniXj9lZA/uU6Mq7ZyR8mxt/v6cilcu0RdcujrefUnLbnWS21VLqHeFEYSig4w7aSq988H3cZU86eFuVFDUWYia3w8muq6QopJMO3lbPv/O/uOs46eBtVVLI6T46Q1+Yd91Dsxwvn65Pkko/vfbPqECeFMyXFQyquqrxmhYxBdRg52ttrEQVkd6aWz+43a5K9NOFvz5gS/3zw0XxF2yxfDwjtu6jwlBQNfXRuMsWhoIasXWfuMu5db+8rk6iL4roi47QFfCSk8c5G0icPG6ynp2YXG+61pGJnDd98+U3/1IgqMpInmxbCloxNdiNF+62FFPEzlNUlhpsqdYOqdLqqm2Luyi/1yAVD9tLoV6DVCq1ek+zItZD/6rdTjuGFqlvcKN6WDVqUFCLoz2VH95dvbf6WZsMyXRNpCG126ebFzKkynPDC8BNmR5cRGJSQf+wNm6xjfr07alX3vxClmKy7Kh651VJtqWF0d6a2zBYtoIKWRHV2fnNh49vEajU/b/doXG6XNpfv+3RRy9cOSXh9W9eYOnYsfTXiw/QVXf/S18v7Pj0JcOHluqvFx/Q7veuOW1P2U/M1owvl3V4+/13HqBrTtuz3e/ttUM/XXvGXrrzH3NUWdMgy2o8tK3p38WF+bp87G7aa4d+cX5CM/yeH7nN6Sd7Nl/+ryVPKZim10IxW1oXzdPCaD+tiXVTlV0oDdhRH3wfTfhTrHsO6ylJuvXy0Y5+tlsvbxzsjtpzqKPhxag9h0qSuhbla1N1/IuJdy3K1zaDe2j+/MbtZbLbz2S2O8muK9WOcOKkg3+mvLw8vTD9m06W2Va/Paz1OVszuR1Odl2/PWy4bNtO6GdrOeQH0Jqbr/0jMWlJpKuG7b6bApFa2Qoqv2d/FQzYWoFAvgL5BQoUdFG/+npddu9HKvjxdX6tHdK6WHGHXTU5wcHNmcfu6mh4ceaxuya03AsTj9Rvxk1RbX3H1z4qDAX1wsQjE163W/fL62pnfQHAHzbVu7u8JPXQel1b8lqHHdm0HU3U5veR6OzCllQXlboO20MFPXrLrq9VoKBI+b0HK1TaTwMLS3TZvR8pVL9JJVadNtkF2hgrVO9A4wfPVsW6qrgwX3dctI+sUKHyuvdqdfTE5u9pVsR6aGVtd20RqFKB1aA6O1/bj9hGl56+V4cZU+0aL3SVFzKkguEFckb5hOPT+ubFtqVoiw8PRSRV2XlqsAu0wu6hzxuG6suGoXr2ykO1Zv58dRs+XBcccPxPO8gSuLbaE7f8ts3Xptx2TEI72Tr6xFo6dizdcsmBWr6mUn95dJYWr6xs3ugN6lOi684aGffTtGWn76W1G2p027Ofan7FOkWjMQWDAQ0fuoX+cPLuzZ/i7cjIEf31xPV9NOPLpfpo7jJtqq5X16KQ9tmxv/bbaYAnJ8Ut+T0/kIxSzUv6Uz0tt7d1Curduu31Qf2Oimz2MmbKRUfpfQdDiOt+v/9Pt01y25rM7Z694XCN/ePrqqxp5+p7P+palK9nbzi8zY7pZLefyWx3Nl9XJBprvDh3nHWl2hFOnHr49vr1z3+mJ974SrP/u0K19RF1CeVprx366vTDt+/wU6aZ3A4nu65kfzYAjUq1yvlr/832tjT1T9Pu9oCkjSrQyzV7aX5kiH41crBGHbNHO3fU2oN/HZ7S6/fOlnfjfl+ceJTmfbdSf3pwpiItrlWRF7R0w7l7J3zERSbut+U29t+fL9bK1RvUp1d37b/LoJx5XU1fAHDippJnVJgXjduPiQ4wOrofy5IaGn7qUEmql1Rv56nSLtaSWE99Ed1aN084W4FAx28U779hKy1YuFrX3v+R6iKN97Ym1l0F+QFNuGgfDRvSq9N87b1/2hTopkEJ7n+SUn/v4IV9QH7uS4YXyAnlE46XlPrgIvLjfqbVsS76W9Vh2qSuju8jHW8yptx2jE4eN7ndCXvXUNsjLjaXjh1L/XqW6L6rR8ddriOl3Qs14fz94y/YgVB+UL/YfbB+sfvgpO/DJL/nB5waV/KZo22wZUmxmNQQkf5ceYKq1fmFy5q2malsY6fcdoyuvGN6u6eQGjaopPmIi/Zu9+7HFe0ehXH5mJ2bj7ho6bkbj/jpRXjDTy/pC/IDmnB+5y/Ck91+JrPdaVpXdXW15s+fr+HDhyd0EblUO8KJkqKQLjxhF114grPbZXI7nOy6kv3ZAEjjSv6f49f+lhqP7ItGpS8ipXqh5peqU0GHy194YvzBRZMptx2jY/4wWe0ddxBQ4kdctHe/j706p92jMH59wJYJH3GxuRFb99E//3q04+1/ovebTk3b2JHDe6Y1q5/QFwASMankKRXkJX5IRWcDDNuWAi3PdRjMV8GIfdX7V2cqFPppn9KcBcv154dnKdbifgKW9OdzRuq3wxL7pP+wIb300qSjku6kVPc/Sam/d/DCPiC/9iXDC2S98jeeSMv9WCdfpSvvXZGW+4q3cy2RT0cle07DJk07ltL9hgQANuf0qAtbjTuQel9yh377lzlxl2/vaIi/PPRvfbxgTZtl9xzWs9URF5trGlA43TaO2nNou0OKzjS9CAcApFep3k/6aL/u592gMyd1fAqeJslcl6NpQJHu199nHrtr0kMKAEBu2D5vbvPgwumHytrT4/yJ6tlz27i333VYP02+NX3XskLuYXiBrBaN1ktzXkvqtrbdeKTFgD/cpW7dBkmSptzm7JzvU247psNzUafzQoQA4GVlDo+6iEja8vKnVFRUpCm3bZnUsLezAQUAILuNK1mU1BHX4WtfliRNuW17/e2FT/TmrCVtljl05EBHR1wAAGBaQDGdXTwn9dOoFw3QoAsntjqyAnAbwwtktYWTxiZ1O9uWlkWkv1aepik/Di6auHVuWQDIRqVao3wnR13YUpW1Y6uvsT0FALTU2evxUr3c5qiLRHbWNA0umlx44h4MKQAAvrNFkbRus8/Q3lzydOtTPCVh6LjnO702BeCWFJ+6gHeVv/cPx7ex7cYLCl27/gT9tfK0DpeLtyONHW0A0Kis9HVnR10EJB3KqZQAAJ3r6PX2uJKqVr2TzOACAAC/evKG1v14S8mTnZ5KMX5PFit87csMLmAMzzxkr/+86GjxptNEXdXJ0KIlBhQAEF+BGq9hkQjblkLb/lJVbgYCAGSNzY/AKNW/Wu2gSWh4Pjqx1/4AAPhFUz82DS466sN4PTnwysdVUNAt/QEBBxheICuVTzje0fJOBxcAgPhKNU9S44tiO4EJRiAg9TvyNK2bP9/lZACAbDGlxUWwF93xpONTC4T35gNJAIDsc1fPtxWLJj+44KhEeAXDC2SdjRsXO74NgwsASL+y4s+a/79l/XgERntDDEuyJKn3LhnJBQDIPmvXfuv8ze1vLnMhCQAAZkUitZK9zPF1Lmw1vi9jcAEvYXgB3/rzAx/q02/WtvhK49DiltInFXJwP7YtTawcltZsAAC1ebFsNf9P+8K//5Oqq6s7XgAAgA7UPzG+s4ppV3jbA1zJAgCASYtuPiWp223Y5UwN/8Uv0pwGSA3DC/hSy3PbtlSqT5UXk2wrwXPcqvGoi7UamcZ0AIBSrVUwaDoFAAAd+HlyO3YAAPAyp6dRbxYqkvr1S28YIA0YXsB3OhpcSNK4kv82Dy1sO/4Ao/GoiyPSmA4AIEmXF09NeIgsSdr5cNeyAACceeW9r/X41AUtvtJ4hPPvjhym436xnZlQnfj++5mObxPe7zgXkgAAYE5Nzdr4C3Wg34UPcu1BeJLT65kBRv35gQ87/F6pvlTeZuO4zq4Pa9tSfURaq57pCQcAaFbo8BVG+Miz3AkCAHDkqD9M3mxw8ZPHpy7o9INEptjP3uLsBr12dicIAAAGLbv9nKRuxzUu4GUML+Arra9x0VpZ8edtP+XbyfQiEpGu4SLdAAAAgKTOj3BOZjmvCp97nekIAACkVfnHU5O6HYMLeB2njULW2PzCsJ1pPF1Uf/fCAIBPXHTLNC1cXtviK42nBhnSr4vuveqQpO6zVHOdXe+i9y5JrQcAkD6vvPe14+W9cAqpysrlpiMAAGDeW487vkmX3/3RhSBAenHkBbJCqZ50tKOs8SLdv3QvEAD4wFF/mLzZ4OInC5fXJv3J2rLiOY6udxH+/Z+SWg8AIH06OlVUupZ3y8q7LnF2g60PdCcIAACGLFw4O6nbDRiwa5qTAOnH8AJZoawk/sW5mzQedcF1LgDkNjdPDeLkSDgAAFITdbR0eMylLuUAAMCM6NM3O74Np4uCX7B7Ab7XTRuV7+AEaJGotFZHuBcIADzuolumubo8AAAAAMB9pfre+Y32Pj79QQCXMLyA711c/Kqj05PUxdzLAgB+0NGpotK1vCM7H+7efQMAslr51Eed3aDbcHeCAABgSFnJh45vEx59sgtJAHcwvIDvbeHgWWxZ0u1Vie8om3LbMUkkAoDcVaqXHV2DKHzkWe6FAQBkty/ecLR4+OIbXQoCAEDmFarG0ZlIJElb7e9KFsAtDC/ga6Wa4WgnmSQ9cVtiO8oYXACAc2XFVY6OhgMAAAAAOHd68YuO33uFT77cnTCASxhewNfKir9ztqHusYOk+IMJBhcAkBwu1g0AaMnp62pehwMAkJifOX3vtfWBruQA3OT04CLAU5zuJAtf+Jfm/88bIwAAAMB9U247Rkf9YXJCyyWq/O2nnYU4+nxnywMA4GGletLxmUjCYy51JwzgIj4fCd8q1VOON9QAAA85kUOWASBXpP3I59n/dLR4eMeDnd0/AAAeNq5Ezs5EUjLMtSyAmzjyAr5VVmw721AfMMa1LACQC+J9crZU37YaKsfbRoe34WJxAJBLOPIZAIDUler/Kc/hHt3wpTe5EwZwGUdewLccnzLqwN+4EwQAckhnO57Kiv/TPLDgot0AAAAAkH5lxat4v4WcwfACvpTMuf0AAOnR0QCjaajMC2kAgJsaGqqd3eDQs9wJAgCAAU4/zLvFBbe4EwTIAE4bBV8qK3a2cyx0+v+5FwYAclB7A4zyCU8aSAIAyDU//PUCR8uHdz/cpSQAAGRWMh/m3WKLsDthgAzgyAv4ktMp86BBu7sTBACQnGGjTCcAAPjWJtMBAAAwwvGFuo8817UsQCYwvIDvlOobThkFAD4XPuFC0xEAAAAAwDdKtdD5hbp3/pU7YYAMYXgB3ykr/ijhKbNtS4Vn/sndQAAALVw423QEAADaKuBUGQCA7FBW/IHD6wt2cSsKkDEML+A7Tk4ZFY1K/fvv4loWAECj6NM3m44AAEAb4Su5SCkAIDs4PYX60HFPuBMEyCCGF8hqsZjpBAAAAADSpfyWK01HAAAg40q1wPEp1AMBh+eYAjyI4QV8pVSTE95Y27Y0qarI3UAAAAAAMqf+e9MJAADIuLLiWc5OGbXV/q5lATKJ4QV8pax4Q8Ib62hUWqsT3A0EAHAufIDpBAAAAADgG05PGRU++XJ3ggAZxvACvuJ0Yw0A8J7w2MtMRwAAAAAAXyjVWsenjAKyBbuCkbW43gUAAACQu7a85hnTEQAASNnlxVOdnTJq+MGuZQEyjeEFfKP8zSccXu9iT3cDAQAkSeVz3zEdAQCQA1as+NLR8nl5XVxKAgBA5hQ6PWXUcee7EwQwgOEF/OPT1xxe72K4u3kAAI1eu990AgBADqh6ZLzpCAAAAMgghhcAAAAAAAAA4DGletvZ9S567exaFsAEhhfISlzvAgAAAAAAAH5WVrzM0fUuwude514YwACGF/CF8reeSnjZxutd7OhiGgBA0nY+3HQCAEAu6L+H6QQAAKQswJ5b5Dj+BOAPH7+a8KKN17vY1b0sAICkhY88y3QEAEAOCJ85znQEAABSUqpVzk4ZBWQhhhcAAAAAAE+LRGpNRwAAIKOuLP5/jk4ZpUPOdC0LYArDC2QdrncBAAAAZJdFN19oOgIAABkVcrjXNrzHEe4EAQxieAHPK/94asLLNl7vYoSLaQAALZW/9DfTEQAAOWG96QAAAADIMIYX8L63Hk940cbrXezmYhgAQCsL3jWdAAAAAACySqkWOLveRV/2hSE7MbwAAAAAAGSP0FamEwAAkJKy4lmOrncRPvta98IABjG8QFbhehcAAABAbgtfdavpCAAApCTAHltAEsMLZJHG610MMB0DANCREy83nQAAAAAAAPgEwwt4WvmMVxJetvF6Fwe7mAYAkIrwNvubjgAA8KEVK740HQEAgIwp1dyEr3dh25KGsy8M2YvhBbzt/WdMJwAAAABgUNUj401HAAAgY8qK5yR8vYtoVAofd767gQCDGF4AAAAAAAAAgAdwvQvgJ/w5IGtwsW4AAAAAAADkCvaFIdsxvEBWaLxY91amYwBATim/+1rTEQAAaGZLUo9dDKcAACB5pXrT0fUuJlX1dDcQYBjDC3hW+VtPJbxs48W6D3AxDQCgjU1fm04AAECzqKR+v/uD6RgAACStrHilo+tdrNUR7gYCDGN4Ae/6+FXTCQAAAAAAAICM4HoXQGv8SQAAAAAAAACAj3C9C+QChhfICmywAcDb+l52v+kIAAAfKv/7zaYjAACQEeX/+9Dh9S52dDcQ4AEML+B7jRvsEaZjAAA6UVzcx3QEAIAfLZltOgEAAJnx4p0Or3exq7t5AA9geAFPWrXqq4SXbdxg7+ZiGgAAAAAAAABAJjG8gCdteuhPpiMAAAAA8BHOJAsAyBWcPh25guEFAAAAAMD3qnc503QEAACSsnHj4oSXbTx9eomLaQDvYHgB32PaDACZV/4KF+AGAHhMv36mEwAAkJTV91yW8LKNp08/zr0wgIcwvICvNU6bTacAgBw0/x3TCQAAAAAgS9imAwCexPACvtY4bT7NdAwAAAAAabZy5TzTEQAA8BzOQIJcwvACnlP+xVumIwAAAAAwrPLh601HAADAUzgDCXINwwt4z9QHTScAAKTTCZeaTgAAAAAAnlT+8n0JL8sZSJBrGF4AAABXhYcdaDoCAAAAAHjT19NNJwA8i+EFfI3z/AEAAABQt51MJwAAAECaMbyAbzWe56+X6RgAAAAADOt31lWmIwAA4Do+xItcw/ACvtV4nr/DTccAAAAAAAAAHIvFIgkv2/gh3n1cTAN4D8MLeEr5aw+bjgAAAAAAAAC4rmLSxQkv2/gh3m1cTAN4D8MLeMvcN00nAADEUT57iukIAAAAAOB/9krTCQBPY3gBAACcefvvphMAALJc+b1/Mh0BAABP4XoXyEUML+BbbLQBAACALLXhK9MJAADwjMbrXZhOAWQewwv4UuNGew/TMQAAAAAAAADH6uo2Jrxs4/UuTnMxDeBNeaYDbK6iokJlZWVat26dSkpKNGnSJG2zTeuL0cRiMd1888368MMPFQwG1aNHD914440aMmSIodTItMaN9vamYwAwiL7wib2PN50AQA6jKwAAiaAvYMKSWy8wHQHwPM8deXHdddfpxBNP1LRp03TOOeeorKyszTLvvvuuPvvsM02ePFlTpkzRPvvso9tvv91AWqRT+bQnTUcA4CP0hT+ER59sOgKAHEZX5Ibel9xjOgIAn6MvYEaN6QCA53lqeLFmzRrNmzdPRx99tCTpkEMO0fLly7Vw4cI2y9bX16uurk62bauyslL9+vXLdFyk2yeTTScA4BP0BQAgHroid3TtOsB0BAA+Rl/AD7juK3KVp04btWzZMvXu3Vt5eY2xLMtS//79tXTp0laH4Y0aNUqzZs3S/vvvr+LiYvXt21dPPfVUSuu2bVvV1dUp3UeyampqWv3ba7yeLx5Tv9cmXn/8yJcaE/ls25ZlWRlbnxeZ6gs3usLrz/Emyf7cTm/nlceDHN7M0TKD6Sx+yJHrfeHVrvDKcycdTL/OblJdXe2rx5Ws7iBrcnK9KySz+6K88BzoiJeepx3xQ0Yp9ZzxLtadjj72w2NJxvRINqOpvvDU8CJR8+bN0zfffKN//etfKikp0a233qrrr79et956a9L3WV9fr/nz56cxpXMVFRVG1x+P2/lKlPgT0snE2fTvtUmu/35TRb6f1NfXq6CgIGPr87N094WbXeH153jLnzvR7XVEyW+DvfJ4kKM1r+SQvJPFyznoi8SY6gqvPHdS4ebr7GS7xk+PK1ndQVZn6IrEubEvygvPgXjImD6b50y06+JdrDudfeyHx5KM6eE0o6m+8NTwon///lq1apUikYjy8vJk27aWLVumAQNaHwb86quvau+991a3bt0kSb/+9a915plnprTuUCik4cOHp3QfyaqpqVFFRYWGDh2qwsJCIxk6k6l8y9+Mv4ytponzjgnfr6nfaxN+v6khX1uhUCgj6/EyU33hRleYeY4vdnyLlj93IttrScqX822wV/7myeHNHF7K4occud4XXu0Krzx32kqtG9LNadd493Fti6zuIGtycr0rJLP7orzwHOiIl56nHfFDRqn9nMvvGd/usnYS95+OPvbDY0nG9Eg2o6m+8NTwomfPntphhx302muv6bjjjtO0adPUt2/fVofpSdLgwYP1wQcf6Mwzz1QoFNJ7772nbbfdNqV1W5aloqKilO4jVYWFhcYzdMYr+RonzrsmvLwXMkveefw6Qr7UZDJfrh/WLZnrCze7wuvP8WSzJXs7rzwe5PBmDsk7WbycI9f7wutd4ZXnTircyl/+yv1J5/DT40pWd5DVmVzvCsnsvigvPAfiIWP6tMoZ+TZt95vOn90PjyUZ08NpRlN94anhhSSNHz9e48aN04MPPqji4mJNnDhRknTttddq1KhRGj16tE455RR99913OuaYY5SXl6fevXtr/Pj2J5YAgOxEX5ixfn2F6QgAkDC6wqfmv2M6AYAcQ1/Ay7hWN3KZ54YX4XBYzz//fJuvT5gwofn/h0Ih3XjjjZmMBZc5/XQVANAXZqz92x9MRwCAhNEVAIBE0BfwsmVML5DDAqYDAJL4dBUAAAAAAADQgm1LD1cdZzoGYAzDCwAAAACAP51wqekEAAA4Uv7G4wkvG41KlSpxMQ3gbQwv4DsxDpcDAH/ouZPpBACALBcedqDpCAAAODNnqukEgG8wvICv2LY0qWqk6RgAgASEz7vedAQAAAAAAOBTDC/gK9GotFbDTMcAAAAAAAAAXMXZR5DrGF4AAAAAAAAAgIc0nn1kZ9MxAKMYXsC48gfGm44AAAAAAAAAuKr82xkJL9t49hGGF8htDC9g3povTScAAAAA4AHlj95kOgIAAO55/nbTCQBfYXgBX+FUfwAAAEAWW/6p6QQAAADwCIYX8JVNTC8AAAAAAACQ5bhYN8DwAj5zT9XRpiMAAAAAAAAArmm8WHeR6RiAcQwv4Cvr1cN0BADIWeV/v9l0BAAAmpWcM950BAAAXNF4se4TTMcAjGN4AQAAErNktukEAAA069NnhOkIAAAkbPk9DN0BpxhewKjyB9hwAwAAAAAAIMtFvjWdAPAdhhcwa82XphMAAAAAAAAAnsG1uoFGDC8AAEDaFZ75J9MRAAAAAMCXfmB6AUhieAEAAFzQv/8upiMAAAAAgO/YtvRY1fGmYwCewPACvrHFBbeYjgAAAADAJQsXzjYdAQAAd7z3XsKLRqNSlYpdDAP4B8ML+MYWW4RNRwAAAADgkujTN5uOAACAK4rqPjIdAfAlhhcAAAAAAAAA4BJ2wALJ4W8HxpT/55+mIwAAAAAAAACeEeNi3UAzhhcw572nTScAAAAA4EfhA0wnAAAg7WxbmlQ1zHQMwDMYXgAAAAAAfCU89jLTEQAASLtoVFqrkaZjAJ7B8AIAAAAAAAAAXLD8+08VNB0C8CmGF/CHA8aYTgAAOa182pOmIwAAAACA/7x6pyzTGQCfYngBXwgf+BvTEQAgt30y2XQCAAAAAACQQxheAAAAAAAAAIBhsZjpBIC3MLwAAAAAAAAAAMMmVRWYjgB4CsMLGFE+8TLTEQAAbjnsbNMJAAA+U/7M7aYjAABg3FqdZDoC4CkML2BG7AfTCQAALgnvdpjpCAAAv6mYYToBAAAAPIbhBQAAAAAAAACkWfk9fzQdAfA1hhfwvsBg0wkAAAAAAAAAZzbON50A8DWGF/C88Lg7TUcAAAAA4BF5p5aZjgAAAIAMYHgBAAAAAPCNLbfc03QEAAAAZADDCwAAAAAAAAAwqM+lfzMdAfAchhfIuIULZ5uOAAAAAAAAAHhGSUk/0xEAz2F4gYyLPn2z6QgAAAAAAACAa8ofvcl0BMD3GF4AAAAAAAAAQDot/9R0AsD3GF4AAIBOlepJ0xEAAAAAAECOYXgBb9tqf9MJACDnlRWbTgAAyGblT/zVdAQAAAB4EMMLeFr45MtNRwCAnBfg1QIAwE2LZ5lOAACAUSXnjDcdAfAkdkcAAAAAAAAAgCF9+owwHQHwJIYXAAAgbYaUPWc6AgAAAAAYVb7gX6YjAFmB4QUyqvzzaaYjAABcFAyGTEcAAGSxLr/7o+kIAADE99JdphMAWYHhBTLr9YdMJwAAAADgUwMG7Go6AgAAADKE4QUAAAAAAAAAAPAUhhcAAAAAAAAAYMLwg00nADyL4QW8a/ejTScAAAAAAAAAXBM+7nzTEQDPYngBzwoferrpCAAAAAAAAAAAAxheAAAAAAAAAEAalD8w3nQEIGswvAAAAAAAGFE+7UnTEQAASK81X5pOAGQNhhfImBUr2HgDAAAAaOGTyaYTAAAAwKMYXiBjqh7hsDkA8JtS/VPBoOkUAAAAAAAg1zC8AAAAHSor3iTLMp0CAAAAALLPFhfcYjoC4GkMLwAAQIcCvFIAAHjFYWebTgAAQFptsUXYdATA09glAW8asKfpBAAAAAA8JLzbYaYjAAAAIIMYXsCTwr8rMx0BAODU8ZeYTgAAAAAAxpTfcqXpCEBWYXgBAADSIrzdQaYjAAAAAIA59d+bTgBkFYYXAAAAAAAAAADAUxheAAAAAAAAAAAAT2F4gYwov/kK0xEAAAAAAAAAT9jymmdMRwA8j+EFMiOy0HQCAAAAAAAAwBPy8rqYjgB4HsMLAAAAAEDGlX/9gekIAACkzaZNS01HALIOwwt4UKnpAAAAAADc9vLdphMAAJA2q+6+1HQEIOswvIDnbPV/D5qOAAAAAAAAADgQMx0AyDoML+A5lsXTEgAAAAAAAAByGXuJAQAAAADetv0vTScAACB9um9vOgHgCwwvAABAu0r1mYJB0ykAAJDCvz7PdAQAANImfNENpiMAvsDwAq4rf/tp0xEAAEkoK54nyzKdAgAAAAAA5CKGF3Df7H+aTgAASEKAVwkAAAAAAMAQdksAAAAAAAAAQJLKX7zXdAQgKzG8AAAAqdvjGNMJAAAAAMCM/71nOgGQlRhewFsOPct0AgBAEsKHnGY6AgAAAAAAyCIML+Ap4d0PNx0BAAAAAAAAAGAYwwsAAAAAQEatXv216QgAAJhx0hWmEwC+wfACAAAAAJBRGx+81nQEAACMCP9sP9MRAN9geAFXRaP1piMAAAAAAAAAAHzGc8OLiooKjRkzRocccoiOP/54ffPNN+0ut2DBAp166qk67LDDdNhhh+mtt97KcFIkYuGki0xHAJCl6AsAQDx0BQAgEfQFUrFo0cemIwBZK890gM1dd911OvHEE3XcccfpzTffVFlZmV5++eVWy9TU1OiCCy7QzTffrD322EPRaFQbNmwwlBidW2M6AIAsRV8AAOKhK7JE391MJwCQ5egLpCLy1CTTEYCs5akjL9asWaN58+bp6KOPliQdcsghWr58uRYuXNhqualTp2qXXXbRHnvsIUkKBoMqLS3NeF4AgBn0BQAgHroie4TP5voYANxDXwCAd3nqyItly5apd+/eystrjGVZlvr376+lS5dqyJAhzct9++23CoVCOvfcc7V8+XINGzZMZWVlKZWGbduqrq5O+WdIRk1NTat/e03m8g105Xdg6vfahN9vasjXlm3bsiwrY+vzIlN94UZXeP05nqh0PS5eeTzI4c0cLTOYzuKHHLneF17tCq88d9IhU6+zE1mPnx5XsrqDrMnJ9a6QzO6L8sJzoCNeep52xA8Z25Pu/kzH/fnhsSRjeiSb0VRfeGp4kahoNKr//Oc/euGFF9SnTx/dfvvt+vOf/6y777476fusr6/X/Pnz05jSuYqKCqPrjyeZfCVK7EkWkVR56Ola58LvwPTvtUk2/n4ziXw/qa+vV0FBQcbW52fp7gs3u8Lrz3G7k+9FlP5trVceD3K05pUckneyeDkHfZEYU13hledOKlLZ9jt5n+BkPX56XMnqDrI6Q1ckzo19UV54DsRDxvgS7bSYpA0amvZ9X+l8L2b6sUwEGdPDaUZTfeGp4UX//v21atUqRSIR5eXlybZtLVu2TAMGDGiz3MiRI9W3b19J0tFHH62zzjorpXWHQiENHz48pftIVk1NjSoqKjR06FAVFhYaydCZVPItfzOx5fKlBB//xY7Wr4Tv1z3Z/PvNBPK1FQqFMrIeLzPVF250hZnnuPNtaWefr0h8Gx6fV/7myeHNHF7K4occud4XXu0Krzx32srs6+x0v0/w7uPaFlndQdbk5HpXSGb3RXnhOdARLz1PO+KVjIl0mq3Gc/cPv/yGOEua2e/llceyM2RMj2QzmuoLTw0vevbsqR122EGvvfaajjvuOE2bNk19+/ZtdZieJB122GF66aWXVFlZqZKSEn3wwQfabrvtUlq3ZVkqKipK6T5SVVhYaDxDZ9zO59Z9e+UxzfXfb6rI95NcP6xbMtcXbnaF157jpZqiYDDx5dOd3SuPBzm8mUPyThYv58j1vvB6V3jluZOKTOV3sh4/Pa5kdQdZncn1rpDM7ovywnMgHjKmlxs503mffngsyZgeTjOa6gtPDS8kafz48Ro3bpwefPBBFRcXa+LEiZKka6+9VqNGjdLo0aM1YMAAnXvuuRozZowsy1Lfvn11ww3xJpcAgGxCX7irrHideC8LwO/oCgBAIugLJKv82xmmIwBZLeXhxdq1a/Xtt99q5cqVikQi7S5z7LHHJnx/4XBYzz//fJuvT5gwoc19OrlfAIBZ9IW/BAKmEwDIRXQFACAR9AU84/nbTScAslrSw4va2lrdcMMNmjx5sqLRaLvLNF2FnA17biq/7WrTEQB4AH0BAIiHrgAAJIK+AIDckvTw4sYbb9TLL7+sYcOG6ZBDDlHv3r2Vl+e5s1DBpNrvTCcA4AH0RQ445gLTCQD4HF2RW8o/eMF0BAA+RV8AQG5Jegv/1ltvacSIEXr++ecVdHJFTwBATqEvsl94xGjTEQD4HF2RY/7d9tQsAJAI+gJ+ZUuyBu1vOgbgO0mf0ToajWqvvfaiLAAAnaIvAADx0BUAgETQF/CrqKR+vznXdAzAd5IeXuy4445auHBhOrMghw266gnTEQC4hL4AAMRDVwAAEkFfAEBuSXp4cemll2rGjBl677330pkHOSoUKjEdAYBL6AsAQDx0BTr0i9+aTgDAQ+gLAMgtSV/zYtddd9Wjjz6qCy64QNtvv7222247FRcXt1nOsixdeOGFKYUEAPgXfQEAiIeuQEfC+/7adAQAHkJfwEvKn73DdAQg6yU9vFi3bp1uv/12bdiwQR999JE++uijdpejMAAgt9EXAIB46AoAQCLoC3jK9/82nQDIekkPL2688UZ9+umnOuigg3T44YerT58+XDAJANAGfQEAiIeuAAAkgr4AgNyS9PDiww8/1F577aUHH3wwnXmQJcrfeNx0BAAeQV8AAOKhKwAAiaAv4Fcx0wEAn0r6gt22bWvEiBHpzIJsMmeq6QQAPIK+AADEQ1cAABJBX8CvqoefYjoC4EtJDy922203LViwIJ1ZAABZiL4AAMRDVwAAEkFfwLeGDDGdAPClpIcXV199tebOnaunn346nXkAAFmGvvCfbtooTh0MIJPoCgBAIugLAMgtSV/z4pFHHtGwYcM0YcIEPfXUUxo2bJiKi4vbLGdZlm666aaUQiLLHXmu6QQAXERf+M/Fxa/KskynAJBL6AoAQCLoC3hF+dx3TEcAckLSw4t//vOfzf9/4cKFWrhwYbvLURiIJ7zzr0xHAOAi+sJ/tkj6uEwASA5dkTvKX7nfdAQAPkZfwDNeo8+ATEh6eDF9+vR05gAAZCn6AgAQD12RQ+bzSVUAyaMvACC3JD28GDhwYDpzAACyFH2R5XrsYDoBgCxAVwAAEkFfAEBu4cQQAAAgaeEL/2I6AgAAAAB417acLh1IVtJHXrz66qsJL3vssccmuxr4UPnt15iOAMBD6AsAQDx0Bdp1wqWmEwDwGPoCftTviFO1bv580zEAX0p6eFFWVibLsjpdxrZtWZZFYeSamm9NJwDgIfQFACAeugLtCQ870HQEAB5DXwBAbkl6eDFx4sR2v75p0yZ99dVXmjp1qkaNGqVf/OIXSYcDAPgffQEAiIeuAAAkgr6AF5R/9x/TEYCckfTw4te//nWn3z/ppJN0+umna+zYscmuAgCQBegLAEA8dAUAIBH0BTzhH7eZTgDkDNcu2L3rrrtq1KhRuuuuu9xaBbLAwCsfNx0BgGH0BQAgHroCAJAI+gIAsotrwwtJGjBggBYsWODmKuBzBQXdTEcA4AH0BQAgHroCAJAI+gIAsodrwwvbtvXJJ5+ooKDArVUAALIAfQEAiIeuAAAkgr6A52zzc9MJAF9L+poXH3/8cbtfj0QiWrFihSZPnqy5c+fq2GOPTXYVAIAsQF8AAOKhKwAAiaAv4DfhEy9WdXW16RiAbyU9vDj11FNlWVaH37dtW7vttpvKysqSXQUAIAvQFwCAeOgKAEAi6AsAyC1JDy8uvPDCdgvDsix1795dO+64o3beeeeUwsF/yt99znQEAB5DXwAA4qErckP5s3eYjgDA5+gLAMgtSQ8vLr744nTmQLb46CXTCQB4DH0BAIiHrsgR3//bdAIAPkdfwLTy268xHQHIKa5dsBsAAPhPqZ5UMGg6BQAAAAB4UM23phMAOSXp4cWCBQv00ksvqbKysvlrtbW1uv7663XAAQfol7/8pZ57jlMIAUCuoy/8paxY6uQ0wgDgCroCAJAI+gIAckvSw4v7779fd911l4qLi5u/dvvtt+v5559XVVWVli1bpr/85S+aMWNGWoIiC/3yDNMJAGQAfeEvAY7JBGAAXYHN5Z3KxXYBtEVfAEBuSXoXxZdffqmRI0c2XygpEonolVde0U477aSPPvpI06dPV2lpqZ588sm0hUV2Ce91lOkIADKAvgAAxENXYHNbbrmn6QgAPIi+gJ8MvPJx0xEA30t6eLFu3Tr179+/+b/nzp2ryspKjRkzRgUFBerbt69Gjx6tr7/+Oi1BAQD+RF9kr76X3W86AoAsQVcAABJBX8BPCgq6mY4A+F7Sw4tgMKj6+vrm/549e7Ysy9LIkSObv9ajRw+tW7cutYQAAF+jL7JXcXEf0xEAZAm6AgCQCPoCAHJL0sOLgQMHatasWc3//eabb2rQoEEaOHBg89dWrFihHj16pBQQAOBv9AUAIB66AgCQCPoCJn3//UzTEYCck/Tw4phjjtHXX3+t3/zmNzrllFP09ddf68gjj2y1zIIFCzRkyJCUQ8Ifyl/6m+kIADyIvgAAxENXAAASQV/AJPvZW0xHAHJO0sOL3/72tzr00EM1b948ffrppzrwwAN13nnnNX//m2++0ddff6299947LUHhAwveNZ0AgAfRFwCAeOgKAEAi6AsAyC15yd4wFArpzjvvVGVlpSSppKSk1fd79uypV199tdWhewCA3ENfAADioSsAAImgLwAgtyQ9vGiyeVE0KS0tVWlpaap3DwDIEvQFACAeugIAkAj6Ap639YGmEwBZIeXhhSTFYjGtXr1akUik3e8PGDAgHatBNjnpCtMJABhAXwAA4qErslP5/X82HQFAlqEv4GXhMZeajgBkhZSGF5MnT9Zjjz2m7777TtFotN1lLMvSV199lcpqkIXCP9vPdAQAGURfAADioSuy3Nq5phMAyBL0BQDkjqSHF48++qhuvfVW5eXlaY899lDv3r2Vl5eWAzkAAFmEvgAAxENXAAASQV8AQG5Jegv/9NNPq2/fvvrHP/6hfv36pTMTACCL0BcAgHjoCgBAIugLmFL+2sOmIwA5KZDsDdeuXatf/epXlAUAoFP0BQAgHroCLZVeeJvpCAA8ir6AMXPfNJ0AyElJDy+GDh2qjRs3pjMLfKz8jcdNRwDgUfSFf5SqXMGg6RQAchFdgZZ69BhqOgIAj6IvACC3JD28OOOMMzR9+nQtWbIknXngV3Ommk4AwKPoC/8oK/63LMt0CgC5iK4AACSCvgCA3JL0NS9+/etfa82aNRozZoxOPvlkbbfddiopKWl32T333DPpgAAAf6Mv/COQ9EcaACA1dAUAIBH0BXzh2AtNJwCyRtLDC0mqrKxUZWWl7r777k6Xmz9/fiqrAQD4HH0BAIiHrgAAJIK+gNeFdxhlOgKQNZIeXtx111168MEHVVpaqsMPP1y9e/dWXl5KsxDkiiPPNZ0AQAbRF1nqZweZTgAgi9AVAIBE0BcAkFuS3sK//PLLGjp0qF566SUVFxenMxOyXHjnX5mOACCD6IvsFD7pEtMRAGQRugIAkAj6AiaUL/iX6QhAzkr67NYbN27Uz3/+c8oCANAp+gIAEA9dAQBIBH0BI166y3QCIGclPbzYdttttXLlynRmAQBkIfoCABAPXZHd+MQqgHShLwAgtyQ9vDjvvPM0ffp0/fe//01nHgBAlqEvAADx0BVZjk+sAkgT+gIAckvS17zYuHGj9t13X40ZM0bHHHOMtttuO5WUlLS77LHHHpvsauAD5e8/bzoCAA+jLwAA8dAVAIBE0BfwvO1/aToBkFWSHl6UlZXJsizZtq2XXnpJkmRZVqtlbNuWZVkURrab8YLpBAA8jL4AAMRDVwAAEkFfwOvCvz7PdAQgqyQ9vJg4cWI6cwAAshR9AQCIh65As+EHm04AwMPoCwDILUkPL37961+nMwcAIEvRFwCAeOgKNAkfd77pCAA8jL5AppXPnGw6ApDTkr5gN5CUUaeaTgAAAAAAAADEN/1J0wmAnJb0kRdLly5NeNkBAwYkuxpkmfA+x5qOACDD6AsAQDx0BQAgEfQFAOSWpIcXo0aNanNRpPZYlqWvvvoq2dUAAHyOvgAAxENXAAASQV8AQG5Jenhx7LHHtlsYmzZt0tdff63Fixdrzz331KBBg1IKCADwN/oCABAPXQEASAR9AU/b9zemEwBZJ+nhxaRJkzr8nm3beuyxx/TII4/opptuSnYVAIAsQF/4Q6meVDBoOgWAXEVXAAASQV/Ay8K/GGM6ApB1XLlgt2VZOuuss/Szn/1Mf/3rX91YBTyifOZk0xEA+Bh94R1lxVICR+ADQMbRFQCARNAXAJB9XBleNBkxYoRmzpzp5ipg2vQnTScAkAXoC/MCrr4iAIDU0RUAgETQF0iXH374xHQEIOe5uqvihx9+UCQScXMVAIAsQF/4THBL0wkA5CC6wp/KZ7xiOgKAHENfIF0anpxoOgKQ85K+5kVHYrGYVqxYoVdeeUXTp0/XPvvsk+5VAACyAH3hX+GyO0xHAJAj6Ios8P4zphMAyAH0BQBkp6SHF9ttt52sTk6Obdu2unfvrmuuuSbZVSDb7Psb0wkAGEBfAADioSsAAImgLwAgtyQ9vNhzzz3b/XogEFD37t01YsQIHX/88erZs2fS4ZBdwr8YYzoCAAPoCwBAPHQFACAR9AU8a+h+phMAWSnp4cVTTz2VzhwAgCxFXwAA4qErIEk6gA87AegcfQGvCp9yhekIQFZyfMHu+++/X7fffrsaGho6XKa+vl533HGHHnrooZTCAQD8i74AAMRDV6Cl8IGcZhZA++gLAMhNjoYX//nPf3T33XerR48eys/P73C5UCikHj166I477tDMmTNTDgkA8Bf6AgAQD10BAEgEfQET1q0rNx0BgBwOL1599VV169ZNv/3tb+Mue8opp6h79+565ZVXkg4Hbyt/8V7TEQB4FH0BAIiHrgAAJIK+gAnr7rvKdAQAcji8mDNnjvbdd1+FQqG4y4ZCIe2777767LPPkg4Hj/vfe6YTAPAo+gIAEA9dAQBIBH0BALnL0fBi5cqVGjx4cMLLDxo0SKtWrXIcCgDgb/QFACAeugIAkAj6AgByl6PhRSAQ6PTiSJtraGhQIOD4muAAAJ+jLwAA8dAVAIBE0BfwvJ47mU4AZC1HW/M+ffrom2++SXj5b775Rn369HEcCllozB9MJwCQQfQFACAeugIAkAj6Al4XPu960xGArOVoeLH77rtr5syZWrx4cdxlFy9erJkzZ2rPPfd0FKiiokJjxozRIYccouOPP77TgrJtW6eddpr22GMPR+tA5oW33td0BAAZRF/4S6leUjBoOgWAXENXZL/yL982HQFAFqAvACB3ORpenHLKKYpEIrrkkku0du3aDpdbt26dLr30UkWjUY0dO9ZRoOuuu04nnniipk2bpnPOOUdlZWUdLvv3v/9dW265paP7BwC4j77wl7LialmW6RQAcg1dkQOmPGA6AYAsQF8g0zZujD8oA5AZjoYXO+ywg04//XR99dVXOuKII3TXXXdp5syZqqioUEVFhWbNmqU777xTRxxxhP773//qjDPO0A477JDw/a9Zs0bz5s3T0UcfLUk65JBDtHz5ci1cuLDNst98843eeecd/f73v3fyIwAAMoC+8BdOCQzABLoCAJAI+gKZtvqey0xHAPCjPKc3KCsrU0FBgR599FE98MADeuCB1p+msW1bwWBQ5557ri677DJH971s2TL17t1beXmNsSzLUv/+/bV06VINGTKkebmGhgb96U9/0oQJE9J2ESbbtlVdXZ2W+3Kqpqam1b+9Jh35TD22ptct5cbv103ka8u2bVk++Jh8NvaFG13h9ed4e9zcrnrl8SCHN3O0zGA6ix9y+KEvcrErvPLcSYd090Eq9+enx5Ws7iBrcvzQFVJ29oXkjedAR7z0PO2IexltR0vH6y+3H8t09HFu/77TJ5szmuoLx8MLy7J0xRVX6IQTTtDLL7+sOXPmaPXq1ZKkXr16abfddtNxxx3n6iF09957r375y19q6623Tuich4mor6/X/Pnz03JfyaqoqDC6/nha5XvzPnWXlMhTNiIZfWxN/16b+Or360Hk+0l9fb0KCgoytr5kZWNfuNkVXn+O2z/+s2Hr32hdBrarXnk8yNGaV3JI3sni5Rx+6Itc7gqvPHdSEe/nLFFibzhtSRu0c1r6xU+PK1ndQVZn/NAVUnb2heSN50A8uZgx0f6SpHolvt/Jrccyne9Rc/H37YZszGiqLxwPL5psueWWuvzyy9OZRf3799eqVasUiUSUl5cn27a1bNkyDRgwoNVyH3/8sZYtW6ZnnnlGkUhElZWVGjVqlF566SWVlpYmte5QKKThw4en48dwrKamRhUVFRo6dKgKCwuNZOhMe/mWv7k+4dvnS2l8bJ2/QDD1e23ix9+vl5CvrVAolJH1pEs29YUbXWHmOe58W2r9+M/wHw+nd4tX/ubJ4c0cXsrihxx+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S1J0uhbJYfz48frxxx/r/11YWKh//vOfGjVqVKO18XqfZUdOf69Ksv/1VFOc8DorGCe9DmuOE16jNcdp72HVccpru6gzYYuHHnrIvOOOO0Jae84555hvvPGGaZqm+d///tccPnx4LKOZpmmaX3/9tbl582bTNE1z1apV5oABA8ylS5cGXHv22WebH374YcwzhbIfli1bZh5yyCFmaWmp6ff7zdGjR5svvPBCzLNVVVWZn376qen3+03TNM3nn3/ePPvssxutW758ubnffvvFPE8gRx55pLlgwYJm19i1/3b09NNPm6NHj250erz237fffmsWFxc32meh3hedsh/hTHY/vjrhsdRJj5lOfGyM52OgUx7vAuUI9XZimtHdN03tk1BuK6YZ232yo6ZuK6Zp73MOhMZKH9jFjtch4bDyeOEEy5cvN8844wzz9NNPj8vrqHBNmDDBvO222+r3a2lpqc2JAvP7/Wb//v3NhQsXmqZZu3/79u1rbtmyxeZktSLtWiSn0tJSc88992zyfhWv91l25PT3qkzT/tdTTXHC66xgnPQ6rDlOfI3WHLvfw6rjlNd20cbXRjncunXrNH/+fJ144omSpCFDhqikpERLly6N6eUedNBB9ZPp/Px8dejQQcXFxTG9zOaEuh9mzZqlQYMGqUOHDjIMQyNHjtS7774b83wZGRkaOHBg/eR/77331sqVK2N+udFm1/7b0bRp03TaaafF/XLr9O/fX506dWpwmpX7olP2I5zJzsdXpzyWJtpjZrzv0/F8DHTK412gHHbdTgJlsSKW+2RHdvclIuO059s7sut1SDgSqVf8fr/+9a9/6V//+pc8Ho/dcZpUUVGhadOm6Zprrqnfrx06dLA5VdMMw9CWLVskSWVlZWrTpo1j9m+kXYvk9NZbb+nQQw919P2qOXbehp3Yn055nRVMIvVlMHbvy+055Tm5U17bRRvDCxvNnDlTJ554okaNGqU5c+YEXFNcXKwOHTooLa32G74Mw1B+fr5WrVoVt5xff/21Nm3apD333LPJNffee69OOOEEXX311Vq+fHnUM4S6H4qLi9WlS5f6f3fp0sWWEps6daoGDRoU8GeVlZU69dRTdcopp+iRRx6Rz+eLW67rr79eJ5xwgm666SatX7++0c+dsP9+/PFHbd68WUcccUTAn9u1/6zcF52wH5EY4v346tTHUrsfM5302OiEx0CnPt41dzuRnHFbkeK3T4LdViR7n3PAmlD6IN6c8DokXMEeL+z07LPPql+/furbt6/dUZq1bNkytWnTRo8//riGDx+uM888U998843dsQIyDEOTJ0/W5ZdfriOPPFJnnnmm7rrrLscMLwJJ5PsXouONN94I+mZnrN9naUqivFclOeP9Ksm5r7OCsft1WHOc9BqtOU54/dYcp762s4JjXsTIGWecoaKiooA/e/vttzVixAhdeumlSk9P1w8//KDLL79c06ZNa3AjsTNffn6+JGnRokW68cYbNXnyZGVlZQVcf/fddys/P1+maerFF1/U6NGj9f7778cquuM9/vjjWrZsmZ577rlGP+vYsaM+//xztWvXThs3btQ111yj//znP7r44otjnuuFF15Q586dVVNTowceeEA33HCDnnrqqZhfrlXTpk3TSSedVP/Auj079x8QKh5frbH7MdNpj408BgbW3O1E4rYSSCrfXpwimn2A0AV7vLDT77//rg8++EAvvPCC3VGC8vl8WrlypXbddVddZTXQEAABAABJREFUd911WrBggc4//3y99957at++vd3xGvB6vXrsscf0yCOPqH///po3b57GjBmjGTNmKDc31+54SCGhPu5///33Ki8v18CBA5s8r1i9DnD6e1WhZOT1VHTY/TqsOU573t0cXr/FHsOLGHn11VdDXrvffvtpjz320Pz58xsVQn5+vtasWSOv16u0tDSZpqni4mJ17tw55vn++OMPXXrppbrzzju1//77N7murjgMw9DZZ5+tu+66Sxs2bFDbtm0jyrjjZYSyH/Lz87Vs2bL6f69cubI+Xzw888wz+uCDD/Tcc88pMzOz0c89Ho/atWsnSWrTpo1OPfVUvfvuu3F54KrbV+np6Tr33HM1ZMiQRmvs3n/l5eX673//q2nTpgX8uZ37z8p90e79CHs5+fHVaY+lTnjMdNJjo1MeA532eBfsdiI557YixWefBLutSPZ2JmpFsw/sEKvXIbEUyuOFnb7//nutXLmy/vFjzZo1+uOPP1RaWqozzzzT5nQN5efny+Vy6YQTTpAk7bHHHuratat+//13xw0vFi5cqNLSUvXv31+StNdeeykvL08LFy7UIYccYnO6wBLx/oXgQn0faNq0aTrllFPkdrubXBOr91mc/l5VqBmd9H5V3eU46XVWME54HdYcJ71Ga45TXr81x2mv7cLB10bZpKSkpP5/FxUVaeHChQ2OPl+nXbt26tOnj2bMmCGp9vvH8vLy1L1795jmW7JkiS655BLddtttzT7h83q9Wrt2bf2/Z82apfbt20e9CELdD0OGDNHHH3+sNWvWyDRNvfzyyxo2bFhUszTl2Wef1Xvvvadnn31WrVq1Crhm3bp1qqmpkSRVV1frgw8+UO/evWOeraKiQps3b67/93vvvac99tij0To7958kvf/++9p99921yy67BPy5XftPsnZftHs/wtnsfHx10mOpEx4znfbY6JTHQCc93oVyO5Gcc1uR4nN7CXZbkeztTIQm1D6wi12vQ8IV6uOFnc4880x9+eWX+vjjj/Xxxx9rn3320e233+64wYUk5ebm6qCDDtKXX34pSVq+fLlWrFjR7OOOXfLz81VaWqolS5ZIkpYuXarly5dr5513tjlZ0xLt/oXoKSsr06xZs3Tqqac2uSZe77ME4vT3qiTnvV8lOet1VjBOeB3WHKe9RmuOU16/NcdJr+3CZZimadodIhXdcMMN+vXXX+V2u+V2u3XJJZfo2GOPlSTNnj1bH3/8sSZMmCBJKiws1I033qiNGzcqOztbEydOVK9evWKa7/zzz9f8+fMbTOKuu+46HXbYYfrll1/00EMP6amnnlJFRYXOPvts1dTUyDAMtW3bVjfeeKN23333qGdqaj+MGzdOgwYN0uDBgyVJr732mp588klJ0oABAzR+/Hilp6dHPc/2SkpKNHDgQHXr1k3Z2dmSaiesr7/+uh588EF17NhRI0eO1AcffKCHHnpILpdLPp9PBx54oG644YaYfx/r8uXLdcUVV9R/t17Xrl01bty4+v/avf/qjBgxQn/7298aPJGzY//dfPPN+vTTT7V27Vq1adNG2dnZ+vDDD5u9LzppP8LZ7H58dcJjqVMeM5322GjHY6BTHu8C5Xj++eebvJ3Ect8EyvKf//ynydtKPPfJhx9+KCnwbSWW+wSx0VwfOIUdr0PC0VyvONk555yjc889V0cddZTdUQJavny5brrpJm3cuFGGYeiyyy5r8lNndnv33Xf1xBNPyDAMmaapSy65pP5TI3YLp2uRvF599VW98847jb4+zq73WXbk9PeqJPtfTzXFCa+zgnHK67DmOO01WnOc8h5WHae8tos2hhcAAAAAAAAAAMBR+NooAAAAAAAAAADgKAwvAAAAAAAAAACAozC8AAAAAAAAAAAAjsLwAgAAAAAAAAAAOArDCwAAAAAAAAAA4CgMLwAAAAAAAAAAgKMwvAAAAAAAAAAAAI7C8AIAAAAAAAAAADhKmt0BALtce+21evfdd3Xffffp+OOPb3JdWVmZDjnkEKWnp+vTTz/VV199pY8//ljz5s1TSUmJJGnXXXfVKaecojPOOENut7vReWzatEmPP/64PvroIxUXFysnJ0cDBgzQFVdcod12263B2rlz52rUqFHNZu/WrZs++uijMK41AMAqp/ZFnTlz5uiZZ57R77//rg0bNqhjx47ae++9dfHFF2v33XePzk4AADTL6V3xzjvv6MUXX9SiRYtkmqZ22WUXnXXWWRo+fHh0dgAAICTh9MWXX36pDz74QLNmzdKiRYu0bt06SVLnzp11yCGH6MILL1ReXl7A85kxY4amTp2qP/74Q+np6erXr5+uvPJK9enTp8G61atX67///a8+//xzFRYWau3atWrdurX69euniy66SHvvvXf0dgJggWGapml3CMAO33zzjc477zwdfPDBevbZZ5tc98orr+iWW27RiBEjNGrUKA0dOlRZWVk66KCDtPPOO2vLli365JNPVFpaqiOPPFKPPfaYDMOo337Dhg0aMWKEioqKtO+++2qfffbRmjVrNGvWLKWlpWnKlCkNSmDFihV66623Amb5+uuv9eOPP2rkyJG69dZbo7YvAABNc2pfSNLzzz+vO+64Q61atdLRRx+t3NxcFRUV6ZNPPpFhGHryySd18MEHx2zfAABqObkrJk2apGeffVYdOnTQoEGDlJaWps8++0wrVqzQBRdcoBtuuCFm+wUA0FA4fTF+/HhdeumlKioqUp8+fdSxY0eZpqmFCxdq7ty5atmypV566aVGA+zHHntMDzzwgLp06aJjjjlG5eXleu+991RTU6PnnntO++23X/3ae++9V0899ZR22mknDRgwQLm5uVq6dKk++ugjmaap++67T0OHDo3ZfgGaZAIpyu/3m4MGDTJ33313c+XKlU2uO+2008yePXua8+bNM0tKSswXXnjBLC8vb7CmvLzcHD58uNmzZ0/z/fffb/Cz8ePHmz179jQnTpzY4PQff/zR7N27tzl06FDT5/OFlPn44483e/bsac6fPz/EawkAiJRT+6K6utrs16+f2a9fP3PVqlUNtvnggw/Mnj17muecc064VxsAYIFTu2LevHlmz549zaOPPtrcsGFDg8s49dRTzZ49e5o//vhjBNccAGBFOH1hmqZZVVUVcN1rr71m9uzZ07ziiisanP7nn3+ae+yxh3nMMceYmzdvrj99wYIFZt++fc3jjjuuQV/MmjXLnDt3bqPz/+6778w+ffqY/fv3N7du3WrpugLRwDEvkLIMw9Dw4cPl9/v15ptvBlyzePFizZs3T7169dKee+6pvLw8nXXWWcrKymqwLisrS+eff74k6bvvvmvws9mzZ8vlcumKK65ocPq+++6rI488Un/88Ye+/fbboHnnzZun33//Xb1792708T4AQOw4tS82btyosrIy7bbbbsrPz2+wzcCBA2UYhjZs2BD29QYAhM6pXTF79mxJ0rnnnqs2bdo0uIxLL71UUu1f9wIA4iOcvpCkjIyMgGuPO+44SdKyZcsanP7mm2/K6/Xq73//u1q2bFl/eu/evXX88cdryZIl+uGHH+pPP+aYYzRgwIBG57///vvrgAMO0KZNm7Ro0SJrVxaIAoYXSGnDhw+Xy+XSm2++KTPAN6jVFclpp50W9LzS0moPIbPj99KuXbtWbdu2VXZ2dqNtunbtKqn2+8qDef311yVJf/vb34KuBQBElxP7on379mrbtq0WL16s4uLiBus/++wzmaapAw88MGgeAEB0OLEr1q5d2+BnwdYDAGIvmn3x6aefSlKjr4yqG2QfcsghjbY59NBDG6wJpq6T6v4LxBO3OqS0/Px8HXLIIfriiy80Z84cHXTQQfU/83q9mjFjhjwej0488cSg5/XGG29I2lYCddq2bat169apvLy80YuMFStWSJKKioqaPe+Kigq99957atGihU444YRQrhoAIIqc2BeGYejmm2/W9ddfrxNPPLHBMS8+/fRTHXvssbr66qvDvMYAAKuc2BVt27Zt8LNA60tKSlRZWanMzMwQriUAIFKR9MX777+vJUuWqLKyUn/88Ye+/PJLde3aVVdeeWWDdUVFRcrKylKHDh0anUf37t0lSUuXLg2addWqVfr666/VoUMH9ezZ0+pVBSLGJy+Q8uom2dOmTWtw+qeffqq1a9dq8ODBDT5iHcirr76qzz//XAceeKAGDhzY4GeHHXaY/H6/HnnkkQan//zzz/UT8i1btjR7/jNnzlR5ebmOOeYYtWrVKoRrBQCINif2xdChQ/X000/L4/HojTfe0FNPPaUPP/xQO++8s04++eSAf5kLAIgdp3XF4YcfLkmaOnWqNm/eXH96ZWWlnnzyyfp/B3s9AgCIrnD7YubMmXrkkUf0zDPP6LPPPlPv3r317LPPqlu3bg3WlZWVNfi6qO3l5ORICv7YX1NTo+uvv17V1dW67rrrGn0aEIgHPnmBlDd48GDl5ubqo48+0pYtW+of3OsKJNjH9D755BPdfvvt6tKli+65555GP7/qqqv0xRdf6D//+Y/+97//aZ999lFpaalmzZqlXXbZRYsWLZJhGM1eRqhZAACx48S+eP311zV+/HidddZZOvvss9W+fXsVFhbq/vvv16WXXqqbb75ZZ511VpT2AAAgGKd1Rf/+/XXSSSdp+vTpGjp0qAYNGqT09HR99tln8vl8atmypbZs2SKXi79rBIB4CrcvHnroIUnS5s2btWDBAj3wwAMaPny4Hn744Qaf4IiU3+/X2LFj9d133+n000/XySefHLXzBqzgGQpSXnp6uk466SRVVVXpnXfekSStWbNGX3zxhTp37qyDDz64yW0/++wzXXnllWrXrp2mTJmijh07NlrTqVMnvfHGGzrttNO0YsUKPf/88/r555915ZVX1h8kr127dk1eRmFhoX744Qd1795dBxxwQITXFgAQLqf1xZIlS3TrrbfqiCOO0I033qhu3bopMzNTffr00SOPPKK8vDzdd9992rp1a5T3BACgKU7rCkmaNGmSxo0bp9zcXL311luaMWOG9txzT7344ovy+XxKS0tT69ato7gXAADBRNIXktSqVSsdeOCBevrpp9WiRQvdcMMNqqmpqf95Tk5Ok5+sKCsrk6QmP5nh9/t100036d1339WJJ56o8ePHh3MVgahgeAGo8cf1pk+fLq/XW38QpUA+/fRTXX755Wrbtq2mTp3a6CN628vLy9OECRP0xRdfaP78+froo490ySWXaMmSJZKkvn37Nrktn7oAAOdwUl98/fXX8nq9AQfbmZmZ2muvvVReXh7Sd9kCAKLHSV0hSS6XS6NGjdKMGTP0yy+/6LvvvtPkyZPl9/tVUVGhXr16KT09PRpXHQBgQTh9saOcnBztvffeWr16tZYtW1Z/eo8ePVRRUaE1a9Y02qbu9UHdsS+25/f7deONN+qtt97S8ccfr0mTJvHpPNiKWx8gadddd9U+++yjX3/9Vb/99pvefPNNGYah4cOHB1z/6aef6oorrlDr1q01derUgA/4wfh8Pr333ntKS0vTMcccE3CN1+vV9OnTlZaWplNOOcXyZQAAostJfVH3l1Xr168PuF3d6R6Px/JlAgDC56SuaE7dX/oOHTrU8uUBACJntS+aUlpaKklKS9t2dID+/ftLkr766qtG67/88ktJ0oABAxqcXje4ePvttzV06FDdfffdHOcCtmN4AfylbuI9fvx4LVmyRAcffLC6dOnSaN1nn33W4MVFjx49mj3fmpoaVVVVNTjN7/frrrvu0p9//qmzzz5beXl5AbetO1DT4Ycfrg4dOoR3xQAAUeWUvujXr58k6bXXXtPq1asbXfaPP/6o/Pz8sN4EAwBExildIW37epDtff/993ryySfVpUsXjRgxwuK1AwBESyh9UVZWpsLCwoDbT5s2TfPmzVOPHj0aPO8fPny40tLS9NhjjzX4+qiFCxfq3Xff1S677KL99tuv/vS6r4p6++23deyxx+qee+5hcAFHMEzTNO0OAThBWVmZDjvsMFVUVEiSJk+e3OivkJYsWaKTTz5Z1dXVGjZsmHbeeedG59OlS5cGU/KSkhINGzZMhxxyiLp27aqamhp9+eWXKiws1BFHHKGHH364yb+KvfTSS/XJJ5/oscce06BBg6J4bQEA4XJSX1x77bV69913lZ2draOPPlrt27fXkiVL9Omnn8rlcumhhx7SUUcdFYO9AABojpO64oILLlBVVZV69eqlnJwc/f777/r888/VunVrPfvss+rdu3cM9gAAIBSh9MWKFSt01FFHqW/fviooKFBeXp42bdqk+fPn69dff1VOTo6efvpp7bvvvg22e+yxx/TAAw+oS5cuOuaYY1ReXq733ntPNTU1eu655xoMLx5++GE98sgjysrK0qhRoxp8iqPOUUcdRWcg7hrfEoEUlZOTo2OPPVZvvvmm2rRpE/DNnrVr16q6ulqS9N577wU8nwEDBjR4gZGTk6PBgwfrxx9/1Keffqq0tDT17NlTd9xxh0499dQmvztw9erV+vzzz9WxY0cNHDgwCtcQABANTuqLe+65R/vvv7+mT5+uDz/8UFVVVfWZLrroIu2zzz7RudIAAEuc1BWDBw/WW2+9pXfeeUdVVVXKz8/X2WefrdGjR6t9+/ZRusYAgHCE0he5ubkaM2aMvv32W3399dfauHGj0tPT1aVLF5133nk6//zz1alTp0bb/f3vf1eXLl00ZcoUvfzyy0pPT9f++++vq666Sn369GmwduXKlZKkiooKPf744wGzdunSheEF4o5PXgAAAAAAAAAAAEfhmBcAAAAAAAAAAMBRGF4AAAAAAAAAAABHYXgBAAAAAAAAAAAcheEFAAAAAAAAAABwFIYXAAAAAAAAAADAURheAAAAAAAAAAAAR2F4AQAAAAAAAAAAHIXhBQAAAAAAAAAAcBSGFwAAAAAAAAAAwFEYXgAAAAAAAAAAAEdheAEAAAAAAAAAABwlze4AiC2fz6eamhq7YwC2SE9Pl9vttjsGkBDoC6Qy+gIIDV2BVEZXAKGjL5DK6IvoYniRpEzTVElJiTZu3Gh3FMBWbdq0UadOnWQYht1RAEeiL4Ba9AXQNLoCqEVXAM2jL4Ba9EX0MLxIUnVl0bFjR2VlZXFnQcoxTVMVFRUqLS2VJOXn59ucCHAm+gKpjr4AgqMrkOroCiA09AVSHX0RfQwvkpDP56svi3bt2tkdB7BNZmamJKm0tFQdO3bkY3vADugLoBZ9ATSNrgBq0RVA8+gLoBZ9EV0csDsJ1X2vYFZWls1JAPvV3Q/4vk2gMfoC2Ia+AAKjK4Bt6AqgafQFsA19ET0ML5IYH88DuB8AoeB+AnA/AILhPgJwPwBCwf0E4H4QTQwvAAAAAAAAAACAozC8gOM9/PDD6tWrV/3/HXDAARo5cqQ+++yzmFzeOeeco9GjR8fkvJPZjr+nuv87/vjjQ9p+0KBBuu2222KcEkCyoisSB30BwE70RWKgKwDYia5IHPRF8uOA3QiqusanL39epTnzi7Wlolotszw6sG++Dt27szzp8TnoTIsWLTRlyhRJtQe8efzxx3XppZfqxRdfVL9+/eKSAcFt/3va/jQAyY+ugBX0BZC66AuEiq4AUhddASvoi+TG8ALNmju/WJNf+UnllTUyDMk0JcOQvvmlWE++/Yv+MbKfBvTpFPMcLpdL++yzT/2/9957bw0cOFBvv/02pbEd0/TLu2mtzOpKGZ5MpbVuL8OI3wesdvw9AUgNdEXioS8A2IG+SCx0BQA70BWJh75ALDG8QJPmzi/WhOe+lczaf5s7/LeiskZ3PDtX484boAP65sc1W15ennJzc7Vq1ar603766SdNnjxZ8+bNk9vt1hFHHKGbbrpJ7dq1q19z77336rPPPtOKFSuUk5Oj/v37a+zYserYsWNc88dC9doVKl80VzVrV8rvrZYrzaP09l2U3esAedp3tS1XRUWF7r33Xn311VcqKSlRu3btdOihh+qf//ynWrZs2eR2GzZs0EUXXSTTNPX0008rNzdXS5Ys0b333qtvv/1WPp9PAwYM0L/+9S/ttNNOcbxGALZHVyQe+gKAHeiLxEJXALADXZF46AvEGse8QEDVNT5NfuUnyazvjEbMv/7fA6/8pOoaXxzTSeXl5dq0aZO6dq19IPzpp590zjnnqGXLlpo8ebJuv/12/fLLLxozZkyD7datW6fRo0friSee0Lhx47Ry5Uqdc8458nq9cc0fbdVrV2jTt++puqRQrqyWSm/XWa6slqouKaw9fe2KuGXxer0N/q+qqko+n0/XXHONnnrqKV111VX67rvvGv1utrdmzRqNGjVKHo9HU6ZMUW5urpYvX64RI0Zo06ZNmjRpku69916tX79e5513nqqrq+N2/QBsQ1ckHvqCvgDsQF8kFrqCrgDsQFckHvqCvogHPnmBgL78eZXKK2uCrjMllVXW6Kt5q3Tkft1imqnugb20tFT33HOPsrOzNWrUKEnSfffdp759++qRRx6RYRiSpJ49e+r444/XZ599poEDB0qSJk6cWH9+Pp9P++67rw4//HDNmTNHhx56aEzzx4pp+lW+aK78lZuV1r5b/fU3MrJktO8m79rlKl/0rdLbdY75x/YqKirUp0+fBqfdfffdGj9+fP2/vV6vunbtqjPPPFN//vmndt555wbrV61apfPOO09dunTRv//9b2VlZUmSHnnkEbVu3VrPPvusMjIyJEn9+vXT4MGD9frrr+uss86K6XUD0BhdkVjoC/oCsAt9kTjoCroCsAtdkVjoC/oiXhheIKA584vrv1swmLrvHoxlaez4QOR2u/Xoo4+qoKBAlZWV+vHHH3X99dfL59s2ee/Ro4fy8/P1yy+/1JfGZ599pscee0yLFy9WWVlZ/dqioqKELQ3vprWqWbtS7lbt68uijmEYcrdqr5q1K+TdtFbpbWL7scQWLVrohRdeaHBat27d9Pbbb+u5557T0qVLVVFRUf+zoqKiBoWxbNkynXXWWdp999314IMPyuPx1P/sq6++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joqvfe1r7S47c+bMmDp1akyePDmOOeaYeO211/Ke56abborDDz88jjjiiDjiiCPi3nvvbXfZk08+OSZNmtSa/YYbbshLhmy384477oiDDjooDjzwwPiv//qvaGhoyMv617VmzZo488wzY/LkyXHkkUfGqaeeGrNmzdpouTlz5sSECRNa74ujjjoqZs+enfc8ERGTJk2KyZMnt67n97//fZvLFfr+eeedd9bb3smTJ8d2220XS5cuXW+5Qt43F110UUyaNCnGjx8f06dPb/1+LsdKPu+ntvJkuw9F9Ox+RGlYvHhx7LPPPnHmmWcWO8p6cumKntQTPdlVuZwLiu2uu+6K8ePHxyOPPFLsKBupr6+PCy64IA466KA44ogj4utf/3qxI63nj3/8Yxx99NFx1FFHxeGHHx6/+c1viponHz1J+qW1K2655ZY44ogjWo+Hm266qdiRWqW1x1o89thjMWXKlJg4cWJcfPHFxY4TEek+b7R3rkuDUuj/T3/6063H6oknnhgvv/xysSPRA/J9THflZ46euOyll15q9xhcvHhxfOYzn4mDDjooDj/88PjrX//aejs9cdkxxxzT5rFX7Pus5bINnxMU+/7ad9992/xdWLHvr5dffrnN5yfFzvX3v/+93d/ZFfuxXPeyHpeQs6uuuiq56KKLslr25JNPTu66664kSZLkf/7nf5IpU6bkPc9f/vKXZPny5UmSJMm8efOSPfbYI5k1a1aby5500knJww8/nPcM2Wzn7Nmzk3333TdZsGBB0tzcnJx22mnJzTffnPcsq1evTh577LGkubk5SZIk+eUvf5mcdNJJGy335ptvJrvuumve19+Wj3zkI8nLL7/c4TI9df+s67rrrktOO+20jb5fyPvmmWeeSebPn7/RfZLtsZLv+6mtPNnuQ0nSs/sRpeHMM89MzjnnnOSMM84odpT15NIVPaknerKrcjkXFNObb76ZHH/88clxxx1XkI7vrosvvji54IILWu/HBQsWFDnRu5qbm5Pdd989mT59epIka+/LiRMnJitWrChapu72JKUhrV3R0hNJkiQrVqxI9t9//+Sll14qYqJ3pbXHWsyYMSOZPn16cvnll2f9XLHQ0nzeaO9clwal0P/Lli1r/fdDDz2UHHHEEUVMQ0/J9zHdlZ85euKyj33sY+0eg9OmTUuuuuqqJEmS5B//+EfywQ9+MKmvr++xy/bdd9/Wy9Y99op9n02ZMqXN5wTFvr+23Xbb5Pnnn082VOz7a++9927z+Umxc214TK/7O7tiP5brXtbTDC+6INvhxaJFi5IPfOADSUNDQ5Ika58g77PPPsnMmTMLmu+www5LnnrqqTYvK8TwItvt/NnPfpZ861vfav36scceS6ZOnZrXLG15/vnnk4985CMbfT9tw4ti3D8HH3xwm/tDT9w3694nuRwrhbqfOnqM2tuHksTwgvXdfvvtyXe+853krrvuSt0vpDbUUVf0lGL1ZFd1dC4olqampuSUU05JXnjhhYL9gUJ3rFq1KvnABz5Q1GFAR5qbm5M99tgjeeaZZ5IkSZLp06cn++23X7JmzZoiJ+t6T5J+pdIVb7/9drLvvvumZnixoTT0WFty+UO3QiqV80YahxcbSmP/r+uuu+5KjjzyyGLHoMAKeUxn+zNHT1/WYt1jcOedd17vD2GOOeaY5IknnijKZS3HXhrus7333js5/vjjN3pOUOz7a/vtt09uvfXWZF3Fvr9WrlyZjB8/fqOfb4qdq619f93f2RX7sVz3sp5WVbzXfJS2Bx54IJ5++ukYPHhwnHnmmbHXXntttMz8+fNj+PDhUVW19m7OZDIxatSomDdvXmy11VYFyfWXv/wlli1bFjvssEO7y1x66aVx5ZVXxnvf+9742te+FmPHju3WOrPdzvnz58eYMWNavx4zZkzMnz+/W+vOxk033RSTJk1q87K6uro45phjorm5OQ444IA444wzorKysiA5vvnNb0ZExA477BBf//rXY8iQIetd3tP3z7PPPhvLly+PD3/4w21e3pP3TS7HSjH2o472oYieva9IrzfffDN+/etfxy233NLuW8OlRTZd0ROK0ZPd0dm5oBiuv/762GWXXWLixInFjtKm2bNnx+DBg+Oaa66Jv/zlL9G3b9/44he/GHvvvXexo0XE2n3uiiuuiLPOOiv69+8fy5Ytix/96EdRU1NT7GjrKbVjhfaVQlc88MAD8cMf/jBmzZoVX/3qV2O77bYrdqSNpKXH0sx5I3/S2P8Ra59fPv300xER8dOf/rTIaSi0njqmO1rPoEGDevSylu1qOQbfeeedaGhoiOHDh7fmHTNmTMybN69HL7vyyivjnHPOiYi1x14a7rPq6urYcsst13tOkIb7q7KyMn7yk5/ELbfc0vq7sGLfX2+++WZUVVXFz372s5g1a1br85Oe3r872/fX/Z1dGh7LlsuKwfCiDccff3zMnDmzzcvuueeemDp1apx++ulRXV0df//73+Oss86KO++8c71fqPZknlGjRkVExKuvvhrnnHNOXHHFFdG/f/82l//+978fo0aNiiRJ4pZbbonTTjsttU+c8uGaa66J2bNnt/nZHptvvnn86U9/iqFDh8bSpUvjK1/5SvziF7+Iz33uc3nPcfPNN8fo0aOjoaEhfvCDH8TZZ58dP/vZz/K+nlzceeedcdRRR7WeKNfVk/dN2nW0D0W4r8pJZ+fi//zP/4zzzjsv+vbt27PB/i2fXcHGOjsXFMM///nPeOihh+Lmm28udpR2NTU1xdy5c+N973tffP3rX4+XX345Tj311Pjd734Xw4YNK3a8aGxsjKuvvjp+9KMfxe677x7PP/98nHnmmXHfffdt9EcGkI3e0BUHH3xwHHzwwTFnzpw466yz4sMf/nCMGzcuFdkiitdj2eajd0lj/7f4/ve/HxERv/nNb+LSSy8t+vNLKIR1j8HVq1cXO05ERHz84x+PY489tvXY+/KXv1zUPP/85z9j2bJlccQRRxQ1R1v23HPPOOigg+Koo45q/V1Yse+vpqamaGhoiDFjxsQVV1zR+vwkbUPgjn5nV27cA2247bbbsl521113je222y5efPHFjYYXo0aNioULF0ZjY2NUVVVFkiQxf/78GD16dN7zvP7663H66afHd77zndhtt93aXa7lh+pMJhMnnXRSfO9734t33nknNttss5wybXib2WznqFGj1vsg47lz5xb0h/yf//zn8dBDD8UNN9wQ/fr12+jympqaGDp0aEREDB48OI455pi4//77C/JL55b7orq6Ok455ZSYPHnyRsv05P2zatWq+J//+Z+4884727y8J++biNyOlZ68nzrbhyJ6/r6ieDo6F69YsSL++c9/xle+8pWIWHuMrV69Ok455ZS48cYbi56vRbZd0VPy1ZOFls25oBj+9re/xdy5c1s7ZeHChfH666/HggUL4sQTTyxyurVGjRoVFRUVrU+mtttuu9hiiy3in//8ZyqGF9OnT48FCxbE7rvvHhERO+64Y4wYMSKmT58e++67b5HTvatUjhV6R1e02GKLLWLHHXeMxx57rEeGF2nvsVzuuzRw3ui+tPb/ho4++uj49re/3e3n9aRbTx3THa1n4MCBPXrZhsdgv379oqqqKhYuXNj6F+Fz586N0aNHx2abbdajl0W8e+yNHDmyqPfZ3/72t1i9enWce+65rXlff/31+OIXv1j0+2vJkiUxevTo9X4XVux9rOX3R1OmTImId5+fzJ07NzX7/oa/s+vp/buzfb+nVRRlrSXurbfeav33zJkzY/r06bHNNttstNzQoUNj++23j/vuuy8iIh588MEYMWJE3l+m+8Ybb8TnP//5uOCCCzp8ot3Y2BiLFi1q/frBBx+MYcOGdfsHnGy3c/LkyfGHP/whFi5cGEmSxK233hqHHXZYt9bdnuuvvz5+97vfxfXXXx+bbLJJm8ssXrw4GhoaIiKivr4+HnrooZgwYULes9TW1sby5ctbv/7d737X5svve/L++f3vfx/bbrttvPe9723z8p66b1rkcqz01P2UzT4U0fP3Fek0aNCgePrpp+MPf/hD/OEPf4izzz479t133x77ZVQ2su2KntRTPdkd2Z4LiuHEE0+Mxx9/vHW/23nnnePCCy9MzeAiImLIkCGx9957x+OPPx4Ra1+mPWfOnHb7p6eNGjUqFixYEG+88UZERMyaNSvefPPNeM973lPkZOsrhWOFzpVCV7z++uut/16yZEk8/fTTMX78+CImelcaeyzNnDe6J839v3z58nj77bdbv37kkUdi8ODBMXjw4OKFouB66pjuaD09edkf/vCHNo/Bgw8+OH79619HRMTzzz8fb7/9dusfoRT6sieffDLmzZvXelnLsVfs+2zIkCGx3XbbxZ/+9KeNnhMU8/565plnYv78+a2XtfwurNj31zPPPBMDBgyIN998MyLefX6y6667pmLf32qrrdr8nV0xH8sNL+tpmSRJkqKsuYSdffbZ8dJLL0VlZWVUVlbG5z//+Tj44IMjIuLRRx+NP/zhD3HxxRdHRMSMGTPinHPOiaVLl8aAAQPikksuyfsTgFNPPTVefPHF9SZgX//61+ODH/xgvPDCC3HVVVfFz372s6itrY2TTjopGhoaIpPJxGabbRbnnHNObLvttt3O0N52nnvuuTFp0qQ44IADIiLi9ttvb30p1h577BHnn39+VFdXd3v963rrrbdi//33j7Fjx8aAAQMiYu1fx99xxx1x5ZVXxuabbx4nnHBCPPTQQ3HVVVdFRUVFNDU1xV577RVnn3123t/n+s0334wvfvGL0dTUFBFr/4rt3HPPbf1vT98/ERFTp06Nj3/843HMMce0fq+n7pvzzjsvHnvssVi0aFEMHjw4BgwYEA8//HCHx0oh76e28vzyl79sdx+K6Ln7itJ19913xyOPPBI/+clPih2lVUddUUw90ZNd1VGfpNHJJ58cp5xyShx44IHFjrKeN998M/7zP/8zli5dGplMJr7whS+0+QrEYrn//vvj2muvjUwmE0mSxOc///mivuy+Kz1JaUpjV5x33nnxt7/9LaqrqyNJkjj++OPjE5/4RLFjRUR6e6zFk08+GWeffXasXLkykiSJQYMGxbe//e3Wn1+LIc3njfbOdWmQ9v6fO3dufPnLX441a9ZEJpOJIUOGxNlnn+0PqMpAvo/prvzM0ROXfe1rX4tPf/rTbR6DixYtim9+85sxZ86cqK6ujm9961utn0Fb6MsiIioqKqK6unqjY6/Y99m6l637nKDY91eSJK1vlbnu78KKfX99+ctfjuuuu26j5yfFztVyWVu/syvmY7nhZT3N8AIAAAAAAEgVbxsFAAAAAACkiuEFAAAAAACQKoYXAAAAAABAqhheAAAAAAAAqWJ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlSVewAUCxf+9rX4v7774/LLrssDj/88HaXW7lyZey7775RXV0djz/+eDz00EPx4IMPxquvvhqLFy+OiIjRo0fHvvvuG5/5zGdixIgRbd7OfffdFzfddFO8/vrrUV1dHbvsskt86Utfiu2333695dasWROXX355vPjiizFr1qxYtmxZbLLJJjF27Nj4+Mc/HkceeWRUV1fn744AoENp7Yu2/PSnP43LLrssIiJuu+222HnnnXPfYAByluaumDRpUsydO7fN29ljjz3il7/8ZRe2GICuSHNftHj44YfjV7/6Vbz88stRW1sbw4cPj5133jm+8Y1vxKhRo7p3B0COvPKCsnXsscdGRMRdd93V4XL3339/rF69Og477LDo27dv/P73v4833ngjdtppp5g6dWocf/zxMWzYsLjpppvi8MMPj9dee22j27j66qvjG9/4RixZsiSmTp0aBx98cPz1r3+NqVOnxt///vf1ll21alXceuutkclk4sMf/nCceuqpceCBB8aCBQviP//zP+P000+P5ubm/N0RAHQorX2xoX/+85/xwx/+MPr379/1jQWgS9LeFYMGDYqzzjpro/8dffTR3d94ALKW5r5IkiTOO++8OOuss2LOnDlx6KGHximnnBK77bZbPPfcc+0OwqGgEihTzc3NyaRJk5Jtt902mTt3brvLHXvssck222yTPP/880mSJMnq1avbXO72229Pttlmm+SLX/ziet//17/+lWy33XbJQQcdlCxfvrz1+y+//HIyceLE5JBDDkmamppav9/U1JSsWbNmo9tvaGhITjrppGSbbbZJ/vd//zeXTQWgG9LaF+uqr69Pjj766OTjH/948vWvfz3ZZpttkueeey7HLQWgq9LcFR/5yEeSj3zkI13dNADyKM19ccMNNyTbbLNN8t///d9JY2PjRutqaGjIejshX7zygrKVyWRiypQp0dzcHHfffXeby7z22mvx/PPPx/jx42OHHXaIiIg+ffq0uewhhxwSERGzZ89e7/t33313NDY2xhlnnBGDBg1q/f6ECRPi8MMPjzfeeGO9iXdFRUXU1NRsdPtVVVXx0Y9+NCIiZs2alcOWAtAdae2LdV1zzTXx2muvxXe+852orKzMeRsB6J5S6AoAii+tfbF69er48Y9/HGPHjo1zzz23zecUVVU+fYCeZ3hBWZsyZUpUVFTE3XffHUmSbHR5S5G0vKyvI4899lhERLz//e9f7/vPPPNMRETsu+++G11nv/32W2+ZjjQ3N8ef//zniIjYZpttOl0egPxJc1+89NJLcc0118RZZ50V73vf+zpdPwCFkeauqK+vj7vvvjuuueaauPnmm+Mf//hHpxkAKIw09sXjjz8ey5YtiwMPPDCam5vjoYceip/+9Kdx6623+gNaisrIjLI2atSo2HfffePPf/5zPPXUU7H33nu3XtbY2Bj33Xdf1NTUxJFHHrnRdVveb7Curi5ef/31ePzxx2OLLbaIL33pS+stN3PmzOjfv38MHz58o9vYaqutIqLtV1LU19fHtddeG0mSxNKlS+PJJ5+MGTNmxJQpU9bLCUDhpbUv6uvr4+yzz45tt902PvvZz+ZjUwHoorR2RUTEwoUL45xzzlnvezvssENcfvnlseWWW3ZpewHomjT2xUsvvRQRa98N5IgjjoiZM2e2XlZRURGf+tSn4uyzz+7WdkNXGF5Q9o499tj485//HHfeeed6hfHYY4/FokWL4pBDDonBgwdvdL0HHnggHnzwwdavJ06cGFdccUWMHTt2veVWrlwZQ4YMaXPdAwcOjIiIFStWbHRZQ0ND/OhHP2r9OpPJxKc//en42te+ltP2AZAfaeyLK6+8MmbOnBl33323t4sCSIE0dsWUKVNi1113jW222Sb69+8fM2fOjOuvvz7uvffe+NSnPhX33Xdf63UB6Blp64vFixdHRMQNN9wQ2223Xdxxxx3x3ve+N6ZPnx7f+ta34he/+EWMHTs2TjzxxC5vM3SFt42i7B1wwAExZMiQeOSRR9Y7cd95550R0f7L9K666qp49dVX469//WvceOONUV1dHVOmTIknn3wyL7kGDBgQr776akyfPj3++Mc/xnnnnRd33nlnnHzyybFy5cq8rAOA7KWtL5577rn4xS9+EWeccYa3EwRIibR1RUTEWWedFXvvvXcMHTo0+vXrFxMmTIjvf//7cdRRR8XcuXPjjjvu6PY6AMhN2vqi5e2rqqur48c//nHsuOOOMWDAgNhtt93iyiuvjIqKirj++uu7tQ7oCsMLyl51dXUcddRRsXr16vjtb38bEWtfVv3nP/85Ro8eHfvss0+H199kk01ir732iuuuuy769u0bZ599djQ0NLRePnDgwDZfWRERrUOIdT88aUMVFRUxcuTIOPHEE+OCCy6IZ599Nq6++upcNxOAbkpTXzQ2Nsa0adNi/Pjx8fnPfz4fmwdAHqSpKzpz/PHHR0TEs88+m9XyAORP2vqi5dUYEydOjBEjRqy3/DbbbBNjx46N2bNnx/Lly3PfWOgGwwuIdyfaLRPue++9NxobG1s/RCkbAwcOjJ122inefvvtmD17duv3t95666itrY2FCxdudJ2W9xdseb/BzuTyAd8A5F9a+qK2tjZmzpwZ06dPj4kTJ8b48eNb//eb3/wmItb+Umr8+PHxyCOPdH2DAchZWrqiM5tttllErO0UAHpemvpi3LhxEdH+ALzl+6tXr84qF+SL4QVExPve977Yeeed46WXXopXXnkl7r777shkMjFlypScbmfBggUREVFV9e7Hyey+++4REfHEE09stPzjjz8eERF77LFHl28fgJ6Tlr6oqamJY489ts3/bb311hERMWnSpDj22GNjzJgxOW8nAF2Xlq7ozPPPPx8RoScAiiRNfbHnnntGRMSMGTM2Wr6hoSFmz54d/fv3b/dz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GF/4whc2ut9feOGFWLp0aZx77rnrlUXE2vcdvPHGG+PGG2/caL3V1dX53xigU7qitOgLfQHFoi9Kh67QFVAsuqK06At90VMML2jTXhNHxZMvzM9q2SSJ2HuHUQXNs+6JaMcdd4z3vOc9cdxxx8WPf/zjOPvssyOTycRpp50WBx544EbX3WyzzSIi4pFHHomBAwfGD37wg6ioWPtxL3Pnzi1o7p5QtemwqB42JurfmhGZYWPXe7lekiTRtHxR1Ix8b1RtOqwo+R544IGYMGFCXHDBBa3fe+aZZ9pc9rDDDovKysr46le/Gtdee23svfferZdtuummsf/++8eJJ5640fUGDBiQ/+BAp3RFadEX+gKKRV+UDl2hK6BYdEVp0Rf6oqcYXtCm/XYaHT+954Wo7eTDkjIRMaBfdey74+ieihYRETvssEMcdthhcffdd8dZZ50VO++8c8yYMWOjSeu6Vq9eHdXV1eudUH/729/2RNyCymQqYsD4PaNx2aJoXPTm2vcbrO4TScOaaFq+KCr6bxIDxu8RmUxFUfK13O/r6uh+P/fcc2PNmjVx5plnxnXXXRe77rprRETsvffe8dprr8V2220XlZWVBc0MZEdXlBZ9ARSLvigdugIoFl1RWvQFPaU4exCpV1NdGV89YZeIzNpiaEvm3//3lRN2iZrqnj+AzzzzzGhqaoobb7wxvvnNb8Zjjz0W//Ef/xEPP/xwPP3003HvvffG2WefHU8//XREROy7776xcOHCuPDCC+PJJ5+Mn/zkJ/Gb3/ymx3MXQs2wLWLTPQ6LmpHjorl2RTQsmRfNtSuiZuR7Y9PdD4uaYVsULds+++wTzz//fPz4xz+Ov/zlL3HJJZfEk08+2eF1zj///DjooIPi85//fDz//PMREfGlL30pZs2aFZ/5zGfi97//fTzzzDPx+9//Pv77v/877r///p7YFGADuqL06At9AcWgL0qLrtAVUAy6ovToC33RE7zygnbtsf3IOPdTe8QPfv1crKxraH3vwZb/DuhXHV85YZfYY/uRRck3bty4OPTQQ+PWW2+N0047LX71q1/FD3/4wzjnnHOioaEhRo4cGXvttVdstdVWERGx//77x9e//vW4+eab4+67745ddtklrr322pg8eXJR8udbzbAtonro6GhctiiS+rrI1PSLqk2HFW3K3WLq1KkxZ86cuPnm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AJAqhhcAAAAAAECqGF4AAAAAAACpYngBAAAAAACkSlWxA2xo5syZMW3atHjnnXdi4MCB8d3vfjfe//73r7dMc3NzfO9734s///nPUVlZGYMHD46LLroottpqqyKlBqCn6QsAOqMrAMiGvgBIp9S98uK8886L4447Lh588MH43Oc+F9OmTdtomT/84Q/x7LPPxr333hu//e1vY++9947LL7+8CGkBKBZ9AUBndAUA2dAXAOmUquHF4sWL48UXX4wjjzwyIiImT54cb731VsyaNWujZevr62PNmjWRJEmsXLkyRo4c2dNxASgSfQFAZ3QFANnQFwDplaq3jZo/f34MHz48qqrWxspkMjFq1KiYN2/eei/DmzRpUjz99NOx3377xYABA2LEiBHxy1/+slvrTpIkamtru3Ub68rnbRVLXV3dev/trcphO21j79CybUmSRCaTKXKa4ipWX+S7KyKK1xdpPWbkyk1ac0WkN1s55Sr3vtAVhZfW46kjMvecUsxdjpnLvSsi9EW+lcJxJGN+yJgfpZSxGFI1vMjWiy++GK+99lr86U9/ioEDB8all14a3/72t+PSSy/t8m3W19fH9OnT85Yxn7dVbDNnzix2hB5RDttpG3uHhoaG6NOnT7FjlIR890W+uyKi+H2R1mNGrtykNVdEerOVQ676+np9kQVd0X1pPZ46InPPKcXc5ZRZV2RPX+SmFI4jGfNDxvwohYzFkKrhxahRo2LhwoXR2NgYVVVVkSRJzJ8/P0aPHr3ecvfcc0/stddesckmm0RExNFHHx2f/vSnu7XumpqamDBhQjuXzsn59tq/rdJRV1cXM2fOjK233jr69etX7DgFUw7baRt7h5ZtrK6uLnaUoitWX3TcFRGl1BdpPWbkyk1ac0WkN1s55aqpqcnL7ZQqXVF4aT2eOiJzzynF3OWYudy7IkJf5FspHEcy5oeM+VEqGYslVcOLoUOHxvbbbx/33XdfTJkyJR588MEYMWLEei/Ti4gYO3Zs/PGPf4xPf/rTUVNTE//7v/8b22yzTbfWnclkon///t26jXXl87aKrV+/fr1qe9pTDttpG3uHcn9Zd0Tx+iLfXRFR/L5I6zEjV27SmisivdnKIVe594Wu6DlpPZ46InPPKcXc5ZS53LsiQl8USikcRzLmh4z5UQoZiyFVw4uIiPPPPz/OOeecuPbaa2PAgAFxySWXRETEueeeG5MmTYoDDjggPvGJT8Qbb7wRRx11VFRVVcXw4cPj/PPPL3JyAHqSvgCgM7oCgGzoC4B0St3wYty4cXHbbbdt9P2LL7649d81NTVx0UUX9WQsAFJGXwDQGV0BQDb0BUA6VRQ7AAAAAAAAwLoMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVUje8mDlzZkydOjUmT54cxxxzTLz22mttLvfqq6/GySefHIccckgccsgh8dBDD/VwUgCKSV8A0BldAUA29AVAOlUVO8CGzjvvvDjuuONiypQp8cADD8S0adPirrvuWm+Zurq6OPPMM+N73/te7LbbbtHU1BTLli0rUmIAikFfANAZXQFANvQFQDql6pUXixcvjhdffDGOPPLIiIiYPHlyvPXWWzFr1qz1lrv//vtj5513jt122y0iIiorK2PIkCE9nheA4tAXAHRGVwCQDX0BkF6peuXF/PnzY/jw4VFVtTZWJpOJUaNGxbx582KrrbZqXe7111+PmpqaOO200+Ktt96K8ePHx7Rp07pVGkmSRG1tbbe3oUU+b6tY6urq1vtvb1UO22kbe4eWbUuSJDKZTJHTFFex+iLfXRFRvL5I6zEjV27SmisivdnKKVe594WuKLy0Hk8dkbnnlGLucsxc7l0RoS/yrRSOIxnzQ8b8KKWMxZCq4UW2mpqa4i9/+Uvcfvvtsfnmm8fll18e//3f/x1XXXVVl2+zvr4+pk+fnreM+bytYps5c2axI/SIcthO29g7NDQ0RJ8+fYodoyTkuy/y3RURxe+LtB4zcuUmrbki0putHHLV19friyzoiu5L6/HUEZl7TinmLqfMuiJ7+iI3pXAcyZgfMuZHKWQshlQNL0aNGhULFy6MxsbGqKqqiiRJYv78+TF69OiNlttzzz1jxIgRERFx5JFHxmc+85lurbumpiYmTJjQzqVzcr699m+rdNTV1cXMmTNj6623jn79+hU7TsGUw3baxt6hZRurq6uLHaXoitUXHXdFRCn1RVqPGblyk9ZcEenNVk65ampq8nI7pUpXFF5aj6eOyNxzSjF3OWYu966I0Bf5VgrHkYz5IWN+lErGYknV8GLo0KGx/fbbx3333RdTpkyJBx98MEaMGLHey/QiIg455JC48847Y+XKlTFw4MD44x//GNtuu2231p3JZKJ///7duo115fO2iq1fv369anvaUw7baRt7h3J/WXdE8foi310RUfy+SOsxI1du0porIr3ZyiFXufeFrug5aT2eOiJzzynF3OWUudy7IkJfFEopHEcy5oeM+VEKGYshVcOLiIjzzz8/zjnnnLj22mtjwIABcckll0RExLnnnhuTJk2KAw44IEaPHh2nnXZaTJ06NTKZTIwYMSIuvPDCIicHoCfpCwA6oysAyIa+AEinbg8vlixZEq+//nosWLAgGhsb21zmYx/7WNa3N27cuLjttts2+v7FF1+80W3mcrsAFJe+AKAzugKAbOgLgPLQ5eHF6tWr48ILL4x77703mpqa2lwmSZLIZDJO7ABlTF8A0BldAUA29AVAeeny8OKiiy6Ku+66K8aPHx+TJ0+O4cOHR1VV6t6FCoAi0xcAdEZXAJANfQFQXrp8hn/ooYdi4sSJcdttt0VlZWU+MwHQi+gLADqjKwDIhr4AKC8VXb1iU1NT7LHHHsoCgA7pCwA6oysAyIa+ACgvXR5e7LDDDjFr1qx8ZgGgF9IXAHRGVwCQDX0BUF66PLz48pe/HE888UT87//+bz7zANDL6AsAOqMrAMiGvgAoL13+zIsPfOAD8fOf/zzOPPPM2G677WLbbbeNAQMGbLRcJpOJL3zhC90KCUDp0hcAdEZXAJANfQFQXro8vHjnnXfi8ssvj2XLlsWTTz4ZTz75ZJvLKQyA8qYvAOiMrgAgG/oCoLx0eXhx0UUXxd///vfYf//949BDD43NN9/cByYBsBF9AUBndAUA2dAXAOWly8OLP//5z7HHHnvEtddem888APQy+gKAzugKALKhLwDKS5c/sDtJkpg4cWI+swDQC+kLADqjKwDIhr4AKC9dHl7ssssu8eqrr+YzCwC9kL4AoDO6AoBs6AuA8tLl4cU3v/nNeOGFF+Lmm2/OZx4Aehl9AUBndAUA2dAXAOWly595cd1118X48ePj4osvjl/+8pcxfvz4GDBgwEbLZTKZ+M53vtOtkACULn0BQGd0BQDZ0BcA5aXLw4vf/OY3rf+eNWtWzJo1q83lFAZAedMXAHRGVwCQDX0BUF66PLx49NFH85kDgF5KXwDQGV0BQDb0BUB56fLwYsyYMfnMAUAvpS8A6IyuACAb+gKgvHT5A7sBAAAAAAAKocuvvLjnnnuyXvZjH/tYV1cDQInTFwB0RlcAkA19AVBeujy8mDZtWmQymQ6XSZIkMpmMwgAoY/oCgM7oCgCyoS8AykuXhxeXXHJJm99fsWJFvPzyy3H//ffHpEmT4iMf+UiXwwFQ+vQFAJ3RFQBkQ18AlJcuDy+OPvroDi8//vjj45RTTokTTjihq6sAoBfQFwB0RlcAkA19AVBeCvaB3R/4wAdi0qRJceWVVxZqFQD0AvoCgM7oCgCyoS8AepeCDS8iIkaPHh2vvvpqIVcBQC+gLwDojK4AIBv6AqD3KNjwIkmS+Nvf/hZ9+vQp1CoA6AX0BQCd0RUAZENfAPQuXf7Mi7/+9a9tfr+xsTHefvvtuPfee+OFF16Ij33sY11dBQC9gL4AoDO6AoBs6AuA8tLl4cXJJ58cmUym3cuTJIlddtklpk2b1tVVANAL6AsAOqMrAMiGvgAoL10eXnzhC19oszAymUxsuummscMOO8ROO+3UrXAAlD59AUBndAUA2dAXAOWly8OLL37xi/nMAUAvpS8A6IyuACAb+gKgvBTsA7sBAAAAAAC6osvDi1dffTXuvPPOWLlyZev3Vq9eHd/+9rfjgx/8YHz0ox+NW2+9NS8hAShd+gKAzugKALKhLwDKS5eHF1dffXVceeWVMWDAgNbvXX755XHbbbfFqlWrYv78+XHBBRfEE088kZegAJQmfQFAZ3QFANnQFwDlpcvDi+effz723HPP1g9KamxsjLvvvjt23HHHePLJJ+PRRx+NIUOGxE033ZS3sACUHn0BQGd0BQDZ0BcA5aXLw4t33nknRo0a1fr1Cy+8ECtXroypU6dGnz59YsSIEXHAAQfEK6+8kpegAJQmfQFAZ3QFANnQFwDlpcvDi8rKyqivr2/9+plnnolMJhN77rln6/cGDx4c77zzTvcSAlDS9AUAndEVAGRDXwCUly4PL8aMGRNPP/1069cPPPBAbLHFFjFmzJjW77399tsxePDgbgUEoLTpCwA6oysAyIa+ACgvXR5eHHXUUfHKK6/Exz/+8fjEJz4Rr7zyShx++OHrLfPqq6/GVltt1e2QAJQufQFAZ3QFANnQFwDlpcvDi5NOOikOPvjgePHFF+Pvf/97fOhDH4rTTz+99fLXXnstXnnlldhrr73yEhSA0qQvAOiMrgAgG/oCoLxUdfWKNTU18YMf/CBWrlwZEREDBw5c7/KhQ4fGPffcs95L9wAoP/oCgM7oCgCyoS8AykuXhxctNiyKFkOGDIkhQ4Z09+YB6CX0BQCd0RUAZENfAJSHbg8vIiKam5tj0aJF0djY2Oblo0ePzsdqAChx+gKAzugKALKhLwB6v24NL+699974xS9+EW+88UY0NTW1uUwmk4mXX365O6sBoMTpCwA6oysAyIa+ACgfXR5e/PznP49LL700qqqqYrfddovhw4dHVVVeXsgBQC+iLwDojK4AIBv6AqC8dPkMf/PNN8eIESPi17/+dYwcOTKfmQDoRfQFAJ3RFQBkQ18AlJeKrl5xyZIlcdBBBykLADqkLwDojK4AIBv6AqC8dHl4sfXWW8fy5cvzmQWAXkhfANAZXQFANvQFQHnp8vDiU5/6VDz66KMxd+7cfOYBoJfRFwB0RlcAkA19AVBeuvyZF0cffXQsXrw4pk6dGieeeGJsu+22MXDgwDaX3X333bscEIDSpi8A6IyuACAb+gKgvHR5eBERsXLlyli5cmVcddVVHS43ffr07qwGgBKnLwDojK4AIBv6AqB8dHl4ceWVV8a1114bQ4YMiUMPPTSGDx8eVVXdmoUA0AvpCwA6oysAyIa+ACgvXT7D33XXXbH11lvHnXfeGQMGDMhnJgB6EX0BQGd0BQDZ0BcA5aXLH9i9fPny+PCHP6wsAOiQvgCgM7oCgGzoC4Dy0uXhxTbbbBMLFizIZxYAeiF9AUBndAUA2dAXAOWly8OL008/PR599NF46aWX8pkHgF5GXwDQGV0BQDb0BUB56fJnXixfvjz22WefmDp1ahx11FGx7bbbxsCBA9tc9mMf+1hXVwNAidMXAHRGVwCQDX0BUF66PLyYNm1aZDKZSJIk7rzzzoiIyGQy6y2TJElkMhmFAVDG9AUAndEVAGRDXwCUly4PLy655JJ85gCgl9IXAHRGVwCQDX0BUF66PLw4+uij85kDgF5KXwDQGV0BQDb0BUB56fIHdgMAAAAAABRCl195MW/evKyXHT16dFdXA0CJ0xcAdEZXAJANfQFQXro8vJg0adJGH4rUlkwmEy+//HJXVwNAidMXAHRGVwCQDX0BUF66PLz42Mc+1mZhrFixIl555ZWYM2dO7L777rHFFlt0KyAApU1fANAZXQFANvQFQHnp8vDiu9/9bruXJUkSv/jFL+K6666L73znO11dBQC9gL4AoDO6AoBs6AuA8lKQD+zOZDLxmc98Jt73vvfF97///UKsAoBeQF8A0BldAUA29AVA71OQ4UWLiRMnxlNPPVXIVQDQC+gLADqjKwDIhr4A6D0KOrx48803o7GxsZCrAKAX0BcAdEZXAJANfQHQe3T5My/a09zcHG+//Xbcfffd8eijj8bee++d71UA0AvoCwA6oysAyIa+AOidujy82HbbbSOTybR7eZIksemmm8bZZ5/d1VUA0AvoCwA6oysAyIa+ACgvXR5e7L777m1+v6KiIjbddNOYOHFiHHPMMTF06NAuhwOg9OkLADqjKwDIhr4AKC9dHl788pe/zGcOAHopfQFAZ3QFANnQFwDlJecP7L766qvj8ssvj4aGhnaXqa+vjyuuuCJ++tOfdiscAKVLXwDQGV0BQDb0BUB5yml48Ze//CWuuuqqGDx4cFRXV7e7XE1NTQwePDiuuOKKeOqpp7odEoDSoi8A6IyuACAb+gKgfOU0vLjnnntik002iZNOOqnTZT/xiU/EpptuGnfffXeXwwFQmvQFAJ3RFQBkQ18AlK+chhfPPfdc7LPPPlFTU9PpsjU1NbHPPvvEs88+2+VwAJQmfQFAZ3QFANnQFwDlK6fhxYIFC2Ls2LFZL7/FFlvEwoULcw4FQGnTFwB0RlcAkA19AVC+chpeVFRUdPjhSBtqaGiIioqcPxMcgBKnLwDojK4AIBv6AqB85XQ233zzzeO1117LevnXXnstNt9885xDAVDa9AUAndEVAGRDXwCUr5yGF7vuums89dRTMWfOnE6XnTNnTjz11FOx++67dzkcAKVJXwDQGV0BQDb0BUD5yml48YlPfCIaGxvjS1/6UixZsqTd5d5555348pe/HE1NTXHCCSfkFGjmzJkxderUmDx5chxzzDEdTteTJIlPfvKTsdtuu+W0DgAKS18A0BldAUA29AVA+arKZeHtt98+TjnllLjxxhvjsMMOi6lTp8aee+4ZI0eOjIiIt99+O5588sm4/fbbY8mSJXHqqafG9ttvn1Og8847L4477riYMmVKPPDAAzFt2rS466672lz2hhtuiC233DJefvnlnNYBQGHpCwA6oysAyIa+AChfOQ0vIiKmTZsWffr0iZ///OdxzTXXxDXXXLPe5UmSRGVlZZx22mnxH//xHznd9uLFi+PFF1+MX/ziFxERMXny5Ljwwgtj1qxZsdVWW6237GuvvRaPPPJIXHLJJfHAAw/kuhkAFJi+AKAzugKAbOgLgPKU8/Aik8nEV7/61Tj22GPjrrvuiueeey4WLVoUERHDhg2LXXbZJaZMmRJbbrllzmHmz58fw4cPj6qqqtZ1jRo1KubNm7deYTQ0NMS3vvWtuPjii6OiIqd3vmpXkiRRW1ubl9uKiLzeVrHU1dWt99/eqhy20zb2Di3bliRJZDKZIqfpXG/si3x3RUTx+iKtx4xcuUlrroj0ZiunXKXQF7oiO2l9bpHW46kjMvecUsxdjplLoSsi9EW20tAXpXAcyZgfMuZHKWUshpyHFy223HLL+MpXvpLPLFn70Y9+FB/96Efjve99b1Yf2JSN+vr6mD59el5uKyLyelvFNnPmzGJH6BHlsJ22sXdoaGiIPn36FDtG1npTX+S7KyKK3xdpPWbkyk1ac0WkN1s55Kqvry+ZvtAVHSt2V3QmrcdTR2TuOaWYu5wyl1JXROiLzqSpL0rhOJIxP2TMj1LIWAxdHl4UwqhRo2LhwoXR2NgYVVVVkSRJzJ8/P0aPHr3ecn/9619j/vz5ccstt0RjY2OsXLkyJk2aFHfeeWcMGTKkS+uuqamJCRMmtHNp7qXU/m2Vjrq6upg5c2ZsvfXW0a9fv2LHKZhy2E7b2Du0bGN1dXWxoxRdsfqi466IKKW+SOsxI1du0porIr3ZyilXTU1NXm6nVOmKwkvr8dQRmXtOKeYux8zl3hUR+iLfSuE4kjE/ZMyPUslYLKkaXgwdOjS23377uO+++2LKlCnx4IMPxogRIzZ6j8Ff/epXrf+eM2dOfOxjH4s//OEP3Vp3JpOJ/v37d+s21pXP2yq2fv369artaU85bKdt7B1K4WXdhVasvsh3V0QUvy/SeszIlZu05opIb7ZyyFXufaErek5aj6eOyNxzSjF3OWUu966I0BeFUgrHkYz5IWN+lELGYsjPB0bk0fnnnx+33XZbTJ48OX7605/GJZdcEhER5557bjz66KNFTgdAWugLADqjKwDIhr4ASKdUvfIiImLcuHFx2223bfT9iy++uM3lt9hii/jb3/5W6FgApIy+AKAzugKAbOgLgHRK3SsvAAAAAACA8mZ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlieAEAAAAAAKSK4QUAAAAAAJAqhhcAAAAAAECqGF4AAAAAAACpYngBAAAAAACkiuEFAAAAAACQKoYXAAAAAABAqhheAAAAAAAAqWJ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlieAEAAAAAAKSK4QUAAAAAAJAqhhcAAAAAAECqGF4AAAAAAACpYngBAAAAAACkiuEFAAAAAACQKoYXAAAAAABAqhheAAAAAAAAqWJ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlieAEAAAAAAKSK4QUAAAAAAJAqhhcAAAAAAECqGF4AAAAAAACpYngBAAAAAACkiuEFAAAAAACQKoYXAAAAAABAqhheAAAAAAAAqWJ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlieAEAAAAAAKSK4QUAAAAAAJAqhhcAAAAAAECqGF4AAAAAAACpYngBAAAAAACkiuEFAAAAAACQKoYXAAAAAABAqhheAAAAAAAAqWJ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlieAEAAAAAAKSK4QUAAAAAAJAqhhcAAAAAAECqGF4AAAAAAACpYngBAAAAAACkiuEFAAAAAACQKoYXAAAAAABAqhheAAAAAAAAqWJ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlieAEAAAAAAKSK4QUAAAAAAJAqhhcAAAAAAECqGF4AAAAAAACpYngBAAAAAACkiuEFAAAAAACQKoYXAAAAAABAqhheAAAAAAAAqWJ4AQAAAAAApIrhBQAAAAAAkCqGFwAAAAAAQKoYXgAAAAAAAKlSVewAG5o5c2ZMmzYt3nnnnRg4cGB897vfjfe///3rLfPkk0/GZZddFrW1tZHJZGL//fePr3/961FRYRYDUC70BQCd0RUAZENfAKRT6s6w5513Xhx33HHx4IMPxuc+97mYNm3aRstsuummccUVV8Tvf//7uPvuu+O5556Le+65p+fDAlA0+gKAzugKALKhLwDSKVXDi8WLF8eLL74YRx55ZERETJ48Od56662YNWvWesttt912MXbs2IiI6NOnT0yYMCHmzp3b43kBKA59AUBndAUA2dAXAOmVqreNmj9/fgwfPjyqqtbGymQyMWrUqJg3b15stdVWbV5n4cKF8eCDD8Y111zTrXUnSRK1tbXduo115fO2iqWurm69//ZW5bCdtrF3aNm2JEkik8kUOU1xFasv8t0VEcXri7QeM3LlJq25ItKbrZxylXtf6IrCS+vx1BGZe04p5i7HzOXeFRH6It9K4TiSMT9kzI9SylgMqRpe5GrlypVx+umnx2c/+9nYYYcdunVb9fX1MX369Dwli7zeVrHNnDmz2BF6RDlsp23sHRoaGqJPnz7FjlFS8tUX+e6KiOL3RVqPGblyk9ZcEenNVg656uvr9UUOdEXXpfV46ojMPacUc5dTZl2RO32RnVI4jmTMDxnzoxQyFkOqhhejRo2KhQsXRmNjY1RVVUWSJDF//vwYPXr0RsuuXLkyPvvZz8YBBxwQp556arfXXVNTExMmTGjn0jk53177t1U66urqYubMmbH11ltHv379ih2nYMphO21j79CyjdXV1cWOUnTF6ouOuyKilPoirceMXLlJa66I9GYrp1w1NTV5uZ1SpSsKL63HU0dk7jmlmLscM5d7V0Toi3wrheNIxvyQMT9KJWOxpGp4MXTo0Nh+++3jvvvuiylTpsSDDz4YI0aM2OhleqtWrYrPfvazsd9++8WZZ56Zl3VnMpno379/Xm4rIvJ6W8XWr1+/XrU97SmH7bSNvUO5v6w7onh9ke+uiCh+X6T1mJErN2nNFZHebOWQq9z7Qlf0nLQeTx2RueeUYu5yylzuXRGhLwqlFI4jGfNDxvwohYzFkKrhRUTE+eefH+ecc05ce+21MWDAgLjkkksiIuLcc8+NSZMmxQEHHBA33XRTvPDCC1FXVxcPP/xwREQcfPDBccYZZxQzOgA9SF8A0BldAUA29AVAOqVueDFu3Li47bbbNvr+xRdf3PrvM844QzkAlDl9AUBndAUA2dAXAOlUUewAAAAAAAAA6zK8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwAAAAAAIFUMLwAAAAAAgFQxvAAAAAAAAFLF8AIAAAAAAEgVwwsAAAAAACBVDC8AAAAAAIBUMbwAAAAAAABSxfACAAAAAABIFcMLAAAAAAAgVQwvAAAAAACAVDG8AAAAAAAAUsXwAgAAAAAASBXDCwDg/7N353FW1fX/wN8XZgZZVAIR2dLsm4houe+lgoI7iobgWmpZltq3RfHn0tctq69ltqllpWma61fNVERLK3MtC1E0LAcFBlldYICZYc7vD5oJZGDuzNyZ+5m5z+fjoTD3nHvu+3Pu55zXPfPm3gsAAACQFM0LAAAAAAAgKZoXAAAAAABAUjQvAAAAAACApGheAAAAAAAASdG8AAAAAAAAkqJ5AQAAAAAAJEXzAgAAAAAASIrmBQAAAAAAkBTNCwAAAAAAICmaFwAAAAAAQFI0LwAAAAAAgKRoXgAAAAAAAEnRvAAAAAAAAJKieQEAAAAAACRF8wIAAAAAAEiK5gUAAAAAAJAUzQsAAAAAACApmhcAAAAAAEBSNC8AAAAAAICkaF4AAAAAAABJ0bwAAAAAAACSonkBAAAAAAAkRfMCAAAAAABIiuYFAAAAAACQFM0LAAAAAAAgKZoXAAAAAABAUjQvAAAAAACApGheAAAAAAAASdG8AAAAAAAAkqJ5AQAAAAAAJEXzAgAAAAAASIrmBQAAAAAAkBTNCwAAAAAAICmaFwAAAAAAQFI0LwAAAAAAgKRoXgAAAAAAAEnRvAAAAAAAAJKieQEAAAAAACRF8wIAAAAAAEiK5gUAAAAAAJAUzQsAAAAAACApmhcAAAAAAEBSNC8AAAAAAICkaF4AAAAAAABJ0bwAAAAAAACSonkBAAAAAAAkRfMCAAAAAABIiuYFAAAAAACQFM0LAAAAAAAgKck1LyorK2PixIkxduzYOOaYY2LmzJlNrnfnnXfGmDFj4sADD4wLL7wwamtrO7hSAIpJXgDQHFkBQD7kBUCakmteXHzxxTFhwoSYMmVKfOYzn4nJkyevs86bb74Z11xzTfzqV7+KqVOnxsKFC+OOO+4oQrUAFIu8AKA5sgKAfMgLgDQl1bxYtGhRTJ8+PY488siIiBg7dmzMmzcvZs2atdZ6U6ZMiVGjRsWAAQMil8vFpEmT4oEHHihGyQAUgbwAoDmyAoB8yAuAdJUVu4A1VVVVxYABA6KsbHVZuVwuBg0aFHPnzo0tt9xyrfWGDBnS+POQIUOiqqqqTY+dZVlUV1e3aRtrKuS2imX58uVr/dlVlcI4jbFraBhblmWRy+WKXE1xFSsvCp0VEcXLi1SPGXW1TKp1RaRbWynVVep5ISvaX6rH04aoueN0xrpLseZSz4oIeVFoneE4UmNhqLEwOlONxZBU86KYampqYsaMGQXbXiG3VWyVlZXFLqFDlMI4jbFrqK2tjR49ehS7jJJU6KyIKH5epHrMqKtlUq0rIt3aSqGumpoaeVEEXTErmpPq8bQhau44nbHuUqpZVhRPV8+LznAcqbEw1FgYnaHGYkiqeTFo0KBYsGBB1NXVRVlZWWRZFlVVVTF48OB11nvjjTcaf54zZ04MGjSoTY9dUVERI0aMWM/S2VFfn992GtZb/7Y6j+XLl0dlZWVstdVW0bNnz2KX025KYZzG2DU0jLG8vLzYpRRdsfJiw1kR0ZnyItVjRl0tk2pdEenWVkp1VVRUFGQ7nZWsaH+pHk8bouaO0xnrLsWaSz0rIuRFoXWG40iNhaHGwugsNRZLUs2L/v37x8iRI+P++++P8ePHx5QpU2LgwIFrvU0vYvXnD06aNCnOOuus2GyzzeK2226Lww47rE2PncvlolevXutd/s1lH4yLyt/497rrLs+y/6wXERvcVmfTs2fPLjWe9SmFcRpj11Dqb+uOKF5eNJcVEZ0vL1I9ZtTVMqnWFZFubaVQV6nnhazoOKkeTxui5o7TGesupZpLPSsi5EV76QzHkRoLQ42F0RlqLIakvrA7IuKSSy6J22+/PcaOHRs/+clP4sorr4yIiAsuuCAee+yxiIgYNmxYnH322TFp0qQ46KCDol+/fnHccce1W029yyIWx/5RV7f654ZwaNDwc13d6vV6J9USAuia5AUAzZEVAORDXgCkKblT29Zbbx233377OrdfccUVa/08YcKEmDBhQofU9OtvjYsjvnJffG3pyfG/fX4ZZU3stbq6iK8tPblxfQDal7wAoDmyAoB8yAuANCX3zotU/eY7q0Pga0tPjsve/mDU1KwOiZqaiMve/mBjWDSsB0BpkhcANEdWAJAPeQGUuuTeeZGy33xnXEw8775YXLd/nLts7WW9y3S5AVhNXgDQHFkBQD7kBVDKNC9aqCEUqqurY8aMGTFixAhfpgLAOuQFAM2RFQDkQ14ApcrHRgEAAAAAAEnRvAAAAAAAAJKieQEAAAAAACRF8wIAAAAAAEiK5gUAAAAAAJAUzQsAAAAAACApmhcAAAAAAEBSNC8AAAAAAICkaF4AAAAAAABJ0bwAAAAAAACSonkBAAAAAAAkRfMCAAAAAABIiuYFAAAAAACQlLJiF5CC+fPnx6pVq2L06NF53yfLsqipqYmKiorI5XLtWF3xlMIYI0pjnMbYNTSMcfHixdG9e/dil1NyWpMVEenOTXW1jLpaLtXaSqmuqqoqedHBulpWNKcz1q3mjtMZ6y7FmmVFcXTlvFBjYaixMNRYGFmWxaJFi6KsrONbCZoXEdGjR4+oqalp0X1yuVz06NGjnSpKQymMMaI0xmmMXUPDGMvKyqKioqLY5ZSc1mRFRLpzU10to66WS7W2UqpLXnS8rpYVzemMdau543TGukuxZllRHF05L9RYGGosDDUWRi6Xi/Ly8qLkRS7LsqzDHxUAAAAAAGA9fOcFAAAAAACQFM0LAAAAAAAgKZoXAAAAAABAUjQvAAAAAACApGheAAAAAAAASdG8AAAAAAAAkqJ5AQAAAAAAJEXzAgAAAAAASIrmBQAAAAAAkBTNCwAAAAAAICmaFwAAAAAAQFI0L5pRWVkZEydOjLFjx8YxxxwTM2fObHK9O++8M8aMGRMHHnhgXHjhhVFbW9vBlbZePmN86qmn4thjj41DDz00DjvssPj2t78d9fX1Rai29fJ9LiMisiyLk08+OXbdddcOrLDt8h3jq6++GieddFIccsghccghh8QjjzzSwZW2Xj5jrK+vjyuvvDIOPfTQOOKII+Kkk06KWbNmFaHa1rn88stj1KhRMXz48JgxY8Z61+vM551S0ZLzTj7WNzc29Dgdseyll16KM888M8aOHRtHHnlkfPrTn2485hYtWhSnnXZajBkzJg4//PB47rnnGrfTEcuOOeaYOOKII2LcuHFx/PHHx8svv5zEPmtYdvfdd8fw4cPj0UcfTWJ/7bPPPjF27NgYN25cjBs3Lh588MEk9tfLL78cl156aYwZMyaOOOKI+OpXv5pEXX/5y18a99W4ceNi7Nixsd1228Xbb79d9OdyzWWkrdBZ0RajRo3qsHNAW6SSh4WoeX37PIWaV65cmUy+F6Lmk046KUaNGtW4r2+88cYkam5w6qmnJvGahXR11PPWWY6jjsys1uz7JUuWrPd1YjH3YyoZuqFlTdW4oXkZ0fFzM5Vcb+l+3NC8LMZ+zEvGBp100knZ3XffnWVZlj300EPZ+PHj11nnjTfeyPbZZ59s/vz5WX19fXbGGWdkt9xyS0eX2mr5jPGll17K3njjjSzLsmzFihXZxIkTG+/TWeQzzgY///nPswsuuCDbZZddOqq8gshnjNXV1dmoUaOy5557LsuyLKurq8sWLVrUoXW2RT5jnDp1anbsscdmNTU1WZZl2Y9+9KPs7LPP7tA62+LZZ5/NqqqqsgMOOCB7+eWXm1yns593SkVLzjv5WN/c2NDjdMSyo446Knv88cez+vr6LMuy7Oabb85OPPHELMuybPLkydn3v//9LMuy7O9//3v28Y9/vPHY7Ihl++yzT+OyRx55JDviiCOS2Gfjx4/P3nzzzey4447LJkyYkE2dOjWJ/bXttttm06ZNy96v2Ptrr732yi699NLGOTZ//vwk6nr/MX3DDTdkZ5xxRpP7tqOfyzWXkbZCZ0VbrO+1R3sdM62VSh4WouYNvd4rds0rVqxIJt8LUfOJJ57YmLfvl8K595133mn8ezFfs5CujnreOstx1JGZVYh9v+brxGLux1QydEPLmqpxQ/OyGPs0lVxv6X58vzXnZZaldYw30LzYgIULF2Y77bRTVltbm2VZltXX12d77713VllZudZ6P/3pT7OLLrqo8efHH388mzhxYofW2lr5jvH9LrnkksaJ1xm0ZJz/+Mc/suOPPz6bNWtWp2pe5DvGO+64I/vyl79cjBLbLN8xTp06NTvyyCOz9957L6uvr8++9a1vZd/4xjeKUXKbbChgOvN5p1S09vyajzXnxoYep6OXNZg2bVp2wAEHZFmWZTvuuGPjL5qzLMuOOeaY7MknnyzKsrvvvjs78sgjk9hne+21V3bcccdlL7744lovEIu9v0aOHJnddttt2ZqKvb+WLl2aDR8+PHvppZeSqqupuX/wwQcn81yuuYx0tWdWtEZTrz3a85gpZL3FOu7bUnNTPzdIqeYGxcz3QtS8oV/IpFRzlhXvNQvpKubzlupx1FGZVah9v+brxBT2Y+rXlO+v8f3WnJfF3KfFzPVC7Mc152Ux9+OGlLXsfRqlpaqqKgYMGBBlZat3Uy6Xi0GDBsXcuXNjyy23XGu9IUOGNP48ZMiQqKqq6vB6WyPfMa5pwYIFMWXKlLjuuus6stQ2yXectbW1cdFFF8UVV1wR3bp1rk9Vy3eMr732WlRUVMQZZ5wR8+bNi+HDh8fkyZOjX79+xSo9b/mOcdSoUfHMM8/EvvvuG717946BAwfGzTffXKyy20VnPu+UitacXwv9OBtvvHGHLmsY1y9/+csYNWpULFmyJGpra2PAgAGN9Q4ZMiTmzp3bocuuueaaOP/88yMi4ic/+UkS+6y8vDw++MEPxvbbb99Yawr7q3v37vHjH/84fvWrX8UOO+wQX/3qV4u+v958880oKyuLn/70pzFr1qzYaKON4qyzzurw+d3c3P/rX/8a7777buy///5JPJcNy0hbR2VFS5x77rkREe16DmiPsXX0uaqQY3j/Pu/Xr1+S+71Y+V6ImhtcddVVcc0118SHP/zh+MpXvhLDhg1LquZzzz03nnnmmYgozmuWYp13aF4x8yLl46gjMqsQx8yarxNT3I/Ffr3fmn36/nmZ0j7tqFxv635sal6mtB8bdK7fzlJ0S5cujc997nNx+umnxw477FDscgruhz/8YRx00EHx4Q9/uNiltJtVq1bFn//857j00kvj3nvvjYEDB8b//M//FLusgpo+fXrMnDkz/vCHP8Qf//jH2HPPPePrX/96scuCknDdddfFG2+8EV/5yleKXUqjT37yk/HEE0/El770pbjqqquKXU784x//iHfeeSeOOOKIYpeyjj322CPOPvvsuOeee+IDH/hAnHfeecUuKVatWhW1tbUxZMiQuOeee+LCCy+ML33pS7Fq1VBqjNMAANusSURBVKpil7aWu+66K8aNG9d48QCd0S233BK/+c1vkjoHdHWdZZ+nmO/NeX/N3/72t+Phhx+O+++/P3bdddc444wzilzhur797W8n9ZoFUj6OOsv5M2Ld14kp7cfOqKlMSmWfduZ5GZHOflyT5sUGDBo0KBYsWBB1dXURsfpLnKuqqmLw4MHrrDdnzpzGn+fMmRODBg3q0FpbK98xRqxuXJx++ukxevTo+PSnP93RpbZJvuN87rnn4pZbbolRo0bF8ccfH0uXLo1Ro0bF4sWLi1F2i7Rkvu6xxx4xcODAyOVyceSRR8bf/va3IlTccvmO8d57740999wzNtlkk+jWrVscffTRjf+CqavozOedUtGS82t7PU5HL/vZz34WjzzySPz0pz+Nnj17xgc+8IEoKyuLBQsWNNY7Z86cGDx4cIcvi4jGc8EWW2xR1H32/PPPx4oVK+KCCy6IUaNGxd/+9re46KKL4qGHHir6/lq8eHEMHjw4ysvL45RTTonnn3++6HOs4dw2fvz4iIjYbrvtYujQoTFnzpxk5v6yZcvioYceimOOOSYiIrm5T7o6Kivy1fC47X0OaA8dfdwXSlP7vL3G01rFzvdC1BzxnzzJ5XJx4oknxptvvhlLlixJpuY1Fes1C+kqxvOW+nHUUZnV1n3//teJqe3HhnpSeV3dnKbmZUr7tCNzvS37sal5mdJ+XJPmxQb0798/Ro4cGffff39EREyZMiUGDhy4zltvxo4dG7/73e9iwYIFkWVZ3HbbbXHYYYcVo+QWy3eMy5Yti9NPPz323XffOPPMM4tRapvkO85bb701fv/738fvfve7uPXWW6NPnz7xu9/9rlN8pFK+YzzkkEPixRdfjKVLl0ZExBNPPBHbbrtth9fbGvmOcdiwYfH0009HTU1NRET8/ve/j2222abD621Pnfm8Uyryna/t+Tgduex3v/td/Pa3v41f/OIXsckmmzTWd/DBB8evf/3riIiYNm1avPXWW7Hbbrt1yLKnnnoq5s6d27js0Ucfjb59+xZ9n/Xr1y+22267+MMf/hC/+93vYscdd4zLLrssjj/++KLur2effTaqqqoal/32t7+N7bbbruj769lnn43evXvHm2++GRGrP0Zq9uzZscsuuyQx97fccst48MEHY9ttt13rnZvFfC7fv4x0dVRW5KO6ujrefffdxp/b8xzQHjr6uC+E9e3z9hpPa/ziF79IIt/bWnNdXV0sXLiwcZ0pU6bEZpttFh/4wAeSqPndd9+Nt956q/HnYr1mIV0d/bylfhx1ZGa1dd+//3ViSvuxQbFf7+e7T9eXSans047O9bbMzaauX1LZj++Xy7Isy3vtEvSvf/0rzj///Hj77bejd+/eceWVV8bw4cMb/7Xk6NGjIyLijjvuiJ/85CcREbH77rvHJZdcEuXl5cUsPW/5jPHaa6+NH/7wh/Ff//Vfjfc7+OCD4/Of/3wRK2+ZfJ/LBrNnz46jjjqqsUvaGeQ7xnvvvTduuOGGyOVyMXDgwLjssss6zb/az2eMNTU1cemll8Zf/vKXKCsriwEDBsQll1wSw4YNK3b5ebn44ovj8ccfj4ULF0bfvn2jd+/eMXXq1C513ikV65uvrbW+ubGhx+mIZV/5ylfi1FNPjWHDhkXv3r0jIqKioiLuvPPOWLhwYZx77rkxe/bsKC8vj4suuij23HPPiIh2XxYR0a1btygvL49cLhf9+vWL8847L0aMGFH0fbbmspNOOilOOeWUOPDAA4u+v7Isi4022igiIoYOHRoXXHBBDB06tOj765xzzokbbrgh3n777cjlcvGFL3whxo4dW/S6GpZNnDgxPvnJT671L5eK+Vy+fxlpK3RWtNabb74ZZ511VuNHsrX3OaAtUsnDttb885//fL37PIWa582bF/vtt18S+d7Wmm+66aY48cQTo7a2NnK5XHzgAx+I888/v/EfcRX73Dtnzpw455xzYuXKlUV/zUK6Oup56wzHUUdnVlv2/ftfJ1ZXVxd1P6aSoRta1lSNN99883ozqRj7NJVcb+l+nDp1apPzMoW5uT6aFwAAAAAAQFJ8bBQAAAAAAJAUzQsAAAAAACApmhcAAAAAAEBSNC8AAAAAAICkaF4AAAAAAABJKSt2AQBdxaxZs+JnP/tZ/P3vf4+ZM2fG1ltvHQ888ECrt/f444/HddddF6+88kqUl5fHtttuG//7v/8bW2yxRQGrBgAAAID0aF4AFMjMmTPjiSeeiI997GNRX18fWZa1elv33XdfXHDBBXHqqafGl770pVi2bFk8//zzsXLlygJWDAAAAABpymVt+e0adGJf+cpX4oEHHojvfOc7cfjhh693vaVLl8Y+++wT5eXl8ac//SkeeeSRmDJlSrz66quxaNGiiIgYPHhw7LPPPnHaaafFwIEDm9zO/fffH7/85S/jtddei/Ly8th5553j7LPPjpEjR6613j333BPnn3/+Bmvfc88946abbmrhiGlv9fX10a3b6k/jmzx5ckyfPr1V77x4++23Y/To0fGVr3wljj/++EKXCbRQqnkREZFlWUydOjVuvvnmeP311+O9996LLbbYIvbYY4/4zGc+E8OGDSvMTgBgg1LOivr6+rj11lvj7rvvjn/961/RvXv3GDFiRJx66qkxevTowuwAAPLSUXmxfPnyuO222+Kll16Kl156KSorKyPLsnjsscdi6NCh633c119/Pb73ve/F008/HcuXL4+tttoqJk6cGJMmTYpcLleYnQAt4DsvKFnHHntsRETcfffdG1zvgQceiBUrVsRhhx0WG220UTz44IPxz3/+Mz72sY/FxIkT47jjjovNNtssfvnLX8bhhx8eM2fOXGcb1157bXzta1+LxYsXx8SJE+Pggw+O5557LiZOnBh/+ctf1lp3xIgR8cUvfrHJ/z7ykY9ERMS+++5boL1AITU0LjYky7L42c9+FmPHjo3tt98+Ro8eHTfeeONa6zz00ENRX1/fOEeB4ko1LyIivvWtb8VZZ50Vr7/+eowePTpOPPHEGDp0aNxxxx0xbty4+Mc//lGYnQDABqWaFVmWxZe+9KW47LLLYunSpXHsscfGYYcdFq+//nqceeaZccsttxRuJwDQrI7Ki0WLFsW3vvWteOCBB6KmpiY23XTTZmt77bXX4pOf/GQ89thj8YlPfCJOOumkqK+vj0suuSQuv/zy1g8a2iKDElVfX5+NGjUq23bbbbM5c+asd71jjz0222abbbJp06ZlWZZlK1asaHK9O+64I9tmm22ys846a63bX3/99Wy77bbLxowZk7377ruNt7/88svZ9ttvnx1yyCHZqlWrmq135cqV2e67755tt9122YIFC/IZIkV03nnnZYcddtg6t1922WXZRz/60ezHP/5x9uSTT2Y/+MEPspEjR2a33nrrWvc9+uijs9tvvz3bf//9sxEjRmRHHnlk9vjjj3fkEIB/SzUv5s+fn2277bbZAQccsNb6WZZlv/jFL7Jtttkmmzx5covHC0DLpZoVDz30ULbNNttkEydOzJYvX954+6JFi7IDDjgg23777bM333yzVWMGoOU6Ki+WLl2a/elPf8qWLFmSZVmWnXrqqdk222yzwXP+CSeckG2zzTZr/e5h5cqV2fHHH59ts8022V//+td8hwkF450XlKxcLhfjx4+P+vr6uOeee5pcZ+bMmTFt2rQYPnx47LDDDhER0aNHjybXPeSQQyIi4o033ljr9nvuuSfq6uri85//fGy88caNt48YMSIOP/zw+Oc//9nkv6Z9v0cffTTefvvt2H///WOzzTbLa4yk5Y033ohbbrkl/t//+3/x+c9/Pvbee+/44he/GJ/61KfiRz/6UdTX10dExIIFC+L111+Pa665Js4555z46U9/GkOGDIkzzzyzyX99B7SvVPNizpw5UV9fHzvttNNa60dE7L///hERsWTJkpYNFoBWSTUrHnvssYiI+NznPhcbbbRR4+39+vWLU045JWpqatZbLwCF11F50bt379hnn32ib9++edX1+uuvx3PPPRd77LFH7Lfffo23V1RUxDnnnBMREXfccUde24JC0rygpI0fPz66desW99xzT5NfrtwQJPl8fM/jjz8eEdH40U4Nnn322YiI2Geffda5T8PHPzWssyF33XVXRER88pOfbHZd0vTnP/85IiLGjBkTdXV1jf/tvffesWDBgqiqqoqI1W/vr66ujksvvTSOOuqo2GeffeKaa66JgQMHxk9/+tNiDgFKVop5seWWW0Z5eXm88MILsXTp0iYfY88992y2HgAKI8WsWLhwYUREk59v3nDb008/3Ww9ABROR+RFSzVkR1MfU77LLrtEr1694rnnnmvTY0BrlBW7ACimQYMGxT777BN//OMf4+mnn4699tqrcVldXV3cf//9UVFREUceeeQ69234vMHly5fHa6+9Fn/6059i6NChcfbZZ6+1XmVlZfTq1SsGDBiwzja23HLLiIiYNWvWBuucM2dOPPXUU7HFFlvExz/+8dYMlQQsWbIksixb7y8Tq6qqYsiQIbHJJptExNq/dCwvL4/ddtvNOy+gSFLMiw984APx1a9+Nb75zW/GwQcfHKNHj44+ffrEK6+8Es8880wcf/zxceKJJxZqFwDQjFSzIiJi9uzZ8eEPf3it9WfPnt24TQA6TkfkRUs1ZEFDlqype/fuMXTo0Hjttdeirq4uysr8OpmOY7ZR8o499tj44x//GHfddddagfH444/HwoUL45BDDmnybXYPP/xwTJkypfHn7bffPq6++uoYNmzYWustXbo0+vXr1+Rj9+nTJyIi3nvvvQ3WeM8990R9fX0cffTR0b1793yHRmI23XTTyOVyceutt0Z5efk6yz/0oQ9FRMR//dd/rXcbK1eubLf6gA1LMS8+9alPxeabbx4XXnhh/PrXv268fZdddonDDz/chQVAB0stKz7xiU/Eb3/72/jJT34Se+65Z+PHjixZsiRuuummiIh49913WzdYAFqtvfOipRreyf3+j6Nt0Lt376ivr49ly5bl9eXfUCg+NoqSN3r06OjXr188+uija73Qb/iYpvW9Te/73/9+vPrqq/Hcc8/FTTfdFOXl5TF+/Ph46qmnClpfw+cg5nK5OOaYYwq6bTpWwwuSt99+O3bYYYd1/mu44DzggAMiItaaSzU1NfHcc8/FyJEjO75wICLSzIsf/vCHce6558bnPve5eOKJJ+Kvf/1r/OpXv4qVK1fGySef3PhZ5wB0jNSy4vDDD4899tgjnn/++TjiiCPisssui4svvjgOP/zwxtee3br5tQBAR0stLyBVXqVQ8srLy2PcuHGxYsWK+M1vfhMRq78w+Y9//GMMHjw49t577w3ef5NNNok999wzbrjhhthoo43ivPPOi9ra2sblffr0We87K5rrbEes/p6EuXPnxp577tnmTjrta/ny5fHwww/Hww8/HHPmzImlS5c2/rx48eL40Ic+FCeccEKce+65ce2118af//zneOKJJ+Kmm26KM888s3E7I0eOjLFjx8ZFF10Ud911VzzxxBNx1llnxcKFC+O0004r4gihtKWWF3/+85/jBz/4QZxwwgnx2c9+NrbYYovo3bt37LrrrnHddddFWVlZfOtb32rrsAFogdSyoqysLG644YY466yzIpfLxe233x5Tp06N0aNHx/e///2IiOjfv3+bxgxAy7V3XrRUc58MsmzZssjlctG7d+9WPwa0huYFxH862g0d7vvuuy/q6uoav0QpH3369ImPfexj8dZbb8Ubb7zRePtWW20V1dXVsWDBgnXu0/B5tE19pmCDO++8MyJ8UXdnsGjRojjnnHPinHPOiWeffTaqqqoaf274rooLL7wwvvSlL8WDDz4Yn/3sZ+Pcc8+Nhx56KHbfffe1tvXNb34zDjvssPjOd74TX/ziF+Odd96JX/ziFzF8+PBiDA34t5Ty4g9/+ENEROyxxx7rrD9gwIDYeuutY9asWbFs2bI8RwdAIaSUFRERFRUV8cUvfjGmTJkS06dPj6eeeiouvfTSeOuttyJi9UeOANDx2jMvWmqrrbaKiKa/k3XVqlUxe/bsGDp0qI+lpcOZcRCrv2Ngxx13jL/97W/xyiuvNH5M0/jx41u0nfnz50dErHUy32233eKFF16IJ598Mo466qi11v/Tn/4UEbHOL64bLFmyJB577LHo27dvHHTQQS2qhY43dOjQePXVVze4Ti6XixNPPLHZL9Ht1atXXHjhhXHhhRcWskSgjVLKi4Z/WbV48eImH2Px4sXRrVu3Jr9jB4D2k1JWbEjDv/Q99NBDW1QXAIXRnnnRUrvttltErM6Sz372s2st+8tf/hLV1dVx8MEHt3r70FreeQH/1tDxvuSSS+Kf//xn7L333jFkyJC11lm6dGn861//avL+d911V0ybNi222mqrtf610/jx46OsrCyuvfbatd5+N2PGjHjggQfiwx/+cOyyyy5NbvO+++6L2traOOKII6KioqKtQwSgAFLJi5133jkiIm688cZ13t592223xbx582LHHXeUHwBFkEpWNDzO+z388MNx9913xw477BBjxoxp9TgBaJv2youW2nrrrWO33XaLZ555Jp544onG22tqauKaa66JCJ8IQnHksizLil0EpGDp0qXx8Y9/PKqrqyMi4uqrr17nXyHNnj07DjzwwNh+++1j6623joEDB8Y777wT06dPj5deein69OkTN9xwQ+y0005r3e/aa6+N733vezFkyJAYM2ZMLFu2LH77299GbW1t3HjjjettXhxxxBHxj3/8I+6//34fFwSQiFTyYtWqVXHKKafEc889F/37949Ro0bFxhtvHC+//HI8/fTTsdFGG8XNN98cH/3oR9t/pwCwllSyIiLikEMOiUGDBsXWW28dPXr0iGnTpsWzzz4bw4YNi5tuummdX5IB0HHaMy++9a1vxZIlSyIi4sknn4z58+fH2LFjo1evXhGxunGy6667Nq4/c+bMmDRpUqxYsSIOPfTQGDBgQDzxxBMxc+bMOPHEE+Oiiy5qz10BTdK8gDWcf/75cc8990Tfvn3jj3/84zr/WrW6ujpuuOGGePbZZ6OysjLefvvtKC8vjyFDhsQ+++wTn/70p2OLLbZoctv3339/3HTTTfHaa69FeXl57LzzznHOOefEyJEjm1x/2rRp8clPfjI++tGPNn7vBQBpSCUvampq4sYbb4yHHnooXn/99aitrY3+/fvHHnvsEZ/73Ofiwx/+cLuMH4DmpZIVP/jBD+KRRx6JOXPmRF1dXQwdOjTGjBkTp59+euMXtAJQPO2VF6NGjYo5c+as93GvvPLKdT6i6l//+ld873vfi2eeeSaqq6tjq622iokTJ8bxxx8fuVyuMAOGFtC8AAAAAAAAkuI7LwAAAAAAgKRoXgAAAAAAAEnRvAAAAAAAAJKieQEAAAAAACRF8wIAAAAAAEiK5gUAAAAAAJAUzQsAAAAAACApmhcAAAAAAEBSNC8AAAAAAICkaF4AAAAAAABJ0bwAAAAAAACSonkBAAAAAAAkpazYBdC+Vq1aFbW1tcUuA4qivLw8unfvXuwyoFOQF5QyeQH5kRWUMlkB+ZMXlDJ5UViaF11UlmUxb968ePvtt4tdChRV3759Y4sttohcLlfsUiBJ8gJWkxewfrICVpMVsGHyAlaTF4WjedFFNYTF5ptvHr169XKwUHKyLIvq6uqYP39+REQMGjSoyBVBmuQFpU5eQPNkBaVOVkB+5AWlTl4UnuZFF7Rq1arGsOjfv3+xy4Gi6dmzZ0REzJ8/PzbffHNv24P3kRewmryA9ZMVsJqsgA2TF7CavCgsX9jdBTV8rmCvXr2KXAkUX8Nx4PM2YV3yAv5DXkDTZAX8h6yA9ZMX8B/yonA0L7owb88DxwHkw3ECjgNojmMEHAeQD8cJOA4KSfMCAAAAAABIiuYFyfvBD34Qw4cPb/xvjz32iEmTJsUTTzzRLo930kknxRlnnNEu2+7K3v88Nfx3+OGH53X/UaNGxaWXXtrOVQJdlazoPOQFUEzyonOQFUAxyYrOQ150fb6wm2bV1K6KP/19bjw9vSreq66JjXtVxJ7bD4p9PzY4Kso75ktnNtpoo7jpppsiYvUX3lx33XXxuc99Ln71q1/Fzjvv3CE10Lw1n6c1bwO6PllBS8gLKF3ygnzJCihdsoKWkBddm+YFG/TM9Kq4+tcvxLLltZHLRWRZRC4X8dSLVfGTe1+ML0/aOXYfuUW719GtW7fYcccdG3/+2Mc+Fvvtt1/ce++9QmMNWVYfde8sjKxmeeQqekbZpptFLtdxb7B6//MElAZZ0fnIC6AY5EXnIiuAYpAVnY+8oD1pXrBez0yviitufDYiW/1z9r4/q5fXxuW/eCYu+NTuscf2gzq0toEDB0a/fv1i7ty5jbe98MILcfXVV8e0adOie/fusf/++8f/+3//L/r379+4zlVXXRVPPPFEzJ49O/r06RO77bZbTJ48OTbffPMOrb891CycHctefSZqF86J+rqa6FZWEeWbDYnew/eIis2GFq2u6urquOqqq+LJJ5+MefPmRf/+/WPfffeNr33ta7Hxxhuv935LliyJ008/PbIsixtuuCH69esX//znP+Oqq66KZ599NlatWhW77757XHjhhfHBD36wA0cErElWdD7yAigGedG5yAqgGGRF5yMvaG++84Im1dSuiqt//UJE1pgZ68j+/b/v/fqFqKld1YHVRSxbtizeeeedGDp09YnwhRdeiJNOOik23njjuPrqq+Oyyy6LF198Mc4888y17rdo0aI444wz4vrrr48LLrgg5syZEyeddFLU1dV1aP2FVrNwdrzz7G+jZt6/oluvjaO8/+Do1mvjqJn3r9W3L5zdYbXU1dWt9d+KFSti1apV8d///d/x05/+NM4555x47rnn1nlu1rRgwYI4+eSTo6KiIm666abo169fvPnmmzFx4sR455134pvf/GZcddVVsXjx4vjUpz4VNTU1HTY+4D9kRecjL+QFFIO86FxkhayAYpAVnY+8kBcdwTsvaNKf/j43li2vbXa9LCKWLq+NJ6fNjQN2GdauNTWc2OfPnx//+7//G717946TTz45IiK+853vxPbbbx8//OEPI5fLRUTENttsE4cffng88cQTsd9++0VExJVXXtm4vVWrVsVOO+0Un/jEJ+Lpp5+Offfdt13rby9ZVh/LXn0m6pe/G2WbDWscf65Hr8htNizqFr4Zy159Nsr7D273t+1VV1fHyJEj17rt29/+dlxyySWNP9fV1cXQoUPj+OOPj9dffz0+9KEPrbX+3Llz41Of+lQMGTIkfvSjH0WvXr0iIuKHP/xhbLrppvGLX/wievToERERO++8c4wePTruvPPOOOGEE9p1bMC6ZEXnIi/kBRSLvOg8ZIWsgGKRFZ2LvJAXHUXzgiY9Pb2q8bMFm9Pw2YPtGRrvPxF17949fvzjH8fWW28dy5cvj7/+9a9x7rnnxqpV/+m8b7XVVjFo0KB48cUXG0PjiSeeiGuvvTZmzpwZS5cubVy3srKy04ZG3TsLo3bhnOi+yWaNYdEgl8tF9002i9qFs6PunYVR3rd935a40UYbxS233LLWbcOGDYt77703brzxxpg1a1ZUV1c3LqusrFwrMN5444044YQTYtttt41rrrkmKioqGpc9+eSTceihh0b37t0bX0Bssskmsd1228X06dPbdVxA02RF5yIv5AUUi7zoPGSFrIBikRWdi7yQFx1F84ImvVddk1dgRKwOlveq2/etUg0noizLorKyMr7zne/EeeedF7/5zW8iy7JYtWpVXHnllWt1tBtUVVVFRMS0adPizDPPjNGjR8dnPvOZ6N+/f+RyuZgwYUKsXLmyXetvT1nN8qivq4nu5T2aXJ4r7xH1qxZFVrO83Wvp1q1b7LDDDmvdNnXq1DjvvPPiuOOOi//+7/+Ovn37xoIFC+ILX/jCOvv9xRdfjLfffjsuuOCCtcIiYvXnDt50001x0003rfO45eXlhR8M0CxZ0bnIC3kBxSIvOg9ZISugWGRF5yIv5EVH0bygSRv3qmhRx3vjXhXNr9gGa56IPvrRj8aHPvShmDBhQvzoRz+K8847L3K5XJxxxhlx4IEHrnPfD3zgAxER8eijj0afPn3ie9/7XnTrtvota3PmzGnXujtCrqJndCuriKx2ZeR69FpneVa7Mrp1r4hcRc8iVBfx8MMPx4gRI+LSSy9tvO3ZZ59tct3DDjssunfvHl/+8pfj+uuvj7322qtx2aabbhr77bdfHH/88evcr3fv3oUvHGiWrOhc5IW8gGKRF52HrJAVUCyyonORF/Kio2he0KQ9tx8UT71Ylde6WRax1w6D2rmite2www5x2GGHxT333BNf/OIXY8cdd4x//etf63Ra17RixYooLy9f6+1sv/nNbzqi3HZVtulmUb7ZkKiZ96/IrfE5gxGx+l8DvLswKrb4cJRtullR6mvY72va0H6/4IILYuXKlXHmmWfGDTfcELvssktEROy1114xc+bM2G677aJ79+7tWjOQH1nRucgLoFjkRechK4BikRWdi7ygo7TvN6bQae37scHRu2d55JpZLxcRfXqWxz4fHdwRZa3lzDPPjFWrVsVNN90U5557bjz++OPxpS99KaZOnRrPPPNM3HfffXHeeefFM888ExER++yzTyxYsCAuu+yyeOqpp+LHP/5x/N///V+H111ouVy36D18j+jWc5OoW/hm1K+sjqx+VdSvrI66hW9Gt16bRO/hu7f7FyStz9577x3Tpk2LH/3oR/HnP/85rrzyynjqqac2eJ9LLrkkxowZE5/97Gdj2rRpERFx9tlnx6xZs+K0006LBx98MJ599tl48MEH43/+53/igQce6IihAO8jKzoXeSEvoFjkRechK2QFFIus6FzkhbzoKJoXNKmivHt8edLOEblYb3Dk/v2//560c1SUd3z3ceutt45DDz00brvttvjIRz4St956a1RXV8f5558fn/3sZ+PHP/5xbLTRRrHllltGRMR+++0XX/3qV+Oxxx6Lz3/+8/H888/H9ddf3+F1t4eKzYbGprsfFhVbbB311e9F7eK5UV/9XlRs8eHYdLfDomKzoUWrbeLEiXHqqafGLbfcEl/84hejqqoqvvOd72zwPrlcLr7xjW/EJz7xiTj99NPjlVdeiS233DLuvPPO6Nu3b1xyySVx2mmnxVVXXRXLly+P4cOHd9BogDXJis5HXsgLKAZ50bnIClkBxSArOh95IS86Qi7L8v06HDqLFStWxOuvvx4f+tCHYqONNmrTtp6ZXhXf+/ULsXR5beNnDzb82adnefz3pJ1j95FbFKhy2irL6qPunYWR1SyPXEXPKNt0s6J1uVNRyOMBuppCHR+yovORF+uSF9A01xalS1asS1bA+rm2KF3yYl3yonB85wUbtMf2g+Kmr28eT06bG0+9WBXvVdfExr0qYq8dBsU+Hx1clE4365fLdYvyvpsXuwygxMiKzkdeAMUgLzoXWQEUg6zofOQF7UnzgmZVlHePA3YZFgfsMqzYpQCQKFkBQD7kBQDNkRVAg9J+Dw8AAAAAAJAczQsAAAAAACApmhcAAAAAAEBS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21v/ttKyfPnyqKysjK222ip69uxZ7HJazTjSYhztq6KiotglFF2x8mLDWRHRWfMi1bm+JjUWhhoLo7PUWOpkRdulPNdTrU1dLaOulmmPulxbyIvUpHr8FZIxdh2lMM6GMZaXlxfl8ZNqXvTv3z9GjhwZ999/f4wfPz6mTJkSAwcOXOttehERhxxySNx1112xdOnS6NOnTzzxxBOx7bbbtumxc7lc9OrVq03bWFMht9URevbs2elqbopxpMU42kepv607onh5UeisiEgrL1Kb601RY2GosTA6Q42lTFYUTspzPdXa1NUy6mqZQtbl2kJepCrV46+QjLHrKIVxFisvkmpeRERccsklcf7558f1118fvXv3jiuvvDIiIi644IIYNWpUjB49OgYPHhxnnHFGTJw4MXK5XAwcODAuu+yyIlcOQEeSFwA0R1YAkA95AZCmNjcvFi9eHK+99lrMnz8/6urqmlznqKOOynt7W2+9ddx+++3r3H7FFVess82WbBeA4pIXADRHVgCQD3kBUBpa3bxYsWJFXHbZZXHffffFqlWrmlyn4VvIndgBSpe8AKA5sgKAfMgLgNLS6ubF5ZdfHnfffXcMHz48xo4dGwMGDIiysuQ+hQqAIpMXADRHVgCQD3kBUFpafYZ/5JFHYvvtt4/bb789unfvXsiaAOhC5AUAzZEVAORDXgCUlm6tveOqVati9913FxYAbJC8AKA5sgKAfMgLgNLS6ubFDjvsELNmzSpkLQB0QfICgObICgDyIS8ASkurmxfnnHNOPPnkk/H73/++kPUA0MXICwCaIysAyIe8ACgtrf7Oi5122il+9rOfxZlnnhnbbbddbLvtttG7d+911svlcvGFL3yhTUUC0HnJCwCaIysAyIe8ACgtrW5eLFmyJL773e/GO++8E0899VQ89dRTTa4nMABKm7wAoDmyAoB8yAuA0tLq5sXll18ef/nLX2K//faLQw89NDbffHNfmATAOuQFAM2RFQDkQ14AlJZWNy/++Mc/xu677x7XX399IesBoIuRFwA0R1YAkA95AVBaWv2F3VmWxfbbb1/IWgDoguQFAM2RFQDkQ14AlJZWNy923nnnePXVVwtZCwBdkLwAoDmyAoB8yAuA0tLq5sW5554bL774Ytxyyy2FrAeALkZeANAcWQFAPuQFQGlp9Xde3HDDDTF8+PC44oor4uabb47hw4dH796911kvl8vFN77xjTYVCUDnJS8AaI6sACAf8gKgtLS6efF///d/jX+fNWtWzJo1q8n1BAZAaZMXADRHVgCQD3kBUFpa3bx47LHHClkHAF2UvACgObICgHzIC4DS0urmxZAhQwpZBwBdlLwAoDmyAoB8yAuA0tLqL+wGAAAAAABoD61+58W9996b97pHHXVUax8GgE5OXgDQHFkBQD7kBUBpaXXzYvLkyZHL5Ta4TpZlkcvlBAZACZMXADRHVgCQD3kBUFpa3by48sorm7z9vffei5dffjkeeOCBGDVqVBxwwAGtLg6Azk9eANAcWQFAPuQFQGlpdfPi6KOP3uDy4447Lk455ZSYNGlSax8CgC5AXgDQHFkBQD7kBUBpabcv7N5pp51i1KhRcc0117TXQwDQBcgLAJojKwDIh7wA6FrarXkRETF48OB49dVX2/MhAOgC5AUAzZEVAORDXgB0He3WvMiyLJ5//vno0aNHez0EAF2AvACgObICgHzIC4CupdXfefHcc881eXtdXV289dZbcd9998WLL74YRx11VGsfAoAuQF4A0BxZAUA+5AVAaWl18+Kkk06KXC633uVZlsXOO+8ckydPbu1DANAFyAsAmiMrAMiHvAAoLa1uXnzhC19oMjByuVxsuummscMOO8THPvaxNhUHQOcnLwBojqwAIB/yAqC0tLp5cdZZZxWyDgC6KHkBQHNkBQD5kBcApaXdvrAbAAAAAACgNVrdvHj11VfjrrvuiqVLlzbetmLFivj6178eH//4x+Oggw6K2267rSBFAtB5yQsAmiMrAMiHvAAoLa1uXlx77bVxzTXXRO/evRtv++53vxu33357LFu2LKqqquLSSy+NJ598siCFAtA5yQsAmiMrAMiHvAAoLa1uXkybNi322GOPxi9Kqquri3vuuSc++tGPxlNPPRWPPfZY9OvXL375y18WrFgAOh95AUBzZAUA+ZAXAKWl1c2LJUuWxKBBgxp/fvHFF2Pp0qUxceLE6NGjRwwcODBGjx4dr7zySkEKBaBzkhcANEdWAJAPeQFQWlrdvOjevXvU1NQ0/vzss89GLpeLPfbYo/G2vn37xpIlS9pWIQCdmrwAoDmyAoB8yAuA0tLq5sWQIUPimWeeafz54YcfjqFDh8aQIUMab3vrrbeib9++bSoQgM5NXgDQHFkB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qqqK7t27F7uMktOarIhIdx6tSY2FocbCUGNhZFkWixYtirIyL/c7UlfLilTriki3NnW1jLpapj3qcm1RHF0tLwrJGLuGUhhjRGmMs2GMixcvLkpeuJqJiB49ekRNTU2L7pPL5aJHjx7tVFHHMY60GEdaUh1HWVlZVFRUFLuMktOarIhIdx6tSY2FocbCUGNh5HK5KC8vlxcdrKtlRap1RaRbm7paRl0t0x51ubYojq6WF4VkjF1DKYwxojTG2TDGYuVFLsuyrMMfFQAAAAAAYD185wUAAAAAAJAUzQsAAAAAACApmhcAAAAAAEBSNC8AAAAAAICkaF4AAAAAAABJ0bwAAAAAAACSonkBAAAAAAAkRfMCAAAAAABIiuYFAAAAAACQFM0LAAAAAAAgKZoXAAAAAABAUjQvWqmysjImTpwYY8eOjWOOOSZmzpxZ7JIiImLlypVx5plnxtixY+PII4+MT3/60zFr1qyIiFi0aFGcdtppMWbMmDj88MPjueeea7xfa5d1hLvvvjuGDx8ejz76aKccR01NTVx66aUxZsyYOOKII+KrX/1qRGx4DrV2WXt54okn4uijj45x48bF4YcfHv/3f/8XEek/F5dffnmMGjUqhg8fHjNmzGi8vT32farnBIqro+bFhs79J510UowaNSrGjRsX48aNixtvvLHxfh19DI8aNSrGjh3bWMuDDz4YEekck0uWLGmsbdy4cTF27NjYbrvt4u233y7qfkzlXLahZU3VuKF5GdHxc3N9+3F98zKV/biheVmM/UjhtUdWpHjeOProo+OUU07psOuUli479dRT44gjjohx48bF8ccfHy+//HLR91nDso64HmrpslQy/f3LXn755Q679sp32bhx4+Lggw9u8jyewnNJmvLNhjvvvDPGjBkTBx54YFx44YVRW1vbwZW2Xj5jfOqpp+LYY4+NQw89NA477LD49re/HfX19UWotnVakvFZlsXJJ58cu+66awdW2Hb5jvHVV1+Nk046KQ455JA45JBD4pFHHungStsmn3HW19fHlVdeGYceemgcccQRcdJJJ611/ZOy9b12fL+inHMyWuWkk07K7r777izLsuyhhx7Kxo8fX+SKVluxYkX2+OOPZ/X19VmWZdnNN9+cnXjiiVmWZdnkyZOz73//+1mWZdnf//737OMf/3hWU1PTpmXt7c0338yOO+64bMKECdnUqVM75TiuuOKK7NJLL218TubPn59l2YbnUGuXtYf6+vpst912y2bMmJFl2ernZPvtt8/ee++95J+LZ599NquqqsoOOOCA7OWXX268vT32farnBIqro+bFhs79J554YuP58/06+hh+/7HYINVj8oYbbsjOOOOMLMuKux9TOZdtaFlTNW5oXhZjn65vP65vXqayH99vzXmZZWkd47ROe2RFiueN+++/PzvooIM67DqlpcsWLlzYWPcjjzySHXHEEUXfZw899FB2+OGHd8j1UEuX7b///klk+vuX7bXXXh127dXaZWuex1N4Lp3f05RPNrzxxhvZPvvsk82fPz+rr6/PzjjjjOyWW27p6FJbLZ8xvvTSS9kbb7yRZdnq15YTJ05svE9n0JKM//nPf55dcMEF2S677NJR5RVEPmOsrq7ORo0alT333HNZlmVZXV1dtmjRog6ts63yGefUqVOzY489tvG8+qMf/Sg7++yzO7TO1srnOqRY5xzNi1ZYuHBhttNOO2W1tbVZlq3+5e7ee++dVVZWFrmydU2bNi074IADsizLsh133LHxxVuWZdkxxxyTPfnkk21a1p5WrVqVnXLKKdmLL7641oV5ZxrHsmXLsp122il777331rp9Q3OotcvaS319fbb77rtnzz77bJb9f/buO06uul4f+DPJZkOKlEASUrggaigBQXoVDSVKVUAEBFFBRa6oV72UH6KCIuoFES9Xiihiw4JIUwlNkF5sdIxoQhICJBhKCmw2Ob8/MGtCypbs7nw3+36/Xhh3ztkzz5w55zw7+WR2qqp69NFHq1122aV65ZVXesxzsfjFtyv2fU+6JtB96nlcLH7tX9FfbHb3ObysH4RKPiff8Y53tOy7EvZjPa9lbd2nK/phd/Hjsp77tK3Di1L34+LHZT33I52jq7ui5OtGV79OWZlj/Je//GW1//77132fNTc3V2PHjq2uv/76Ln891N5lO+64Y907/bXLZs+eXW200UbVww8/XFSu1x77i1/HS3guXd/L09Zu+M53vlOdeuqpLV/fcsst1aGHHtqtWTuqo/132mmntQzgSteex/jXv/61Ovzww6vJkyf3qOFFWx/jz3/+8+rTn/50PSJ2irY+zhtuuKHaf//9q5deeqlauHBh9bWvfa36yle+Uo/IHbai1yH1uuY0dP17O1Y906dPz9ChQ9PQ8Oruq9VqGTFiRJ566qmsv/76dU63pB/84AcZN25cZs2alfnz52fo0KEty0aNGpWnnnqqw8u62iWXXJKtttoqm222WcttPe1xPPnkk1lzzTVzwQUX5M4778xqq62W448/Pq973euWewx1dFlXHXu1Wi3nnHNOPv7xj2fgwIF54YUXct5552XOnDk96rlYZEXnb096XihfPbti0bV/kbPOOivnnntu3vCGN+Qzn/lM1ltvvbpdT0844YQkyeabb57PfvazxZ6Tf/zjH/Piiy/mbW97W5H7sbv3W2fs09celyXt09cel0OGDCny2FzWcVnSfqT9urMrSrtudOXrlI4uO+GEE3LPPfckSS666KK677Pvf//7WWuttTJ48OCWrKXsrylTptS901+7bMqUKWloaMh3vvOdTJ48uUtfe3V02XPPPddyHS/luXR9L09bu2H69OkZNWpUy9ejRo3K9OnTuz1vR3Sk/2bMmJEJEybkggsu6M6oHdbWxzh//vyceuqpOeOMM9KnT8/67f5tfYx/+9vf0tjYmI9+9KN5+umns9FGG+Wkk07KkCFD6hW9Xdr6OMeNG5d77rknu+yySwYNGpThw4fnhz/8Yb1id7p6XXN61llBu1xwwQV58skn85nPfKbeUdrtr3/9a66//vp87GMfq3eUlbJgwYJMmzYtb3zjG3PFFVfkc5/7XD71qU9lwYIF9Y7WZs3NzTn//PNz3nnn5Xe/+12+//3v54QTTuhRjwF6k9de+7/+9a/nuuuuy9VXX51tttkmH/3oR+uW7Uc/+lGuueaaXHHFFVlrrbVy4okn1i1Lay6//PIccMABLT+glrQfe6Jl/UxSyj7tycdlUs5+hPYo9XXK17/+9dx666351Kc+lbPOOquuWRa9Hho2bFhdcyzPhz/84eKunQsWLMj8+fMzatSoYl97Les6DrRu9uzZOfbYY3PMMcdk8803r3ecTnXeeedlzz33zBve8IZ6R+kyCxYsyJ133pnTTz89V155ZYYPH54vfvGL9Y7V6R566KFMnDgxv//973Pbbbdlhx12yBe+8IV6x+rxDC86YMSIEZkxY0aam5uTvPqhOtOnT8/IkSPrnOzfvvvd7+b666/Pd77znQwYMCBrrbVWGhoaMmPGjJZ1pk2blpEjR3Z4WVe6//77M23atIwfPz7jxo3Ln//855x66qn57W9/26Mex4gRI9KnT5/st99+SZJNN900o0ePzrRp05Z7DK3o+KrHsffoo4/m2WefzbbbbpskefOb35zhw4fn8ccf71HPxSId3b+lPS+Urx7HxWuv/YtyJK/+65AjjjgiU6ZMyaxZs+rSC4vW6devX4466qjcf//9RZ6Tc+bMyW9/+9scdNBBLbeVtB8X5enO/bYy+3RZx2VJ+3RZx2U99nFrlnVclrQf6Zju7IpSrht33HFHl79OWdlj/N3vfnfuueeerLvuunXbZ4teDz3yyCM58cQTu/T1UEeWbbrppknq2+mvXbboenjggQcm6drXXh1ZttZaay1xHS/x2KcMbe2GESNGZNq0aS1fT5s2reU8KF17+m/27Nk55phjsvvuu+eDH/xgd0ftsLY+xvvuuy8/+tGPMm7cuBx++OGZPXt2xo0bl3/+85/1iN0u7TlWt99++wwfPjy1Wi37779//vznP9chcce09XFeeeWV2WGHHbL66qunT58+LT9PrCrqdc0xvOiAtddeO2PHjs3VV1+dJJkwYUKGDx9ezK+HueSSS/LrX/86l1xySVZfffWW29/xjnfkpz/9aZLkgQceyDPPPNPyF9IdXdZVDj/88Nx+++25+eabc/PNN2fLLbfMl770pRx++OE96nEMGTIkO+64Y26//fYkr76VeerUqdl6662Xewyt6Piqx7E3YsSIPPvss3niiSeSJJMnT86UKVPy+te/vkc9F4t0dP+W9rxQvu4+LpZ17W9ubs7MmTNb1pkwYULWWWedrLXWWkm6txfmzp2bF198seXrX//619l0002LPCd/85vfZOONN275108l7cdFunu/dXSfLu9nklL26fKOy3rs49a89rgsaT/Scd3ZFSVcN/r27Zs777yzW16ntGfZ9OnTl9jnN954Y9Zcc8267rPDDz88n/vc57LJJpvk97//fZe/HmrPskW/8mORenX6a5fde++9GTRoUKZMmZKka197dWTZgw8+uNR1vN7Ppet7mdraDePHj8/NN9+cGTNmpKqqXHbZZdlnn33qEbnd2voY58yZk2OOOSa77LJLjjvuuHpE7bC2Psaf/OQn+d3vfpebb745P/nJTzJ48ODcfPPNPeJXKrX1Mb7zne/Mgw8+mNmzZydJbr311my88cbdnrej2vo411tvvdx9991pampKkvzud7/LmDFjuj1vV6nXNadWVVXV5feyCvr73/+ek08+Oc8//3wGDRqUM888c4kf4Orl6aefzm677Zb11lsvgwYNSpI0NjbmF7/4RWbOnJkTTjghU6dOTb9+/XLqqadmhx12SJIOL+suRx55ZI466qjssccePe5xTJkyJf/v//2/PP/886nVavnP//zPjB8/foXHUEeXdZVrr702F154YWq1Wqqqykc+8pHst99+xT8Xn//853PLLbdk5syZWXPNNTNo0KDccMMNXbLvS70mUF/ddVws79p/6aWX5ogjjsj8+fNTq9Wy1lpr5eSTT275QbE7z+EpU6bk+OOPb/nVDaNHj84pp5yS0aNHF3dOHnrooXnPe97T8i8j586dW9f9WMq1bEXLlpXxhz/84XJ/JqnHPl1Wxu9973vLPS5L2Y833HDDMo/LEo5NOkdXdEWJ143Gxsb89a9/7bbXKe1Z9rGPfSzf//7388orr6RWq2XIkCE58cQTs8kmmxRzre3q10PtWfbRj3403/ve94ro9Ncu++QnP5mLL764W157tXfZF77whaWu4/V+Ll3fy7W84+uUU07JuHHjsvvuuydJfv7zn+eiiy5Kkmy33XY57bTT0q9fv3pGb7O2PMZFv8L6jW98Y8v3veMd7+gxv2K8rc/jIlOnTs273vWulncC9wRtfYxXXnllLr744tRqtQwfPjxf+tKXesw7hZK2Pc6mpqacfvrp+cMf/pCGhoYMHTo0p512WtZbb716x2/V8n52LOGaY3gBAAAAAAAUxa+NAgAAAAAAimJ4AQAAAAAAFMXwAgAAAAAAKIrhBQAAAAAAUBTDCwAAAAAAoCgN9Q4AAAAAAAC0z+TJk/Pd7343f/nLXzJx4sRsuOGGufbaazu8vVtuuSUXXHBBHnvssfTr1y8bb7xx/ud//ifrrrtuJ6ZuO8MLAAAAAADoYSZOnJhbb701W2yxRRYuXJiqqjq8rauuuiqnnHJKPvShD+VTn/pU5syZk/vvvz+vvPJKJyZun1q1Mo8IAAAAAADodgsXLkyfPq9+MsRJJ52Uhx56qEPvvHj++eez++675zOf+UwOP/zwzo7ZYd55Qa/1mc98Jtdee23OPvvs7Lvvvstdb/bs2dl5553Tr1+/3H777bn++uszYcKEPP7443nuueeSJCNHjszOO++co48+OsOHD1/i++fNm5fLLrssDz/8cB5++OFMmjQpVVXlpptuyujRo5d5nzfffHPuuOOOPPzww3nssccyb968fPzjH8/xxx/feTsAgDYptS9mzZqV66+/Pr/73e8yceLEPPPMMxk0aFA233zzHHXUUdl11107d0cAsFyldsXi7rnnnnz/+9/Pn//857z00ktZe+21s9lmm+X444/PxhtvvPI7AYBWldoX99xzT97//vevMPt6662XG2+8sQOPmq60aHCxIlVV5Xvf+15+/vOfZ9q0aRk+fHiOPPLIfOADH2hZ57e//W0WLlyYgw8+uAvTtp/hBb3WwQcfnGuvvTa//OUvV1gY1157bV5++eW8613vymqrrZbf/OY3mTRpUrbYYosMGzYsVVXl0UcfzQ9+8IP86le/yk9+8pO86U1vavn+5557Ll/72teSJKNGjcoaa6yR559/foXZLrnkktx7770ZPHhwhg0blsmTJ3fKYwag/Urti+uuuy5f/OIXM2zYsOy4444ZPnx4nn766Vx//fW57bbb8t///d855phjOm0/ALB8pXbFIueff36++c1vZtiwYdljjz2y1lprZebMmfnjH/+Yxx9/3PACoJuU2hejRo3Kxz/+8WUuu/POO/PHP/4xu+yyS8ceNHV3xhln5Be/+EWOPfbYbLHFFvnjH/+Ys846K/37989hhx2WJPnLX/6S17/+9bnyyitz/vnn55lnnsmb3vSmfPrTn85uu+1Wv/AV9FILFy6sxo0bV2288cbVtGnTlrvewQcfXI0ZM6Z64IEHqqqqqpdffnmZ6/385z+vxowZUx1//PFL3D579uzq9ttvr2bNmlVVVVV96EMfqsaMGVNNmTJlufd53333Vf/4xz+qhQsXVtdee201ZsyY6lvf+lY7HyEAnaHUvrjzzjurm266qVqwYMEStz/xxBPV1ltvXY0dO7Z6+umn2/owAVgJpXZFVVXVDTfcUI0ZM6Y67rjjqnnz5i21fP78+a09PAA6Scl9sTz77rtvNWbMmOqhhx5q9/fSvU488cRqn332WeK2yZMnVxtttFH105/+dInb/+d//qfaeeedW15PfuhDH6q23HLLaqeddqp+9atfVbfffnv1sY99rNp0002rv/71r932GF6r9feVwCqqVqvlwAMPzMKFC3PFFVcsc52JEyfmgQceyEYbbZTNN988SdK/f/9lrvvOd74zSfLkk08ucfugQYOy8847Z80112xztm222SYbbLBBarVam78HgK5Ral/suOOOGTdu3FJvE95www2z9957Z/78+fnTn/7Upm0BsHJK7YokOfvsszNo0KB89atfzWqrrbbU8oYGv5ABoLuU3BfL8sADD+Svf/1rNtlkk4wdO3altkV93HnnnUmSvfbaK83NzS3/7bTTTpkxY0amT5+e5NVfLTV37tycfvrpede73pWdd9455557boYPH57vfOc7dctveEGvduCBB6ZPnz654oorUi3js+sXFUlbft/bLbfckiRLvE0PgFVDT+uLRX8R5S+kALpPiV3x2GOP5e9//3t23nnnDBw4MLfeemsuuuii/PCHP8xjjz22UtsGoGNK7Ivl+cUvfpEkec973tMl26frzZo1K1VVZYcddsjYsWNb/vvgBz+YJC3Di9VXXz1JssMOO7R8b79+/bLtttvmb3/7W/cH/xevaOnVRowYkZ133jm33XZb7r777uy4444ty5qbm3P11VensbEx+++//1Lf+5vf/CZPPPFE5s2bl7/97W+5/fbbM3r06HziE5/ozocAQDfoSX0xe/bsTJgwIf3798/WW2/dJfcBwNJK7IqHHnooSbLGGmvksMMOy1/+8pcllu+33375yle+ksbGxpW6HwDarsS+WJa5c+fm17/+dVZbbbXst99+nb59uscaa6yRWq2Wn/zkJ+nXr99Sy1//+tcnSd74xjcudxuvvPJKl+VrjeEFvd7BBx+c2267LZdffvkShXHLLbdk5syZeec737nMt9ldd911mTBhQsvXm222Wc4555yst9563REbgG7WU/riC1/4QmbOnJlPfOITWWuttbrkPgBYttK64p///GeSV/8V7+jRo3PppZdm8803z+TJk3P66afnmmuuyfDhw/Pf//3fK3U/ALRPaX2xLNddd13mzJmT/fffv+Vf5dPzLDq+nn/++YwbN26567397W/P//7v/+auu+7KHnvskSRpamrKfffdl2222aZbsi6LXxtFr7f77rtnyJAhufHGG/PSSy+13H755ZcnWf7b9L71rW/l8ccfz3333ZdLL700/fr1y4EHHpi77rqrW3ID0L16Ql+cffbZufbaa7Prrrvm2GOP7fTtA7BipXXFwoULW/4855xzssMOO2TQoEHZdNNN83//938ZOHBgfvzjH6epqWml7geA9imtL5altSyUYd68ebnuuuty3XXXZdq0aZk9e3bL1//85z/z+te/Pu973/tywgkn5Pzzz8+dd96ZW2+9NZdeemmOO+64lu2MHTs248ePz6mnnprLL788t956a44//vjMnDkzRx99dN0en+EFvV6/fv1ywAEH5OWXX84111yTJJkxY0Zuu+22jBw5MjvttNMKv3/11VfPDjvskIsvvjirrbZaTjzxxMyfP787ogPQjUrvi29+85u56KKLssMOO+S8885L3759O23bALRNaV3xute9Lkmy7rrrLvVBq2uvvXa23HLLzJs3L0888USH7wOA9iutL17r73//e/7whz9k/fXXz/bbb99p26XzPffcc/nkJz+ZT37yk7n33nszffr0lq8nTpyYJPnc5z6XT33qU/nNb36Tj3zkIznhhBPy29/+Ntttt90S2/rqV7+affbZJ2effXY+/vGP54UXXsgll1ySjTbaqB4PLYnhBST59xR50VT5qquuSnNzc8uHKLXF4MGDs8UWW+SZZ57Jk08+2WVZAaifUvvim9/8Zs4///xst912ueCCC7Laaqt1ynYBaL+SumLR77FeNMR4rUW3v/zyyx2+DwA6pqS+eC3vuug5Ro8enccff3yZ/y0aPNVqtRxxxBG55ppr8tBDD+Wee+7JT3/603zgAx9YYlsDBw7M5z73udx111158MEH89Of/rTun6NoeAF59UNpttxyyzz88MN57LHHcsUVV6RWq+XAAw9s13aeffbZJElDg4+TAVgVldgXiw8uLrroogwYMGCltwlAx5XUFVtssUVWW221TJ06dZkftrnoHRejRo3q8H0A0DEl9cXimpubc9VVV6WhoSHvfve7O2Wb0FGGF/Avi6bJp512Wp544onstNNOS/0QP3v27Pz9739f5vdffvnleeCBB7LBBhtk/fXX7/K8ANRHSX1x7rnn5vzzz88222yTCy+80OACoBCldMWgQYNywAEHZO7cufn2t7+9xLIrr7wyf/vb37L11ltn2LBhHb4PADqulL5Y3KIPDX/rW9+aoUOHdso2oaNqVVVV9Q4BJZg9e3Z23XXXzJ07N0lyzjnnZO+9915inalTp2aPPfbIZpttlg033DDDhw/PCy+8kIceeigPP/xwBg8enIsvvjhvectblvi+r33ta5k1a1aS5I477sizzz6b8ePHZ+DAgUleLattttmmZf0bb7wxN954Y8t93nfffdl4442zySabJEk23HDDfOQjH+maHQHACpXSF1dccUVOPvnkNDQ05P3vf3/LOovbbrvt/I5agDoopSuSZNasWTn00EMzadKkbLfddtlss80yadKk/O53v8vqq6+en/zkJ3njG9/YlbsDgOUoqS8WOfbYY/O73/0u559/fsaNG9cVDxvazPACFnPyySfniiuuyJprrpnbbrstjY2NSyyfO3duLr744tx7772ZNGlSnn/++fTr1y+jRo3KzjvvnA9+8INZd911l9ruuHHjMm3atOXe75lnnrnE2wL/93//N+edd95y199uu+3ywx/+sAOPEIDOUEJftNYVSfLxj388xx9/fAceIQArq4SuWOT555/PeeedlxtvvDEzZ87MGmuskZ133jnHH3981ltvvc55wAB0SEl98cwzz+Ttb3971l577dxyyy3p27dv5zxI6CDDCwAAAAAAoCg+8wIAAAAAACiK4QUAAAAAAFAUwwsAAAAAAKAohhcAAAAAAEBRDC8AAAAAAICiGF4AAAAAAABFMbwAAAAAAACKYngBAAAAAAAUxfACAAAAAAAoiuEFAAAAAABQFMMLAAAAAACgKA31DkDXWrBgQebPn1/vGFAX/fr1S9++fesdA3oEfUFvpi+gbXQFvZmugLbTF/Rm+qJzGV6soqqqytNPP53nn3++3lGgrtZcc82su+66qdVq9Y4CRdIX8Cp9AcunK+BVugJWTF/Aq/RF5zG8WEUtKothw4Zl4MCBThZ6naqqMnfu3Dz77LNJkhEjRtQ5EZRJX9Db6Qtona6gt9MV0Db6gt5OX3Q+w4tV0IIFC1rKYu211653HKibAQMGJEmeffbZDBs2zNv24DX0BbxKX8Dy6Qp4la6AFdMX8Cp90bl8YPcqaNHvFRw4cGCdk0D9LToP/L5NWJq+gH/TF7BsugL+TVfA8ukL+Dd90XkML1Zh3p4HzgNoC+cJOA+gNc4RcB5AWzhPwHnQmQwvAAAAAACAohheULz//d//zUYbbdTy3/bbb5/DDjsst956a5fc35FHHpmPfvSjXbLtVdlrn6dF/+27775t+v5x48bl9NNP7+KUwKpKV/Qc+gKoJ33RM+gKoJ50Rc+hL1Z9PrCbVjXNX5Db//JU7n5oel6a25TXDWzMDpuNyC5bjExjv+750JnVVlstl156aZJXP/DmggsuyLHHHpsf//jH2WqrrbolA61b/Hla/DZg1acraA99Ab2XvqCtdAX0XrqC9tAXqzbDC1bonoem55yf/ilz5s1PrZZUVVKrJXc9OD0XXflgPn3YVtlu7LpdnqNPnz7ZcsstW77eYoststtuu+XKK69UGoupqoVpfmFmqqZ5qTUOSMMa66RW6743WL32eQJ6B13R8+gLoB70Rc+iK4B60BU9j76gKxlesFz3PDQ9Z3z/3qR69evqNX/OnTc/X77knpzyge2y/WYjujXb8OHDM2TIkDz11FMtt/3pT3/KOeeckwceeCB9+/bN2972tvy///f/svbaa7esc9ZZZ+XWW2/N1KlTM3jw4Gy77bY56aSTMmzYsG7N3xWaZk7NnMfvyfyZ07KwuSl9GhrTb51RGbTR9mlcZ3Tdcs2dOzdnnXVW7rjjjjz99NNZe+21s8suu+S///u/87rXvW653zdr1qwcc8wxqaoqF198cYYMGZInnngiZ511Vu69994sWLAg2223XT73uc/lP/7jP7rxEQGL0xU9j74A6kFf9Cy6AqgHXdHz6Au6ms+8YJma5i/IOT/9U1K1dMZSqn/9zzd/+qc0zV/QjemSOXPm5IUXXsjo0a9eCP/0pz/lyCOPzOte97qcc845+dKXvpQHH3wwxx133BLf99xzz+WjH/1oLrzwwpxyyimZNm1ajjzyyDQ3N3dr/s7WNHNqXrj312l6+u/pM/B16bf2yPQZ+Lo0Pf33V2+fObXbsjQ3Ny/x38svv5wFCxbkv/7rv/Kd73wnn/zkJ3Pfffct9dwsbsaMGXn/+9+fxsbGXHrppRkyZEimTJmSQw89NC+88EK++tWv5qyzzso///nPfOADH0hTU1O3PT7g33RFz6Mv9AXUg77oWXSFroB60BU9j77QF93BOy9Yptv/8lTmzJvf6npVktnz5ueOB57K27der0szLbqwP/vss/mf//mfDBo0KO9///uTJGeffXY222yznHfeeanVakmSMWPGZN99982tt96a3XbbLUly5plntmxvwYIFectb3pK3vvWtufvuu7PLLrt0af6uUlULM+fxe7Jw3otpWGe9lsdf6z8wtXXWS/PMKZnz+L3pt/bILn/b3ty5czN27Nglbvv617+e0047reXr5ubmjB49Oocffnj+8Y9/5PWvf/0S6z/11FP5wAc+kFGj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6QsAWqMrAGgLfQHQu3TZB3YDAAAAAAB0RIeHF48//nguv/zyzJ49u+W2l19+OV/4whey6667Zs8998xll13WKSEB6Ln0BQCt0RUAtIW+AOhdOjy8OP/883Puuedm0KBBLbd94xvfyM9+9rPMmTMn06dPz+mnn5477rijU4IC0DPpCwBaoysAaAt9AdC7dHh48cADD2T77bdv+aCk5ubmXHHFFXnzm9+cu+66KzfddFOGDBmSH/zgB50WFoCeR18A0BpdAUBb6AuA3qXDw4tZs2ZlxIgRLV8/+OCDmT17dg499ND0798/w4cPz+67757HHnusU4IC0DPpCwBaoysAaAt9AdC7dHh40bdv3zQ1NbV8fe+996ZWq2X77bdvuW3NNdfMrFmzVi4hAD2avgCgNboCgLbQFwC9S4eHF6NGjco999zT8vV1112X0aNHZ9SoUS23PfPMM1lzzTVXKiAAPZu+AKA1ugKAttAXAL1Lh4cXBxxwQB577LG85z3vyfve97489thj2XfffZdY5/HHH8/666+/0iEB6Ln0BQCt0RUAtIW+AOhdOjy8OOKII/KOd7wjDz30UP7whz/krW99a4499tiW5RMnTsxjjz2WHXbYoVOCAtAz6QsAWqMrAGgLfQHQuzR09BsbGxvzzW9+M7Nnz06SDB48eInla6+9dq688sol3roHQO+jLwBoja4AoC30BUDv0uHhxSKvLYpFhgwZkiFDhqzs5gFYRegLAFqjKwBoC30B0Dus9PAiSRYuXJiZM2emubl5mctHjhzZGXcDQA+nLwBoja4AoC30BcCqb6WGF1dddVW+973v5YknnsiCBQuWuU6tVssjjzyyMncDQA+nLwBoja4AoC30BUDv0eHhxXe/+92cddZZaWhoyDbbbJOhQ4emoaFT3sgBwCpEXwDQGl0BQFvoC4DepcNX+B/96EcZPnx4fvrTn2bdddftzEwArEL0BQCt0RUAtIW+AOhd+nT0G//5z39mr732UhYArJC+AKA1ugKAttAXAL1Lh4cXG2ywQV588cXOzALAKkhfANAaXQFAW+gLgN6lw8OLD3zgA7npppsybdq0zswDwCpGXwDQGl0BQFvoC4DepcOfefHud787zz33XA499NAcfvjh2XjjjTN48OBlrrvtttt2OCAAPZu+AKA1ugKAttAXAL1Lh4cXSTJ79uzMnj07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aXmS8jKVkKdefVGrqqrq9nsFAAAAAABYDp95AQAAAAAAFMXwAgAAAAAAKIrhBQAAAAAAUBTDCwAAAAAAoCiGFwAAAAAAQFEMLwAAAAAAgKIYXgAAAAAAAEUxvAAAAAAAAIpieAEAAAAAABTF8AIAAAAAACiK4QUAAAAAAFAUw4sOmDRpUg499NCMHz8+Bx10UCZOnLjS2/zyl7+ccePGZaONNsqjjz7apvvq6mXvfve7c9RRR2X8+PHZf//988EPfjCTJ09Okjz33HM5+uijs9dee2XffffNfffd17KN7lr2oQ99KPvtt18OOOCAHH744XnkkUfqvs8WLfvlL3+ZjTbaKDfeeGMx+2vcuHEZP358DjjggBxwwAH5zW9+U8T+euSRR3L66adnr732yn777ZfPfvazdc91wAEH5B3veEfLvho/fnw23XTTPP/880U8l/QcXdEXSfLKK6/kuOOOK+L6/Fr1vv4t0tTUVMS1ZXG33npr3v3ud+eAAw7Ivvvum1/96lfduo9K/Fljxx13zK677rpEphUd3129v7bZZpuMHTt2qX20yGuP7+58/lh16Yr65imtL+rdFUl5r0232WabbLbZZsV0xV577ZXtttsuO++8s76gW+kLfbG4evdFaV3htcUq3BUV7XbkkUdWv/zlL6uqqqrf/va31YEHHrjS27z33nur6dOnV29/+9urRx55pE331dXLrr766mrPPfesFi5cWFVVVf3whz+sjjjiiKqqquqkk06qvvWtb1VVVVV/+ctfql133bVqamrq1mUzZ85syX399ddX++23X9332W9/+9tq3333rd773vdWhxxySHXDDTcUs7/e9ra3LXFsdec+WdGyHXfcsTr99NNbjrNnn322iFyLL7v44ourj370ox3a7125jPJ1RV9UVVW9/PLL1S233FLE9XlxU6ZMqfv1b5EzzjijiGvLIgsXLqy23Xbb6tFHH23ZV5tttln10ksvdds+uvPOO4v7WeN///d/q/3222+JTCs6vjt7n7x22b333lvdfPPN1cYbb1w98MADSzyHyzq+uzrPspax6tEV9c1TUl+U0BVNTU3FvTa99957q8suu6waO3ZsEV1RVVV12WWXVTvttNMyX2PpC7qKvtAXi5TQF15beG3RXQwv2mnmzJnVW97ylmr+/PlVVb16wdhpp52qSZMmdcr2Fz/BVnRf3b2sqqrqgQceqN7+9rdXVVVVW265ZcuFuqqq6qCDDqruuOOOuiyrqqr65S9/We2///5132fNzc3V2LFjq+uvv7464ogjWi5AJeyvHXfccakfrOu9v2bPnl1ttNFG1cMPP1xUrtce++94xzuKei4XP/YpV1f3xeLqeX1eZMGCBdVRRx1VPfjgg3W9/lVVVc2ZM6d6y1veUr300ktLZKzH9WORhQsXVtttt1117733VlVVVY8++mi1yy67VK+88kq376MSf9bYddddlzlgr6olj++u2ievXTZ27Njqsssua/l6ecd3d+Vx7V916Yr6dUVVldcXJXVFVZXXFxtvvHF10003VctSj65Y1mssfUFX0Rf6otS+KK0rvLZo37KeoKHe7/zoaaZPn56hQ4emoeHVXVer1TJixIg89dRTWX/99bvtvl73utd167L1118/P/jBDzJu3LjMmjUr8+fPz9ChQ1uyjho1Kk899VS3LzvhhBNyzz33JEkuuuiiuu+z73//+1lrrbUyePDglqyl7K8pU6bkhBNOSJJsvvnm+exnP1v3/TVlypQ0NDTkO9/5TiZPnpzVVlstxx9/fLcf3yta9txzz+XFF1/M2972tmKey6eeeiqUrzv7ol7X58Vdcskl2WqrrbLZZpu13FavPE8++WTWXHPNXHDBBbnzzjvrdm1Z/Hmu1Wo555xz8vGPfzwDBw7MCy+8kPPOOy9z5syp67Wj3j2w+LLlWXR8J913TPXt2zfPPvtsy9fLOr67M49r/6pLV9T3PCqtL0rtiqSMvnjttXlx9eiKRa+xFqcv6Cr6Ql/0hL4ooSu8tmj7sp7CZ17QJhdccEGefPLJfOYzn6l3lCV8/etfz6233ppPfepTOeuss+qa5a9//Wuuv/76DBs2rK45lufDH/5wrrnmmlxxxRVZa621cuKJJ9Y7UhYsWJD58+dn1KhRueKKK/K5z30un/rUp7JgwYJ6R2tx+eWX54ADDmgpQyhNCdfnRde/j33sY3XLsLgFCxZk2rRpeeMb31jMtaW5uTnnn39+zjvvvPzud7/L97///ZxwwglFXe9K5PiGzuFcWrbS+kJXdEwJx3dS5jEO7VXC+VTiuaQvVg2O757J8KKdRowYkRkzZqS5uTlJUlVVpk+fnpEjR3brfXXnsjvuuCPXX399vvOd72TAgAFZa6210tDQkBkzZrRknTZtWkaOHNntyxZ597vfnXvuuSfrrrtu3fbZ/fffn2nTpuWRRx7JiSeemD//+c859dRT89vf/raI/bXpppsmSfr165ejjjoq999/f92PsREjRiRJDjzwwCTJpptumtGjR2fatGlFHPtrrbVWfvvb3+aggw5KkiKPfcrVHX3x3e9+t67X50UWXf/Gjx+fcePG1e36t8iIESPSp0+f7Lfffknqd21Z3KOPPppnn3022267bZLkzW9+c4YPH57HH3+8rteOevfAomXLGhC/9vhOuu86vGDBgpZ/jLC84/snP/mJaz8rTVfUryuS8vqi1K5YtK/q3ReLX5sXqWdXTJs2LX379m35Wl/QlfSFvugJfVFCV3ht0fHnr1SGF+209tprZ+zYsbn66quTJBMmTMjw4cM7/W16rd1Xdy3r27dv7rzzzlxyySVZffXVW7K94x3vyE9/+tMkyQMPPJBnnnmm5aLZHcumT5++xD6/8cYbs+aaa9Z1nx1++OH53Oc+l0022SS///3vs+WWW+ZLX/pSDj/88Lrvr6effjobbbRRy/769a9/nU033bTux9i9996bQYMGtbzdesqUKZk6dWq23nrruh/7w4cPz4MPPpiNN944b3jDG4o59hdfRtm6ui8uueSS/PrXv6779TlJDj/88Nx+++25+eabc/PNN9f1+pckQ4YMyY477pjbb789Sf2uLYsbMWJEnn322TzxxBNJksmTJ2fKlCl5/etfX9drR717YNGy177AWN7x3VX75LXLFixYkLFjxyZZ8fHdXXlc+1dduqJ+XZGU1xeldkVSRl/07du35R8/JfXvimeeeSb9+/dvuU99QVfSF/qiJ/RFCV3htcUq2BWd/ikavcATTzxRHXLIIdVee+1Vvfvd764ee+yxld7mqaeeWu26667VJptsUu24447VHnvs0ep9dfWyfffdtxozZky1++67V/vvv3+1//77VwcffHBVVVU1Y8aM6oMf/GC15557VnvvvXd11113tWyjO5Zdc8011UEHHVTtu+++1X777VcdddRRLR/GU899tviyxT90p97766qrrqoOOOCAat9996323Xff6thjj62mTJlSxP665ZZbqiOOOKLlubzuuuuKyPXYY49V733ve6vLL7+8Wly9n8vFl1G+ruiLqqqq6dOnF3N9XpZ6Xv8WefLJJ4u4tizummuuacmz7777VldffXW37qMSf9bYfvvtqx133HGJTCs6vrt6f2211VbVJptsUm288cZL7KPFvfZD9Uo45+jZdEV985TWF/Xuiqoq77XpVlttVW266aZLXJvr2RV77rlntc0221Tbb7/9UvtocfqCzqYv9MXi6t0XpXWF1xarblfUqqqq6j1AAQAAAAAAWMSvjQIAAAAAAIpieAEAAAAAABTF8AIAAAAAACiK4QUAAAAAAFAUwwsAAAAAAKAohhcAAAAAAEBRDC8AAAAAAICiGF4AAAAAAABFaah3AKiXz3zmM7n22mtz9tlnZ999913uerNnz87OO++cfv365fbbb8/111+fCRMm5PHHH89zzz2XJBk5cmR23nnnHH300Rk+fPgS3z9v3rxcdtllefjhh/Pwww9n0qRJqaoqN910U0aPHr3c+7377rvz3e9+N3/9618za9asDBs2LFtssUU+/OEPZ+ONN+6cnQBAq0rvi2uuuSY//vGP8/jjj6eqqrzhDW/I+973vhx44IGdswMAaFV3dcWjjz6aCRMm5M4778yUKVPy0ksvZfjw4dl1113zsY99bKn1F/nHP/6Rb37zm7n77rszb968bLDBBjn00ENz2GGHpVardd6OAGCFSu6Lm2++OXfccUcefvjhPPbYY5k3b14+/vGP5/jjj+/cnQDt4J0X9FoHH3xwkuSXv/zlCte79tpr8/LLL2efffbJaqutlt/85jd54oknssUWW+TQQw/Ne9/73qyzzjr5wQ9+kH333TcTJ05c4vufe+65fO1rX8u1116bpqamrLHGGq1m++EPf5ijjjoqf/7zn7Pzzjvn/e9/fzbeeONcd911Ofjgg3PnnXd2/IED0C4l98VXv/rVfPazn83UqVOz33775cADD8zzzz+fk08+OV/72tc6/qABaJfu6oovfOELOf/881NVVfbZZ58ceeSRWXfddXPZZZflgAMOyBNPPLHUff7tb3/Le97zntx0001561vfmiOPPDILFy7Maaedli9/+cudtxMAaFXJfXHJJZfkRz/6USZOnJhhw4Z13oOGlVFBL7Vw4cJq3Lhx1cYbb1xNmzZtuesdfPDB1ZgxY6oHHnigqqqqevnll5e53s9//vNqzJgx1fHHH7/E7bNnz65uv/32atasWVVVVdWHPvShasyYMdWUKVOWuZ2mpqZqq622qrbaaqvqqaeeWmLZ9ddfX40ZM6Y68sgj2/owAVhJpfbFAw88UI0ZM6bac889W76nqqpqzpw51UEHHVSNGTOm+uMf/9iORwpAR3VXV/zgBz+oJk2atNT6F154YTVmzJjqwx/+8FLL3ve+91VjxoypbrnllpbbXnnllerwww/XFQDdrOS+uO+++6p//OMf1cKFC6trr722GjNmTPWtb32rPQ8POp13XtBr1Wq1HHjggVm4cGGuuOKKZa4zceLEPPDAA9loo42y+eabJ0n69++/zHXf+c53JkmefPLJJW4fNGhQdt5556y55pptyvX8889n9uzZedOb3pQRI0YssWy33XZLrVbLrFmz2rQtAFZeqX1x0003JUmOOuqoJb5n4MCBOfbYY5MkP/3pT9u0LQBWTnd1xZFHHpn1119/qfWPPvrorLbaarnvvvuWuP0f//hH7rvvvmy//fbZbbfdWm5vbGzMJz/5ySTJz3/+8zY+SgBWVql9kSTbbLNNNthgA79OkKIYXtCrHXjggenTp0+uuOKKVFW11PJFRbLobX0rcssttyRJ3vSmN61UpnXWWSdrrbVWJk6cmOnTpy+x7NZbb01VVdlhhx1W6j4AaJ8S+2LmzJlJsszPw1h02913371S9wFA29WzK2q1WhoaGtK3b98lbr/33nuTJLvssstS37P11ltn4MCBy/wLLAC6Tol9AaXygd30aiNGjMjOO++c2267LXfffXd23HHHlmXNzc25+uqr09jYmP3333+p7130+wbnzZuXv/3tb7n99tszevTofOITn1ipTLVaLZ///OdzwgknZP/998+ee+6ZIUOGZNKkSbnlllvyjne8I5/61KdW6j4AaJ8S+2KttdZKkkydOnWpZYtue/rppzNv3rwMGDBgpe4LgNbVsyuuu+66zJ49O+94xzuWuH3SpElJssx/fdu3b9+MHj06f/vb39Lc3JyGBn89ANAdSuwLKJWfTuj1Dj744Nx22225/PLLlyiMW265JTNnzsw73/nOZf4Kj+uuuy4TJkxo+XqzzTbLOeeck/XWW2+lM+29994ZMmRIPvOZzyzxIU5jxozJu971rgwaNGil7wOA9imtL9761rfmoosuyg9+8IPst99+WX311ZMk8+bNy0UXXdSy3ksvvWR4AdBN6tEV06dPzxlnnJHVVlut5VdBLTJ79uwkyete97plfu+gQYOycOHCzJkzJ2ussUZbHiIAnaC0voBS+bVR9Hq77757hgwZkhtvvDEvvfRSy+2XX355kuW/Te9b3/pWHn/88dx333259NJL069fvxx44IG56667VjrTL37xixxzzDHZd999c+ONN+bPf/5zrrjiigwbNizHHntsfvzjH6/0fQDQPqX1xbbbbpsDDjggkyZNyt57753Pf/7z+dKXvpT99tsvM2bMaPmLqj59/LgH0F26uytmzZqVj3zkI3nuuedy+umnZ8MNN+y8BwNAl9EX0DZezdLr9evXLwcccEBefvnlXHPNNUmSGTNm5LbbbsvIkSOz0047rfD7V1999eywww65+OKLs9pqq+XEE0/M/PnzO5zniSeeyBe/+MW87W1vy8knn5z11lsvAwYMyNixY3Peeedl+PDhOfvss/PKK690+D4AaL/S+iJJvvrVr+aUU07JkCFD8qtf/SpXX311Nt988/z4xz/OggUL0tDQ4F/SAnSj7uyKWbNm5QMf+EAmTpyYL37xiznggAOWWmfw4MFJssRfjC1uzpw5qdVq3tkN0M1K6wsoleEF5N8T7UUT7quuuirNzc0tH6LUFoMHD84WW2yRZ555Jk8++WSHs9x5551pbm7O9ttvv9SyAQMG5M1vfnPmzJmTyZMnd/g+AOiYkvoiefVdFe9///tz9dVX58EHH8x9992Xc845JwsXLszcuXOz0UYbpV+/fit1HwC0T3d0xaK/iHrsscdy6qmn5tBDD13mdjbYYIMkWeZrhwULFmTq1KkZPXq0z7sAqIOS+gJKZXgBSd74xjdmyy23zMMPP5zHHnssV1xxRWq1Wg488MB2befZZ59NkpX64X/RpPyf//znMpcvur2xsbHD9wFAx5TUFyuy6F9v7b333l2yfQCWr6u74rV/EfW+971vudvYdtttkyS33377Usv+8Ic/ZO7cuS3rANC9SuoLKJXhBfzLoon3aaedlieeeCI77bRTRo0atcQ6s2fPzt///vdlfv/ll1+eBx54IBtssEHWX3/9DufYaqutkiQ///nP88wzzyyx7NZbb80f//jHjBgxYqXuA4COK6UvFt3Pa91///256KKLMmrUKP+yCqBOuqornn/++Xzwgx/MY489llNOOSVHHHHECnNsuOGG2XbbbXPPPffk1ltvbbm9qakp5557bpLkPe95T4ceIwArr5S+gFLVqqqq6h0CSjB79uzsuuuumTt3bpLknHPOWepfrE6dOjV77LFHNttss2y44YYZPnx4XnjhhTz00EN5+OGHM3jw4Fx88cV5y1vessT3fe1rX8usWbOSJHfccUeeffbZjB8/PgMHDkzyallts802Let/5jOfybXXXptBgwZlzz33zDrrrJMnnngit9xyS/r06ZNvfetb2WOPPbpydwCwHCX1xYc+9KG8/PLL2WijjTJ48OD89a9/ze9///usscYaueSSS7LJJpt05a4AYDm6qiuOPPLI3Hvvvdlwww2X++66o446KquvvnrL1xMnTsxhhx2Wl19+OXvvvXeGDh2aW2+9NRMnTswRRxyRU089tQv2AABtUVJf3Hjjjbnxxhtb7vO+++7Lxhtv3PKaYsMNN8xHPvKRTn380BrDC1jMySefnCuuuCJrrrlmbrvttqV+NdPcuXNz8cUX5957782kSZPy/PPPp1+/fhk1alR23nnnfPCDH8y666671HbHjRuXadOmLfd+zzzzzCXeFrhw4cL/394doioURlEY3c7AYBEMDkEM5jsMMQtOR9AZiMEkdwAOwCkYxFHIH182PB6KD05YK/7cstMJX7g5nU7p+z632y2ttQyHw8zn86zX68xms69tBuB9Ve7F8XjM+XzO4/FIay3j8Thd12Wz2WQ0Gn1vMABv+49b8dedSJLL5ZLJZPLydr/fs91uc71e83w+M51Os1wus1qtMhgMvjMYgI9UuRe73S77/f7X7xeLRQ6HwwcL4XPiBQAAAAAAUIp/XgAAAAAAAKWIFwAAAAAAQCniBQAAAAAAUIp4AQAAAAAAlCJeAAAAAAAApYgXAAAAAABAKeIFAAAAAABQingBAAAAAACUIl4AAAAAAACliBcAAAAAAEAp4gUAAAAAAFCKeAEAAAAAAJQiXgAAAAAAAKX8ACgTp5BeSmJIAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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Xj117dpV//rXv/TFF19oxYoVqlu3rvr162dc1oULFyRJ5cqVu6YYAEDxwEQmAEChuf3227V161alp6fryJEjatCggdPj586d0wcffKB169bp0KFDSk1NVYUKFRQTE6Nu3bopOjo6x3L37dunNWvW6IcfftCJEycUHx8vHx8fVa9eXa1bt1b37t0VGhpaFF0EgHxJTEzUkCFDnLZd+f+CBQt06623ym63KzMz0ymmT58+ysrK0ty5c3XmzBnddNNNevfdd3XjjTc6Ynx9ffXOO+9owoQJGjZsmHx8fHTnnXdqzJgxhd8xAAA8JD09XZs2bdKGDRv0888/Kz4+XklJSQoMDFSDBg3UuXNndezY0elqblNnz55V//79tXPnTlWtWlXvvvuu0+0szpw5o/nz52vjxo06duyY0tLSFB4erltvvVU9e/ZUnTp13NlVAMgTuQYAoCQrW7asJk2apEOHDmnv3r2aM2eOHn74YcfqSt999526desmSfrvf//r2K9evXpO5YwePVqjR492/H/dunVq3769U8yVcq74c3lSwcb5V7dv7969evfdd/XDDz8oMTFRMTExWrhwoSM+LS1Nixcv1urVq7Vv3z6dP39eQUFBioqKUteuXXNd8fBKfxcsWKCbb75Zb7/9ttasWaMTJ06obNmyaty4sQYMGKBbbrklx/2v2Lx5s5YsWaKdO3cqMTFRZcqUUaVKldSsWTN16tQpx99mCtpmACgIJjIBAApNVlaW499Xf1H2yy+/qH///jp58qSky1dflClTRidPntTKlSu1atUqDR06NMerLvr376/jx49Lunz1YNmyZZWcnKxffvlFv/zyi/79739r3rx5ioyMLMTeAShWLMX/CmlJqlatWrYvR6725y81rvDy8lK/fv1cXolWqVIlzZgx45raCABASbJ9+3YNGDDA8f+AgAD5+fnpzJkz2rx5szZv3qyvvvpKr732miwWi3G5x48fV+/evXXw4EHVr19fb7/9tsLDwx2Pb9myRUOGDJHNZpN0+Ud+X19fxcXFKS4uTsuWLdOECRP0t7/9zW19BeBBJSDfINcAAJR0fn5+6tevn4YMGaJz585p7dq16tKlS577hIWFSbo8+chutysgIEBlypRxPO7t7e2IOX36tCQpKChIvr6+OZbnjnH+mjVrNHz4cKWnpysgIEDe3t5Ojx8/flz9+vXT/v37JV3+LA4ICNDp06e1fv16rV+/Xl27dtXzzz+fax0JCQl64IEHdOTIEfn7+8tisSgpKUkbNmzQN998o1mzZqlly5bZ9rtw4YKefvppp9v0lS9fXna7Xfv27dO+ffv0448/6vPPP3d7mwEgP5jIBAAoNJs3b5Z0eVBbrVo1x/b4+Hj16tVLiYmJuuuuu9SvXz/Vq1dPvr6+SkxM1Pvvv685c+bo1VdfVa1atXTHHXc4ldu0aVMNHjxYt956q6pUqSLp8tUA27Zt06uvvqrdu3drxIgR+uyzz4quswAAAACKXNmyZfXwww/r7rvvVlRUlAICAiRJSUlJWrZsmaZPn67Vq1crNjY225XXufn111/Vp08fxcfH69Zbb9Vbb73lKFe6fIX1//3f/+nixYv6+9//rh49eqhmzZry9vbWiRMn9Pbbb+uDDz7Qv/71L9WqVUuNGjUqlL4DAAAApc3tt98ub29vZWZm6ocffnA5kembb76RJLVr107Hjx/Xv/71Lz3wwAM5xlxZzWjGjBm69dZbs5XlrnH+008/rb/85S8aNWqUatWqJUk6fPiwJCk1NdVxwUSzZs00ePBgNW7cWH5+fkpJSdGSJUs0ffp0ffTRR4qMjFT37t1zrOOFF15QxYoVNX/+fDVr1kxeXl766aef9M9//lOHDh3S2LFjtXbt2mwXc4wePVqrV6+WxWJRr1699I9//EOVK1eWdHky2DfffKMff/zRaR93tRkA8oOJTAAAtztx4oRmzpyprVu3SpLatm2rkJAQx+PTpk1TYmKiOnXqpKlTpzrtW6FCBQ0ZMkRBQUGaOHGiZsyYkW0i0+TJk7PV6efnp+bNm2vevHm666679PPPP+vHH39UkyZNCqGHAIobLy/zFRYAAEDJ0aJFi1wfmzdvnqKiohQVFZXtseDgYHXr1k3h4eEaMmSIFi5caDSR6fvvv9eAAQOUkpKiu+++Wy+//LL8/PycYl566SVdvHhR/fr107Bhw5weq1Klip577jl5e3tr4cKFmjlzpt566y3D3gIorsg3AAAoGuXLl9eNN96ow4cP6+jRo0Vat7vG+bVr19bMmTOdVmKqWbOmJOm9995zTAiaO3eu08pQgYGB6tGjh6pWrapBgwZp5syZeuyxx+Tjk/3nfG9vby1YsEAVKlRwbIuKitL06dP117/+VcePH9eOHTsUGxvrePzbb7/VqlWrJEnPPvusHn30UacyQ0NDdd999+m+++5z2u6uNgNAfpCBAQCuWYsWLRx/jRs3Vtu2bfXJJ59IkiIjIzVu3DhH7KVLl7RixQpJUp8+fXIt8/7775d0+WroK0u+mihfvryaNm0q6fJtJgAAAACUXKdPn871LyMjw+X+bdq0kSQdPXpUCQkJecauXr1avXr1UkpKiv7xj3/otddeyzaJKS4uTlu3bpWPj4+eeOKJXMu6cquJb7/9NttttgEAAADkLigoSJKUnJxcZHW6c5zfq1evbLeTu2LJkiWSpB49euR6e7s77rhDAQEBOnv2rH7++eccY/7+9787TWK6ol69eo67Y1x9y9lPP/1UklS3bt1sk5jy4q42A0B+MB0SAHDNcpto9Le//U0vvPCC/P39Hdv27NmjS5cuSbo8oDdx4sQJx32sr/j666/1+eef66efflJiYqIuXLiQbb+TJ0+adgFASWfx8nQLAABAIbj6y/ecnDt3Th999JE2bNig3377TSkpKUpPT88Wd/LkSVWsWDHHMhYtWqQJEybIbrdr6NCh6t+/f45xVy6WsNvt6tixY65tuvKjRmpqqpKSknL8kQFACUK+AQBAqebOcX5MTEyO+546dUrHjx+XJP3rX//S2LFjc60nNTVVknT8+HHdcsst2R7PadsV4eHhiouLyzYRbMeOHZL+uNjDhDvbDAD5wUQmAMA1u/LjQlZWlhISErR+/XpNnTpVS5cuVd26dZ0mLMXHxzv+bbrS0p8nKdntdo0cOdKxqpMk+fj4KCgoyHE1QEpKii5dupTj5CYAAAAApcehQ4fUo0cPp4sYypYtq8DAQFkslxciv5J35JUfvPDCC5Kkxx57LNdJTNIf+Yzdbi9QPgMAAAAgb1cm4AQHBxdZne4c5+d2EcOpU6cc/z579qxRHRcvXsxxe/ny5XPd58pt3a5ewfZKv6pUqWJUt+TeNgNAfjCRCQDgNl5eXgoPD1fXrl0VERGh7t276+WXX1aDBg3UvHlzSZcTgSt2797ttFqTiU8//VQrVqyQt7e3+vfvr/vvv1833nij40cKSRo5cqSWLVumrKws93QMQPHnxRXSAABcj0aPHq2TJ0+qatWq+uc//6nbbrvN6QePzMxMNWjQQJLyzA/++te/atmyZfrkk0/UsmVLtWvXLse4K/lMWFiYvvnmG/d1BEDxRr4BAECROH/+vI4dOyZJql69epHV685xfm63lfvzbyMrV65UrVq1rqme/PIqwHjG020GcP2yuA4BACD/br31Vt1///3KysrShAkTHEuu/vkWcVeWJM2PL774QpLUpUsXPfnkk6pRo4bTJCbJfKUnAAAAACXX77//7rg9wquvvqq7774721XbprnB5MmT1blzZ6Wnp+vJJ5/U2rVrc4y7ks+cPXvWcesEAAAAAO7xn//8x/FbQrNmzYqs3qIY5//5t5ETJ04USh0m9eenbk+3GcD1i4lMAIBCM3DgQHl7e+vAgQP697//LUlq1KiR4xZwX3/9db7LvHLLiCtXVV/t/Pnz2rVrVwFbDKDEsliK7g8AABQLv//+u+PfueUHW7ZsMSrLYrHopZde0oMPPqj09HQ99dRTWrNmTba4mJgYSZdXetq0aVMBWg2gRCLfAACg0KWlpWn27NmSpMDAQN1xxx1FVndRjPOrVaumSpUqSSrYbyPXKjo6Ot91e7rNAK5fZEYAgEJTvXp13XPPPZKkt956S+np6SpXrpzuu+8+SdLbb7/tchZ/UlKS0/8DAgIkSb/++muO8W+99ZbOnz9/jS0HAAAAUNwFBgY6/p1TfnDu3DnNnDnTuDyLxaIXX3xRDz/8sNLT0zVs2DCtXLnSKaZmzZqOK8Nfe+01paSk5Fnm1fkMAAAAgOwuXryo0aNHa+/evZKkvn37ymq1Fln9RTXO//vf/y5J+vTTTx19dXcduenSpYskaf/+/frggw+M9/NkmwFcv5jIBAAoVP369ZOXl5eOHz+uTz/9VJI0dOhQhYeH6+zZs3r44Ye1dOlSnTt3zrHPmTNntGbNGg0cOFDDhw93Ku/222+XJC1evFgff/yx0tLSJEkJCQl66aWX9M4772S7nQQAAACA0qdWrVqqUqWKJGnMmDHas2eP47EdO3aoW7duSk5OzleZXl5eev755/Xoo48qIyNDI0aM0IoVK5xinn32WZUrV06HDx/W3//+d61du1aXLl1yPH7q1CktXbpU3bt31yuvvHINPQQAAABKL7vdrn379um9995Tx44dHePu+++/X3369Cny9hTFOL9nz56qW7euLl26pG7duun999/X2bNnHY/bbDZt3LhR//znP/XYY49dc5/+7LbbblPHjh0lSePHj9fUqVMdd8CQLv8us3jxYo0Z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y7asbWELCgqSzWZz2hYcHKyMjAwlJibmOuAPCgpSYmJitu2JiYlOxyk/UlJSnK7SAAAAwPWHfOMy8g3yDQAAALgXucZl5BrkGgAAAMVBod/c++LFi/L19XVKBJYvX37N5VaqVElPPPGE6tWrp4MHDxrXFRkZqcqVK+uzzz7LteycrijISWxsrCRp9erVTttXr16tBg0aqFy5csb9Wbt2rS5evKjnn39eCxYscPrr3LmzNm/e7Lji4lr4+voaz/6PiIhQXFyc07bbbrtNXl5eWrJkSa77xcbGat26dcrIyHBs++abb2Sz2RzHLD/sdrtOnDihiIiIfO8LAACuExavovtDsUK+YYZ8I3fkGwAAwCXyjesSuYYZco3ckWsAAAAUjFtXZMpJixYtNH/+fI0fP1533nmnduzYoc8//7xAZY0dO1ZWq1WNGzeW1WrV9u3b9euvv+qRRx4xrsvLy0ujRo3SsGHDNHjwYN1///3y8/PTzp071ahRI7Vt21Y1a9aUt7e3lixZIh8fH3l7e6tRo0bZ2lO/fn3dddddmjRpki5evKiIiAgtW7ZMO3bs0FtvvZWvvi1fvlxVq1bVww8/nO3qj6CgIP373//W6tWr1bVr13weNWeRkZFaunSp1q9fr4oVKyo8PFyVKlXKMTYmJkarVq1y2hYREaGuXbtq+vTpSk5OVvPmzXXx4kVt2LBBgwcPVqVKldS/f3917dpV/fr10+OPP67Tp09r6tSpioqKyvE+464cOnRIqampatKkSYH6DAAAgNKLfMMM+UbuyDcAAACQE3INM+QauSPXAAAAKJhCn8jUunVrjRgxQu+//74+++wzxcTEaPbs2erQoUO+y4qOjtYnn3yixYsX68KFC7rxxhs1evRoPfTQQ/mq695771WZMmU0a9YsDRs2TP7+/mrQoIHuvPNOSVJoaKjGjh2rd955R8uWLVNGRob++9//5timl19+Wa+++qrefvttJSUlKTIyUq+//rratWtn3K/ExER9++236tu3b45L2NavX1833XSTli9ffs2D/T59+ujo0aMaNWqUbDabBg0apMGDB+cY26FDB82ePVuHDx9WzZo1HdvHjh2ratWqafHixZo/f76Cg4PVtGlTxz3EGzZsqLlz5+rVV1/V4MGDVa5cObVr106jRo2St7d3vtu8adMmVa1aNceECwAAQJLkVegL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bNgwx0D/aj/++KMCAgIcA31J8vX11Z133qkVK1Y4xdavX9/p3tC1a9eWpGyD/ZCQEJ09e1bp6ekFulIDAACUcgUYFxW1rl27auHChRo4cKD69eunU6dOacqUKeratasqVarkiOvevbtOnDihr776ymn/vXv36rffflPPnj1zLH/EiBGqUaOGGjRoIH9/f23dulXz5s3THXfcwQ8LyDdyDQAAgD8h3yDfgFuRbwAAACAvTGQqgYKDg+Xv7+9Y7tTUxo0bNXbsWA0YMECdO3d2GX/p0iX5+fk5bbPZbLLb7XlelWOz2VShQoVs28PCwpScnOy07crVQVdcGchfunTJafuVdly6dInBPgAAKJGCgoI0f/58jR8/XgMHDlT58uXVpUsXDR061CnObrcrMzMz2/7Lly+Xn5+fOnTokGP5derU0fLlyzV37lylp6eratWq6t+/v/r27Vso/UHpRK5BrgEAAEom8g2UBOQb5BsAAAAmmMhUAvn4+CgmJkZbt25VRkaGfHxcP407d+7UkCFD9Le//U1DhgwxqicoKEgpKSlO2wIDA2WxWBQfH5/nfomJidm2nz59WkFBQUZ1X81ms8nX11cBAQEF2h8AAJRuXpbif4W0JNWqVUvz5s3LM2bhwoU5bh81apRGjRqV6379+vVTv379rqV5ALkGAABADsg3yDfgHuQbAAAAMGHxdANQMD179lRCQoJmzZqV4+MbN250/PvAgQPq16+fbrvtNj3//PPGdUREROjMmTNKTU11bCtXrpwaN26szz//PMcrdyQpNjZW586d0+bNmx3bMjIytHbtWsXGxhrX/2fHjx9XREREgfYFAAAAYI5cAwAAAEBhId8AAACAK6zIVEK1bt1avXv31owZM3TgwAF17NhRISEhiouL05IlS5SSkqLWrVsrMTFRvXr1kr+/v7p37649e/Y4yggICHDctzknMTExstvt2rt3r5o0aeLYPnz4cPXo0UM9evTQo48+qqCgIP38888KCQlRly5d1KZNG0VFRWnkyJEaPny4wsLCtHDhQsXHx+v1118vUH/37NlT4EQBAABcB7yYnw+4C7kGAADAVcg3ALch3wAAAIArTGQqwUaOHKno6GgtWrRIY8aM0YULFxQeHq6WLVuqV69eki5fsXDy5ElJUo8ePZz2b9asWa5LCUuXr1qoW7eu/vOf/zgN9ps0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//33unTpkmrUqKG+ffuqU6dOkqRLly7p1Vdf1RdffKHk5GRFRkZq0KBBuvPOOx1lPP3009qzZ4+effZZTZw4UYcPH1bt2rU1btw4NWz4x0SSqlWrKioqSp999pnGjBmT7z4AAIDrhOkvwwBcIt8AAAC4CvkG4DbkG/lncuFEnc1rlHzkqMu4oBrVZUtIcBlnrVjRuF7TOJvBBc7WqlWMyzu9boPLuLD2bZRis7mMC7Ra3d7f02vWum5fhzvcVm9+2mZ8Th085DIuKDJCSfv2u4wLrlvH+LkwjbOddH0Bu7VyZePyko8ecxkXVP1G4zjT42J6nJPj4lzHVaumpAMHXddbO9L4vSDpl19dl3dTfdlOxbsur1K40eITgSEhLp9fa+XKxn0wrdPd52hKUpLruOBgpZw54zouNNS8XtP+nj7tOi4szLw80/66+/i5+flF8cCauCVMRkaGtm/frttuu02+vr55xsbFxSkhIUEhISHq37+/GjZsqGbNmumZZ57R+fPn89z3yJEjOn78uGJiYpy2Hz58WA8//LCOHDmif/3rX5o5c6YeeOABnTjxxwB0xIgR+vjjj9W7d2+9+eabql27tgYPHqx169Y5lZWQkKAJEyaoV69emjZtmi5duqRBgwYpPT3dKS46OlpbtmwxOTwAAAAArgH5BgAAAIDCQr4BAAAAE6zIVMIkJSUpLS1NVapUcRl7+n+zKCdPnqy77rpLb7/9tg4fPqypU6cqNTVVr776aq77/vTTT5KkevXqOW2fMWOGfH199eGHHyogIECS9Je//MXx+K+//qovv/xSzz//vLp2vXxbtVatWun48eN688031b59e0dscnKy3n//fdWpU0eSVLZsWXXr1k27du1SkyZNHHH169fXggULdO7cOUedAAAATjx0exOgtCHfIN8AAAA5IN8A3IJ8g3wDAADABCsylVBeBsmz3W6XJEVERGjy5Mlq3ry5HnnkEY0aNUpffPGFjh3LfenDhIQEWSwWhYSEOG3funWrOnTokOuAe9u2bZKku+++22n7Pffco7179yo1NdWxLTw83DHIl6TatWtLkk6dOuW0b0hIiLKyspSYmOiqywAAAADcgHwDAAAAQGEh3wAAAEBemMhUwgQHB8vf399pqdPcBAUFSZJuvfVWp+233XabJGn//tzvzXrp0iX5+PhkSyiSkpIUHh6e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FRMTo1q1amnXrl36/PPPc00Urti5c6dSU1MVGxvrtH3btm3q3r27GjdurAkTJshqtWrPnj06ceLyB2hmZqb69OmjY8eOacSIEQoLC9PChQvVs2dPffTRR2rYsKGjrF9++UVnzpzRiBEjlJmZqUmTJmnkyJH6+OM/ro61WCy65ZZbtGXLFn5cAAAAOfPQFeH58dFHH+n8+fN64403FBwcLOnyuOn5559Xv379VKlSpTz3DwsLU+PGjXN9fM2aNdq/f79WrlypyMhISZLValWvXr20e/duRUVFuasrKMXINQAAAHJAvkG+Abcg3wAAAPCsa8kbpk+f7vT/Vq1aqX379vr8888dE5l27NihzZs3691333Ws1BQREaF7771XX375pe69916jdjKRqQRKSkpSWlqaqlSpYhT/3HPP6bnnntNDDz3k2NavXz/17Nkzz/1++uknlStXTjfeeKPT9pdfflk1atTQ/Pnz5f2/5d//vFzYhg0btHv3br3zzju6/fbbHY/fddddmj17ttM9oVNSUrR06VLHsqqpqakaPXq0Tp48qcqVKzvi6tevr0WLFhn1FwAAoDjatGmTmjdv7kgOJOmee+7Rc889p2+++UYPPPDANZdfr149x48KktSiRQsFBwdr48aN/LAAI+QaAAAAJRP5BkoC8g0AAADPcmfe4O3trcDAQKWnpzuVb7VaHatdSlJkZKRuuukmbdq0yXgik8W4FSh2vAyvBHrllVe0YcMGTZgwQe+//75GjBihBQsW6J133slzv4SEBIVctXzahQsXtGvXLv3tb39zDPSv9uOPPyogIMAx0JfkuGf6tm3bnGLr16/vdG/o2rVrS5JOXrUsY0hIiM6ePev0IgAAAHCwWIrur4AOHjzo9KW/dPkK5ooVK+rgQdfLvy9fvlwNGzZUdHS0+vTpo//+978uy/fy8lJERIRR+cCfkWsAAAD8CfkG+QbcinwDAADAM641b7hy+9+zZ8/q3Xff1ZEjR/Twww87lR8REZFtvBcZGZmvvIEVmUqg4OBg+fv7O5Y7zcu+ffs0d+5czZw5U+3atZMkNW3aVBkZGZo+fbq6du2qgICAHPe9dOmS033QJclms8lutys8PDzXOm02mypUqJBte1hYmJKTk522Wa1Wp/9fWU720qVLTtuvtOPSpUsul5wFAAAoTO3bt8/z8XXr1uW43Waz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u/9Cfm6uZE7h4ID869elc05OuL7/oGTOqW8oNFfTJHP2rTxxbe3nkjnXSeNNvh6a1MvSy+fjjYwFVT8GEQDc35kh3F6+Wl31sqlUkhl9TuDmVoVSKbyN1ecvSOZU7fyh/v28dO7Rdvh7Zaxk7pGoKcL95mVkSuaU7m7IitsimWsxZqTwdlZf+lN6+dr4ivcr+F1W/5kq3a+vD3LP/CaZcwh6TPj7ItqvaHtSx742h/cJHx9FP7M8gZv1lc7OwseL/Js3pXOOjsLLJ3p8FN3GwjnR9bBUe6I5wX3I7Gr5zXuWwguZqEpvvvmm0c9lf1harRatWrXC4MGDLdI/ERERkaV17twZK1euxPLly7F161a4ublhwYIFGDBggEGutLQU2vtG6vrll18AADt37sTOnTsNsh988AGGDBkC4N4fGj7//HNcv34dMpkMbdu2xYcffohnn322hteM6B7WG0RERESWwVqD6jvWGkRERER1Fy9koip5eXlhwoQJFulbLpdj6tSpFumbiIiI6pb6/LTksLAwhIWFVZn5448/DP69aNEiLFq0SLLt5cuXP8yiET001htERERUF9TXeoO1BtVnrDWIiIioTpBzRKaKyC29AERERERERERERERERERERERERByRiYiIiIjqPG39vEGaiIiIiIhqAdYbRERERERUI2Qce6gi3CpERERERERERERERERERERERGRxHJGJiIiIiOo8nY63SBMRERERUc1gvUFERERERDVCLrP0EtRKHJHJDKZOnYq+fftW+n5cXBz8/PyQlpaG/Px8REVFITQ0FIGBgejSpQsmTpyIs2fPlpsvKysLUVFRCA4ORkhICGbPno2CggKDzLp16zB48GB07twZHTp0wMCBA7Fp0ybh4nvz5s0YOnRo9VbYRLRaLfr164edO3dapH8iIiIiorqA9YZxWG8QEREREVWNtYZxWGsQERERPRxeyGQGERERuHr1aoUn7ACQkJCADh06wNPTE8XFxWjUqBFefvllxMbG4r333kNhYSHGjRuHy5cv6+cpKSnBxIkTceXKFSxZsgRz587F4cOHMX36dIO28/PzER4ejg8//BCffPIJnnzySSxYsACxsbGSy33nzh2sXr0akydPfrgNYCS5XI7Jkydj5cqVuHv3rkWWgYiIiOoGnU5nthdRbcN6wzisN4iIiEgU6w1qqFhr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99xzj0eyJHsdOzvO5+o8ALAjU/sGXaNg87m6H9A3CjafK/NMns0dea5ej9ptfWvy8zV5NnfkAYAdmdo1JPpGQefj3IY5ry15Bcvj3IYZx86O89E3fJfD+vNPDMDHnT17VsnJyVker1q1qtMZlmXprbfe0jfffCNJ8vf3z7havGfPnho9enSeZtq+fbueeOIJ1apVS926dVOlSpWUkJCgRYsW6ejRo5ozZ46aNGnisbxffvlFPXv2VEBAgDp16qTKlSsrISFBq1atUmpqqr7++msFBQV5bD5Xvh6ufm1NP3auno+8guWdPn1ajz32mM6fP6+77747I2/Tpk0qX768vvnmG1WpUqXQs9zxXE0+dnacz9V5AGBnpvUNuoY5XcMdeaYfP5PXLCbP5o48V69H7ba+Nfn5mjybO/IAwM5M6xoSfcOkvkHXMGvNYrc8zm2YcezsOB99w3dxIRNs4fz583rnnXf03XffKS0tLdM2y7LkcDgUFxeX59yjR49q06ZNSkxMVGBgoO6++27VqlUrXzNu27ZNEyZM0K5du5Seni4/Pz81adJEL730kpo2berxvF9//VUff/yxNm/enPF8W7ZsqcGDB9/0vVELcz7Jta+HK7NMP3auno+8guUlJiZq5syZmT7/WrZsqX79+ikwMNBjWZK9jp0d53N1HgDYiel9g65hVtdwdZ7px8/kNYvJs7kjz9XrUbutb01+vibP5o48ALAT07uGRN8wrW/QNcxZs9gtj3MbZhw7O85H3/BNXMgEWxg0aJC2bt2qJ554QkFBQSpatGiWfTp06OCBybK6evWqkpKSVKZMGZUoUcK4PFczfT6TcewAAADM4C19g66BvOD4AQAAeJ63dA2JvgHncewAALnhQibYQrNmzfTGG2+oa9eu+c44dOiQ6tatm6e/k5qaqt9++001atTI97+L7Lny9eC1BQAAQEHQN3yLq18LXlsAAADkF13D93BuAwCA3Pl5egCgMJQpU0blypUrUEaPHj00cOBArVmzRikpKTnuGx8fr08//VSRkZGKjY3Ndp8JEybo999/z9MM//73v/Xdd98VSt6wYcPydEva5ORkffXVV1qwYEGhzOfK18PVr63px87V85FXsLzu3bsrNjZW6enpTuWdOnVK48aN08yZM92aJdnr2NlxPlfnAYCdmdY36BoFm8/V/YC+UbD5XJln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n+W9aR0Oh9asWZNjxieffKL58+crNjY2299ekKRDhw6pf//+SkhIyPX9SrOzdu1avf/++/Lz81N8fLxmz56d5Yd0Tv744w99/vnnWrBggX7//fdM2wICAtS6dWsNHjxYYWFhuWZdvXpVY8eO1cqVK5WWlqaHH35Yo0eP1oQJEzRz5syMH54NGjTQ559/7vTCYfv27Vq/fr0OHz6sCxcuSLr+WwN16tTRPffcoyZNmuSasXv3bi1fvlzPPPOMypUrd9P9li5dqp9++inXz5XU1FS9++67+uc//6n09HRJ199rt1mzZvrggw9UvXp1SdffpzklJUVPPvmkU8/1f5n02krSzz//rM8++0ybN29WWlpapvcYLlKkiFq0aKHnnntOTZs2zTVr2rRpmjZtmtasWZNR4P7szJkzGjBggP773//m62sjLi5Ob731VsbnTV6O35/fW9kVpk2bpr///e+6fPmypOvfQx588EGNHDlSgYGBkq5//lmWpQcffPCmOTNmzNDFixc1bNiwHP+9xx9/XLVr19Z7772X437ZfR+tX79+lpLUp08flSlTRlOmTMkxz+RjJ11/f/v169fr1VdfzXG/kydPavPmzerWrVuu81mWpQULFmjBggXau3ev0tLSMuasVq2a2rVrpwEDBjhV/NPT0/Xpp58qJiZGaWlp6t69u5555hl99dVXGj9+vFJTU2VZljp06KBx48apVKlSuWa68msXAOzG5L5B1zCna0j0DZP6Bl2jYOtl+oZZfYOuAQC+y+SuIdE3TOobdA1zuoZE35A4t5EXJncNib4Bz+NCJvisrl27Zvr49OnTOn/+vMqWLasKFSro7NmzSkpKUrly5XTrrbfq22+/dTr7vvvuU1hYmN5+++2bLkZyc+nSJZ06dUo1atTIuEVids6dO6dDhw5lXE2eVykpKZo1a5aOHDmiZ555Jt+30Dtx4oR+//13paenq0yZMrr99tuzlBxnWJYly7Lk5/d/72x58OBBHTp0SNWqVVODBg0ybfNmp0+f1oEDB5SSkqKaNWuqXr16Ls037bW9MdOxY8cybg9btmxZ1ahRQwEBAU5npKen6+rVqypevHiOnwvJycn6/fffnboa/WZiYmJ05MgRPfzwwxm/TeIpqampio+PV0pKimrUqKHSpUu77d+6dOmSAgIC8vS65OTkyZMqVapUxu1OC1th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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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6NKlCw4dOoSVK1fi9OnTePvtt3HPPfegqqoKffr0QefOnXHw4EEsXrwYpaWleO211wTPIScnB6+++ipatmyJfv36obq6GgcOHMCbb76J33//HR999BFkMhm3PcMwmD9/PjZt2gSlUomUlBS0aNECx44dQ1ZWFnbs2IGPP/4Y6enpgp+3YcMGLFu2DHFxcUhLS8OFCxdw5MgRPP/886isrMT999/P295ms+GZZ57Bjh07oFarER8fj8jISJw7dw5bt27F//73PyxatEj081544QVs27YNvXv3xu23344TJ05gz549OHjwIL7++mskJSUBcD5z48ePx/fffw+DwYDhw4cjICCAO07Lli0BABs3bsQLL7wAAEhMTERqaipMJhOKi4uxfft2hIeHiwpSd+p7LdkxnjhxAidPnuTVgTeWMZperwcAqNVqboz/93//BwAYN24c71moL6zwnjhxIve/69evx/bt2/Hiiy/yvq8EQRCEFxiCIAiiyRg8eDCj0+mYDRs2eN126tSpjE6nY/bv389b/vzzzzM6nY7R6XTM+++/z9jtdt56s9nMJCYmMj179mROnz7tcdyioiLm1KlTgsf0ZVz1GSvLBx98wOh0OmbZsmW85UOGDGEGDhzI3Hbbbczo0aN92mfy5MmMTqdj5syZw9TW1nLLy8rKmPHjxzM6nY556qmnfB57bW0tM2jQIEan0zHPPfcco9freeurq6uZPXv2NHgM+/fv5+7bpEmTmPLycm5dUVER06dPH0an0zGjR49mHnroIcZgMHDrc3JymLi4OKZ79+7MhQsXeMd1fR5effVVxmq1cuvy8/OZvn37Mjqdjvn22295+33zzTeMTqdjUlNTmePHj3PLHQ4H8/HHHzM6nY5JSUlhysrKePuxz3B8fDzzf//3f7x1GzZsYHQ6HdO7d2/GaDTy1v3zn/9kdDodM3nyZObPP//krduxYwcTGxvL9OnTh6mqquKWnz9/nju3wYMHM2fOnOHW2Ww25oUXXmB0Oh0zc+ZMxh12nOfPn/dYxzDOZ0+n0zEHDx70WFdaWsocO3ZMcD8hrvZasus+/vhjnz+Lhf3OCe1bXFzMJCcnMzqdjvnoo48YhmGYP//8k7uWQufsK2fOnOHuv+v5jBgxgtHpdMzGjRuv+tgEQRC3IpSyThAE0Qy4p4az/02bNs3nY3Tu3BlPPPEE5HL+T7ler4fJZEKHDh0QFRXlsV+7du3QtWvXBp9DfWBNpfbs2cMtO3/+PIqKijBgwAD07dsX+fn5KC0t5dbv3bsXANC/f39u2aFDh5CdnQ1/f3/84x//4EU+IyIisHDhQgDOVPi//vrLp7GtW7cOly5dQmxsLN58800uy4AlODi4Uccgk8nwxhtv8CKh7dq1Q0ZGBgBnmvYbb7zB8w7o0aMH0tLS4HA4PFpdsWi1WsyfPx9KZV3yW3R0NB599FEAwOeff87b/rPPPgMAPProo7xMCJlMhrlz5yImJgbV1dVYu3at4OdNnToVgwcP5i2bMGECoqKiUFNTg9zcXG55ZWUlvvjiC/j5+WHRokVcfTPLiBEjcPfdd6OqqgpbtmwR/LyXXnoJXbp04f6tUCjw5JNPAgB+++03WK1Wwf3EKCsrQ3BwMFJSUjzWtWjRAnFxcT4fq6HXsrEwGAw4ePAg5syZg9raWgQEBGDy5MkAgPLycm67iIiIq/6MDRs2AHCWLrgeh42Ws+sJgiAI3yBBThAE0Qz06tUL48eP9/gvLS3N52MMGzYMCoXCY3lERATatWuHvLw8vP3224K1uU1N7969odFocOTIERiNRgB8wc0KXnZZdXU1jh07hpCQECQkJHDHYcVoWloal3rsSkJCArp37y4pXN355ZdfAACTJk0SvJ7uNHQMbdu2hU6n81jOGnslJCSgRYsWousvX74sOK677roLfn5+HsvHjRsHADh37hyKi4sBAH/99Rf+/PNPAMD48eM99pHJZFwXAHcPAxZ3Mc7CTvawn8Uew2QyoVevXoiMjBTc77bbbgMAj5pwAFAqlYLfDa1Wi9DQUFgsFlRWVgoeV4wePXqgpqYGzz33HHJzcz38DXylMa5lQ3CtP09OTsbUqVNx7NgxtGjRAkuXLkWbNm0a7bNsNhvnEcAKcJZx48ZBqVTi4MGD3PUgCIIgvEM15ARBEM2AL23PvNGuXTvRde+++y7mzZuHzz//HJ9//jnCwsKQmJiIAQMGICMjo0ERsqtBrVajd+/e2LNnDw4dOoS0tDTs3bsXMpkM/fv350T6vn37kJGRgf3798PhcCA1NZWXAcCKPKm+0h07dsTJkyd5glAK1ulaKJtAiIaOQUwgsZF2sfVs5J41fnNHbDxBQUEICwtDZWUliouLuTZVABAWFiboss2eAwDR6yjWjo89nus4z58/D8B5f2NiYgT3Y3GN5LJotVqoVCrRz6uqqhK9LmK8+uqreOihh7B582Zs3rwZgYGB6NGjB/r27YuxY8f63G6wMa5lQ3CtP1cqlQgNDUV8fDyGDBnCq+V2/c6Xl5f7/Ly78vPPP6OkpASRkZEYOHAgb13Lli2Rnp6O//u//8OGDRu47AWCIAhCGhLkBEEQNyhSxkkpKSn4v//7P/z88884ePAgDh8+jF9//RW7d+/Gxx9/jCVLlvB6EzcF/fr1w549e7B3714MHDgQ+/fvh06n46LM7du35yLk7P829RibAvcSg/qubwgMwzTasepjCsZGnzt16oRevXpJbiskFK/FNenatSt27tyJPXv2YP/+/Th8+DB+//137N+/H0uWLMEbb7yBsWPHNvrnNjbufcjFaNeuHTcxc/ToUcFUfW+wZm5msxlTp071WM9OOGRlZWHevHk+ZZwQBEHc6pAgJwiCuEnRaDQYMWIERowYAcAZFfvwww+xZs0avPjii/jpp5+adDyuaenHjx9HZWUlL8W3f//+WLt2LU6fPs25r7vWbgPg0p3ZiKsQ7Dqx1Gh32rRpg9OnT+PMmTMenyfEtRhDY1BUVCS4XK/Xc+ncrVu3BlA3rsrKSuj1esHIbmOeAxv179KlC95+++0GH6+xUCqVGDRoEOegr9fr8fnnn2Px4sV45ZVXcMcdd/A8AoRo6mt5tcjlcgwePBgbN27Epk2b8MADD9Rr/8uXL2P37t0AnOf6xx9/SG77yy+/4Pbbb2/IkAmCIG4JqIacIAjiFiEiIgLPPvssAGeadlVVFbeOTQeW6lcthS/7x8XFISwsDHl5edi2bRsAvuBmo+Hr16/HuXPn0KZNG56JF1BXZ8y2WXPn+PHjOHHiBORyuc8tq9ja5A0bNvh0/tdiDI3Bzp07YbFYPJZv3rwZgDM6zQrC1q1bc2nUWVlZHvswDMP1pk9NTW3w2Pr16weVSoXffvsNZWVlDT6eL1zNMx0UFITHHnsMISEhMBqNOHfunNd9mvpaNoQHH3wQKpUKJ0+exBdffOF1+0OHDnH/f+PGjbDb7UhKSkJeXp7of7NmzQJAPckJgiB8hQQ5QRDETcaFCxewbt06rg+xK2wf4tDQUF4kjxVqBQUFV/WZvuwvk8nQt29fMAyDf//731CpVDzB2q9fP8hkMvz73//m/u1OSkoKkpKSYDKZsGDBAq72HHBmACxYsAAAMHLkSJ/NrCZPnozWrVvj+PHjeOmll2AwGHjr9Xo9l0J/rcbQGFy+fBnvvPMOT4CePn0aS5cuBQDMmDGDt/3MmTMBAEuXLsXJkye55QzDYOnSpThx4gRCQkIwZcqUBo+tZcuWmDZtGgwGA+bMmYO8vDyPbSwWC3788UecPn26wZ8HSD+TRqMRn3/+uWC9+qFDh1BdXQ2FQsFlFHijKa9lQ+jatSvmz58PAHj77bfxz3/+U/B34uzZs3jqqafw+uuvc8tY93TWJFAMdv3PP/8seH0JgiAIPpSyThAEcZNRXV2Nl156Ca+99hq6d+/OmX0VFhbi+PHjkMlkePbZZ3n1ncOGDcOSJUvw1VdfoaCgAK1bt4ZcLseQIUMwdOhQr585fPhwZGVl4b333sO+ffsQEREBmUyGiRMn8mqG+/fvj507d8JsNiM1NZXX2is8PByxsbE4fvw4t60QH3zwAWbMmIEff/wRQ4cORUpKCmw2Gw4cOAC9Xo/4+HhOFPtCYGAgli1bhtmzZyMrKws//PADevXqhYCAAFy6dAknTpxAYmIibzyNPYbG4J577sG6devw888/IykpCVVVVThw4ACsVivuuOMO3HfffR7bHz58GJs3b8bEiRPRp08ftGjRAseOHcPZs2eh0Wjw/vvvN5oB4NNPP43Lly9j27ZtGDduHLp3744OHTpAoVDgr7/+wsmTJ2EwGLBixYpGacs3fPhwHDhwAM8++ywGDhyIkJAQAEBmZiZatmyJt99+G++++y50Oh06deoElUqFCxcu4MiRIwCAOXPm+HzuTX0tG8LUqVPh7++P119/HcuXL8cXX3yBxMREREZGwmw248yZM9ykyKhRowA4OwsUFhZCrVZzy8SIjo5GfHw8jh07hk2bNnGTFQRBEIQwJMgJgiBuMjp06IAXX3wRBw8eREFBAXbt2gUAaNWqFcaNG4dp06bxWokBTqfmRYsWYdWqVcjOzsa+ffvAMAxat27tkyC//fbb8frrr+Pbb7/F/v37uahx7969PQS50P9n6devHzdpIGbo1qFDB2RlZeGzzz7DDz/8gJ9//hlyuRxdunTBXXfdhenTp0sa3gkRFxeHLVu2YPXq1fjxxx/x22+/weFwQKvVYsiQIR6O+NdiDA0lKSkJd999Nz7++GPs2bMHBoMBnTt3xqRJkzB16lQPEzaZTIZ3330X6enpWLNmDY4dOwaj0YiWLVtiwoQJePDBB6/KiVsMpVKJDz74ABkZGVi/fj2ys7NRUFAAf39/aLVaDB48GEOGDGm0NP97770XtbW12LJlC3bt2sW5sGdkZKBjx4547bXXcPDgQRw/fhx79+6F1WpFq1atcOedd+Lee++tl6FgU1/LhjJx4kQMHjwYa9aswa+//orTp0/j8OHDUKvVaN++Pe6++26MGTOGuxds+vngwYMRGhrq9fhjx47FsWPHsH79ehLkBEEQXpAxjWm5ShAEQRBEkzJ//nxs3LgRb731VoNb6REEQRAE0bRQDTlBEARBEARBEARBNAMkyAmCIAiCIAiCIAiiGSBBThAEQRAEQRAEQRDNANWQEwRBEARBEARBEEQzQBFygiAIgiAIgiAIgmgGSJATBEEQBEEQBEEQRDNAgpwgCIIgCIIgCIIgmgES5ARBEARBEARBEATRDJAgJwiCIAiCIAiCIIhmgAQ5QRAEQRAEQRAEQTQDJMgJgiAIgiAIgiAIohkgQU4QBEEQBEEQBEEQzQAJcoIgCIIgCIIgCIJoBkiQEwRBEARBEARBEEQzQIKcIAiCIAiCIAiCIJoBEuQEQRAEQRAEQRAE0QyQICcIgiAIgiAIgiCIZoAEOUEQBEEQBEEQBEE0AyTICYIgCIIgCIIgCKIZIEFOEARBEARBEARBEM0ACXKCIAiCIAiCIAiCaAZIkBMEwaOoqAgxMTHIysq6qv2zsrIQExODoqKiRh4ZQRAEQRDusH93jx492uSfPW3aNEybNq3JP5cgbiZIkBPEdQj7x5X9Ly4uDmlpaZg/fz6Ki4ube3jXjK1bt+KLL75o7mEQBEEQxDXH/W+963/vv/9+cw/vmmI0GrFo0SIcOHCguYdCEM2OsrkHQBCEOPPmzUP79u1hsVhw5MgRbNy4Eb///ju2bdsGPz+/5h5eo7Nt2zYUFBTg/vvvb+6hEARBEESTwP6td0Wn0zXTaJoGo9GIxYsXY+7cuUhNTW3u4RBEs0KCnCCuY9LT09GjRw8AwOTJkxEeHo4VK1bgxx9/xMiRI5t5dARBEARBNBTXv/UEQdx6UMo6QdxApKSkAADOnz/PW3769GnMmzcPt912G3r06IEJEybgxx9/5G1TWVmJd955B2PGjEFycjJ69eqFWbNm4eTJk1c9noKCAkyfPh2JiYlIT0/H0qVL4XA4PLb74YcfMHv2bAwcOBAJCQkYNmwYlixZArvdzm0zbdo0/Pzzz7hw4QKXsjdkyBAAgMViwUcffYQJEyagd+/e6NmzJ+677z7s37//qsdOEARBENczFy5cwKuvvorhw4cjMTERqampmDdvnk8eLVVVVZg0aRLS09Nx5swZAM6/pR9//DHuuOMOJCQkYNCgQXj33XdhsVh8Gs+aNWswbNgwJCYmYtKkSTh06JDHNr78vS4qKkK/fv0AAIsXL+b+5i9atAgAcPLkScyfPx9Dhw5Fjx49MGDAALzwwguoqKjwaZwEcaNBEXKCuIG4cOECACAkJIRbVlBQgHvvvReRkZF48MEHERAQgB07duDRRx/FokWLcMcddwBwivgffvgBI0aMQPv27VFaWoo1a9Zg6tSp+O677xAZGVmvsZSUlGD69Omw2+2YPXs2/P39sXbtWsFU+o0bNyIgIAAPPPAAAgICsH//fnz88cfQ6/V4/vnnAQBz5sxBTU0N/vrrL7zwwgsAgMDAQACAXq/HunXrMHr0aEyePBm1tbVYv349Zs2ahXXr1iE2Nrb+F5MgCIIgrgP0ej3Ky8t5yyIiInD06FEcPnwYo0aNQuvWrXHhwgV8++23mD59Or777jv4+/sLHq+8vBwzZ85EVVUVvv76a3Ts2BEOhwMPP/wwfv/9d0yZMgVdu3ZFfn4+vvzyS5w7dw5Lly6VHOO6deuwYMECJCcnY8aMGTh//jwefvhhhIaGok2bNrxz8fb3OiIiAq+++ipeffVV3HHHHdx7SkxMDABg7969OH/+PCZMmACtVouCggKsXbsWp06dwtq1ayGTyRpyuQni+oO5hTh37hzz8ssvMxkZGUxsbCwzatSoBh3vp59+Yu6++24mKSmJSUlJYaZOncpcunSpkUZL3Mps2LCB0el0zN69e5mysjLm0qVLzM6dO5m+ffsyCQkJvOdsxowZzOjRoxmz2cwtczgczN13383ceeed3DKz2czY7Xbe55w/f55JSEhgFi9ezFum0+mYDRs2SI7xjTfeYHQ6HZOdnc0tKysrY3r37s3odDrm/Pnz3HKj0eix/8svv8wkJSXxxj179mxm8ODBHtvabDbedgzDMFVVVUz//v2ZF154QXKcBEEQBHE9wv6tF/qPYYT/dh4+fJjR6XTMxo0bPY6Tk5PDXL58mRk1ahQzdOhQpqioiNtm06ZNTPfu3ZmDBw/yjvftt98yOp2O+f3330XHabFYmH79+jFjx47l/S1es2YNo9PpmKlTp3LLfP17XVZWxuh0Oubjjz/2+Dyh8962bRuj0+k8xk8QNwO3VIS8oKAAu3btQlJSEhwOBxiGuepjbd68GX//+98xc+ZMPPHEE6itrcWhQ4dgNpsbccTErY67uVm7du3w3nvvoXXr1gCcaej79+/HvHnzoNfredsOHDgQixYtQnFxMSIjI6FWq7l1drsd1dXVCAgIQJcuXXD8+PF6j23Xrl3o2bMnEhMTuWUREREYM2YMvvnmG962Go2G+/96vR4WiwUpKSlYs2YNzpw5g+7du0t+lkKhgEKhAAA4HA5UV1fD4XAgISHhqsZOEARBENcLCxYsQJcuXTyWu/7ttFqt0Ov16NixI0JCQnD8+HGMGzeOt31xcTGeeeYZAMC///1vXubbzp070bVrV0RFRfGi8X379gUAHDhwAL169RIcX25uLsrKyjBv3jzeu8T48ePx7rvv8rZtjL/XrudtNptRW1uLpKQkAMCxY8e48j2CuFm4pQT5kCFDMGzYMADA/PnzkZube1XHqaysxMKFC/Hiiy/ivvvu45YPHTq0UcZJECzsH+mamhps2LABBw8e5P0x/PPPP8EwDD766CN89NFHgscoKytDZGQkHA4HVq9ejW+++QZFRUW8+u2wsLB6j+3ixYvcH0hXhF4qCgoK8OGHH2L//v0eEwc1NTU+fd7GjRvx2Wef4ezZs7Bardxyd2dagiAIgriRSExMFDR1M5lMWL58ObKyslBcXMwLJAn97Xz22WehVCqxfft2aLVa3rrCwkKcPn2aq912p6ysTHR8Fy9eBAB06tSJt1ylUqFDhw4e2zf073VlZSUWL16M7du3e4zL13cGgriRuKUEuVzu3cOOYRh89tlnWLt2LS5cuIDIyEhMmzaNF6ncsWMHHA4HJk2adA1HSxD8P9LDhg3Dfffdh6effho7d+5EYGAgZ6A2c+ZMpKWlCR6jY8eOAIBPPvkEH330ESZOnIjHH38coaGhkMvlePPNNxuULeKN6upqTJ06FUFBQZg3bx46duwIPz8/HDt2DO+//76gCZw7mzdvxvz58zFs2DBkZmaiRYsWUCgUWL58uYfBHUEQBEHcDPzjH/9AVlYWZsyYgZ49eyI4OBgymQxPPvmk4N/tO++8E5s2bcLq1avx9NNP89Y5HA7odDrOo8UdNvOuoTTG3+snnngChw8fRmZmJmJjYxEQEACHw4FZs2Zd0/cVgmgubilB7gtvvPEG1q1bhzlz5iApKQl//PEH3n//ffj5+eHee+8FAGRnZ6NLly7YtGkTli1bhuLiYkRHR+Opp57CoEGDmvkMiJsVhUKBp556CtOnT8e///1vzJ49m5uZVqlU6N+/v+T+33//PVJTU/Hmm2/ylldXVyM8PLze42nbti0KCws9lp89e5b3799++42b7e7Tpw+3XMglVsyo5fvvv0eHDh2wePFi3jYff/xxvcdNEARBEDcC33//PcaNG4f58+dzy8xms2iUeOrUqejYsSM+/vhjBAcHY/bs2dy6jh074uTJk+jXr1+9TdHatm0LwBlld42wW61WFBUV8crOfP17LTaGqqoq7Nu3D4899hjmzp3LLT937ly9xkwQNxLU9syFP//8E19//TVefPFFPPzww+jfvz/mzp2L+++/H0uWLOEieSUlJTh79iw++ugjPP7441ixYgXatWuHRx55BAUFBc18FsTNTGpqKhITE/Hll1/CbDajRYsWuO2227BmzRpcvnzZY3vXOjGFQuExs7xjxw4UFxdf1VgGDRqEI0eOICcnh/d5W7du5W3HZqa4frbFYvGoMwcAf39/wRcNth7N9RjZ2dk4cuTIVY2dIAiCIK532L99rnz11Ve8kjN3Hn30UcycORMffPAB7+/sXXfdheLiYqxdu9ZjH5PJBIPBIHrMhIQERERE4D//+Q+vRdrGjRtRXV0tOGZvf69Zh3ix/d358ssvRcdHEDc6FCF3Ye/evQCcKT82m41b3r9/f6xYsQKXLl1Cu3btwDAMDAYD3n//fa5u/LbbbsPw4cOxYsUKD4MLgmhMMjMz8fjjjyMrKwv33nsvXnnlFdx3330YM2YMpkyZgg4dOqC0tBRHjhzBX3/9hS1btgAAbr/9dixZsgQvvPACkpOTkZ+fj61btwrWf/nCrFmzsHnzZsyaNQvTp0/n2p61bdsWeXl53HbJyckIDQ3F/PnzMW3aNMhkMmzevFkw7Sw+Ph7bt2/HW2+9hR49eiAgIABDhgzB7bffjv/+97949NFHcfvtt6OoqAj/+c9/0K1bN8mXCIIgCIK4Ubn99tuxefNmBAUFoVu3bjhy5Aj27t3r1ffl+eefh16vx8KFCxEYGIixY8di7Nix2LFjB1555RXOwM1ut+PMmTPYuXMnVq5cKVjHDjiz8J544gksWLAAM2bMwMiRI1FUVISsrCyPdwhf/15rNBp069YNO3bsQOfOnREWFobo6GjodDr06dMHK1euhNVqRWRkJPbs2eNT73WCuFEhQe5CRUUFGIbhHCfdYQU52wPadTuVSoU+ffpQhJy45tx5553o2LEjPvvsM0yZMgXdunXDhg0bsHjxYmzcuBGVlZWIiIhAXFwcHn30UW6/OXPmwGg0YuvWrdi+fTvi4uKwfPlyfPDBB1c1jlatWmH16tV4/fXX8emnnyIsLAz33HMPWrVqhb///e/cduHh4fjkk0/wzjvv4MMPP0RISAgyMjLQr18/ZGZm8o5533334cSJE8jKysIXX3yBdu3aYciQIZgwYQLXN/3XX39Ft27d8N5772Hnzp347bffru5CEgRBEMR1zN///nfI5XJs3boVZrMZvXr1wueff45Zs2Z53fe1116DwWDAiy++iMDAQAwbNgxLlizBF198gc2bN+N///sf/P390b59e0ybNk3QkNWVu+++G3a7HatWrcK7774LnU6HZcuWeRjK1ufv9euvv45//OMfeOutt2C1WjF37lzodDp88MEH+Mc//oFvvvkGDMNgwIABWLFihahXDkHc6MiYW9QdgXVZ37ZtG7fsm2++wcKFC/HNN99ApVJ57NOlSxcEBQVh8eLFWLRoEf744w8EBgZy659//nnk5ubiu+++a5JzIAiCIAiCIAiCIG5cqIbcBdaoorKyEj169PD4LygoCAAwePBgAMC+ffu4fS0WCw4ePIj4+PimHzhBEARBEARBEARxw3FLpawbjUbs2rULAHDhwgXo9Xrs3LkTgLMGvEuXLvjb3/6G5557DpmZmUhKSoLVasW5c+dw4MABLF26FICzznX48OF4+eWXUVlZCa1Wi2+++QalpaUeKbgEQRAEQRAEQRAEIcQtlbJeVFTEmbC5s3r1aqSmpoJhGPz73//GmjVrcPbsWQQGBqJLly4YMWIErxe5wWDAP//5T3z33XfQ6/WIj4/Hs88+i969ezfR2RAEQRAEQRAEQRA3MvUW5IWFhVi1ahWys7NRUFCAqKgoXh22EAcOHMD06dMF13Xp0oWLUottN3LkSPzr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w4dRUFCA+fPnY9KkST7fSaU6RqR1pd6eT7GKND/STST3RCC+5bx582YsXrwY3333HfLy8vDTn/4Uc+bM8enCnWr3pEjurQDzKREYkBMRERERERElAd8hJyIiIiIiIkoCBuREREREREREScCAnIiIiIiIiCgJGJATERERERERJQEDciIiIiIiIqIkYEBORERERERElATaZCeAiIgoVdTX12PFihWoqanBnj17UFhYiPfffz/q7SxYsABvv/12wM/uvfde3HbbbV1NKhEREfUADMiJiIg67NmzB+vWrcOoUaPgcrmgKEpM27njjjtw3XXX+Sxbs2YN/vrXv6KysjIeSSUiIqIeQFBirW0QERH1MC6XC6Kovs21YMECbN++PaYW8kCuv/56NDY24oMPPojL9oiIiCj98R1yIiKiDu5gPBRFUbBixQpcfPHFKC0txZQpU/DSSy+FXOfo0aPYtGkTrrjiijillIiIiHoCdlknIiKKwu9//3usWrUKt99+O0aNGoXNmzfjiSeegMFgwI9//OOA67z//vtwuVy47LLLujm1RERElMoYkBMREUVo//79ePXVV/Hoo49i1qxZAIDzzz8fNpsNzz77LGbNmhWwlf39999HRUUFhgwZ0t1JJiIiohTGLutEREQR+uqrrwAAF110EZxOp+d/559/PhoaGnDkyBG/dfbu3Ytvv/0Wl19+eXcnl4iIiFIcW8iJiIgi1NTUBEVRcN555wX8/MiRIxg0aJDPsvfeew9arRaXXnppdySRiIiI0ggDciIiogjl5ORAEAS89tpr0Ol0fp8XFBT4Lfvggw8wbtw45OXldUcSiYiIKI0wICciIorQuHHjAAAnTpzA5MmTw36/pqYG+/fvx5133pnopBEREVEaYkBORETUwWq1Yt26dQCAQ4cOoa2tDWvXrgUAnHvuuSgoKMBPf/pT/OpXv8Ls2bMxatQoSJKEffv24euvv8Zzzz3ns7333nsPRqMR06ZN6/Z9ISIiotQnKIqiJDsRREREqeDgwYOYMmVKwM9efvlljB07Foqi4G9/+xtWrlyJuro6ZGZmoqCgAJdccgluuukmz/dlWcYFF1yAMWPG4E9/+lP37AARERGlFQbkREREREREREnAac+IiIiIiIiIkoABOREREREREVESMCAnIiIiIiIiSgIG5ERERERERERJwICciIiIiIiIKAkYkBMRERERERElAQNyIiIiIiIioiRgQE5ERERERESUBAzIiYiIiIiIiJKAATkRERERERFREjAgJyIiIiIiIkoCBuRERERERERESfD/gzXMElfpQfUAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "tab_eval.visual_evaluation()" + ] + }, + { + "cell_type": "markdown", + "id": "0440a09b", + "metadata": {}, + "source": [ + "\n", + "## Structute Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "5e452b06", + "metadata": {}, + "outputs": [], + "source": [ + "original_graph_structure = feature_spec_original.get_structural_data('user-product')\n", + "proper_graph_structure = feature_spec_generated_proper.get_structural_data('user-product')\n", + "random_graph_structure = feature_spec_generated_random.get_structural_data('user-product')" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "9081c75a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DEGREE SIMILLARITY SCORE\n", + "ORIG vs PROPER: 0.9369674422689857\n", + "ORIG vs RANDOM: 0.9685419233777225\n" + ] + } + ], + "source": [ + "orig_proper = get_dd_simmilarity_score(original_graph_structure, proper_graph_structure, cdf_points=1000)\n", + "orig_random = get_dd_simmilarity_score(original_graph_structure, random_graph_structure, cdf_points=1000)\n", + "\n", + "print(\"DEGREE SIMILLARITY SCORE\")\n", + "print(\"ORIG vs PROPER:\", orig_proper)\n", + "print(\"ORIG vs RANDOM:\", orig_random)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "d75f8956", + "metadata": {}, + "outputs": [], + "source": [ + "original_snap_graph = Graph.instantiate_from_feature_spec(feature_spec_original, 'user-product', graph_name='original')\n", + "proper_snap_graph = Graph.instantiate_from_feature_spec(feature_spec_generated_proper, 'user-product', graph_name='properly_generated')\n", + "random_graph_structure = Graph.instantiate_from_feature_spec(feature_spec_generated_random, 'user-product', graph_name='randomly_generated')\n", + "all_graphs = [original_snap_graph, proper_snap_graph, random_graph_structure]" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "1b7acca9", + "metadata": {}, + "outputs": [], + "source": [ + "graph_analyser = AnalysisModule()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "81e9ec1f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
CategoryStatisticoriginalproperly_generatedrandomly_generated
0Global statsNodes172871734617346
1Global statsEdges520075153652005
2Global statsDensity0.00030.00030.0003
3Global statsAverage degree3.012.973.0
4Global statsZero deg nodes196102542822
5Global statsZero in deg nodes196102542822
6Global statsZero out deg nodes196102542822
7Global statsSelf loops0352
8Global statsBidirectional edges520075150152003
9Global statsUnique undirected edges520075150152003
10Global statsUnique directed edges104014103002104006
11ConnectivityIs connectedFalseFalseFalse
12ConnectivityNumber of connected components197102552823
13ConnectivityPercent of nodes in largest component98.8740.8983.73
14TransitivityClustering coefficient0.0952540.0536670.016354
15Path stats90% effective diameter3.213.63.87
16Path statsApprox. full diameter556
17Path statsAverage shortest path length2.593.053.69
\n", + "
" + ], + "text/plain": [ + " Category Statistic original \\\n", + "0 Global stats Nodes 17287 \n", + "1 Global stats Edges 52007 \n", + "2 Global stats Density 0.0003 \n", + "3 Global stats Average degree 3.01 \n", + "4 Global stats Zero deg nodes 196 \n", + "5 Global stats Zero in deg nodes 196 \n", + "6 Global stats Zero out deg nodes 196 \n", + "7 Global stats Self loops 0 \n", + "8 Global stats Bidirectional edges 52007 \n", + "9 Global stats Unique undirected edges 52007 \n", + "10 Global stats Unique directed edges 104014 \n", + "11 Connectivity Is connected False \n", + "12 Connectivity Number of connected components 197 \n", + "13 Connectivity Percent of nodes in largest component 98.87 \n", + "14 Transitivity Clustering coefficient 0.095254 \n", + "15 Path stats 90% effective diameter 3.21 \n", + "16 Path stats Approx. full diameter 5 \n", + "17 Path stats Average shortest path length 2.59 \n", + "\n", + " properly_generated randomly_generated \n", + "0 17346 17346 \n", + "1 51536 52005 \n", + "2 0.0003 0.0003 \n", + "3 2.97 3.0 \n", + "4 10254 2822 \n", + "5 10254 2822 \n", + "6 10254 2822 \n", + "7 35 2 \n", + "8 51501 52003 \n", + "9 51501 52003 \n", + "10 103002 104006 \n", + "11 False False \n", + "12 10255 2823 \n", + "13 40.89 83.73 \n", + "14 0.053667 0.016354 \n", + "15 3.6 3.87 \n", + "16 5 6 \n", + "17 3.05 3.69 " + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = graph_analyser.compare_graph_stats(*all_graphs)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "973a5457", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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bkabNm2MQ4cOlZlP//79jfvuu8++/eSTTxpt2rQxfvnlF/u+jIwMIzY21ujfv79htVoNwzCMt956y2jTpo3x5Zdf2uNycnKMoUOHGm3atDE2btx4xuveeuutRnR0tHHkyBH7vj179hiRkZFGmzZt7PsOHz5sREZGGq+++qrD+X/99ZfRrl07+/7c3FyjW7duxujRo438/Hx73EcffWS0adPGGD9+vH3fxo0bjTZt2hgDBgwwsrOz7fttNpsxePBgY9KkSYbNZrPvz87ONmJjY43rr7/evu+BBx4wevfubZw8edIhr+nTpxtdunRxGPff4uLijDZt2hiPPvqow/7/+7//M9q0aWO8/PLL9n1Ff16K3ssvv/yyzD8/SUlJxcYpct999xlt2rQxnnvuuRKP9e/f37596NAho02bNkZMTIxx/Phx+/4tW7YYbdq0MZ566in7vvHjxzvc49LGPFNuL7/8ssN7X3SfHnzwQYe4p59+2mjTpo3x008/2ff179+/2J/bpKQkIyoqynj66aeLXUtEREREnKvoOfdM/1xyySX2+HN5Nvz888/t+9LT043evXsbI0eOPGNeZ/MMfD7Pr5dcckmJz88iItWB2qqIiNNYrVY2bNjAwIEDadKkiX1//fr1GT58OL/99pu9/cf3339Px44diYyMtMf5+/tz6aWXnvP1169fT0xMDBdccIF9n5eXF1deeSVHjhxhz5499muHhoYyYMAAe1y9evUYO3ZsuV7jDz/8wMCBA2nUqJF9f6tWrejTp49D7JdffonNZmPYsGGcPHnS/k9wcDDNmjWzz1Tftm0bKSkpjB07FheXf74AdOmll+Ln51diHiNHjnSYNR0XF8eBAwe49NJLSU5Otl8rKyuLnj178ssvv2Cz2TAMgy+++ILY2FgMw3DIq0+fPqSnp7N9+/Yz3mOg2Fcni74FcCY+Pj4AfPvttyXOpimvq666qtyxAwcOJDQ01L4dExNDhw4d7K+jshSNf/311zvsnzRpksPxIuHh4Q5/bgMDA2nRogWHDh2q1DxFRERE5NzNnDmTt99+u9g///524dk+G9avX9/+TUUAb29vRo4cyY4dO0hISCgzr3N5Bj7bHEVEqiu1VRERpzl58iTZ2dm0aNGi2LFWrVphs9k4duwYrVu35siRI3Ts2LFYXNOmTR2209PTycnJsW+7urri7+9f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0KABvXv3JjY21h43fvx4DMPg7bff5j//+Q9t27bl1VdfPat70b17d5YuXcorr7zCokWLyMrKIiQkhJiYGK688kqH+/TBBx8wb948vvzySxYvXoy/vz/h4eHcfffdZV7nqaeeIiAggNWrV7Nu3Tq6d+/O66+/XuZs6G7durF161Y+/fRTEhMT8fHxISYmhueee87eFgZg1qxZPPHEE8yePZv8/Hxuu+22cy6Ojxw5ErPZzDvvvENSUhIxMTE8/PDD1K9f3x7TqlUr/vOf//Dyyy8ze/ZswsPDeeaZZ1izZk2xDwrOJrdZs2YRFhbGihUr+OqrrwgODmbKlCncdttt5/RaRERERKTmOptnw+bNm/Pwww/zzDPPsH//fsLCwnjhhRfo27dvua5Vnmfg88lx6tSpHD16lP/9739kZmbSrVs3FcdFpNowGf/+zrqISA3y5JNPsnTpUjZv3lzlixQuWLCA2bNn89133xEaGlql1y6JzWajZ8+eDBo0iFmzZjk7HRERERERqWSxsbG0bt2a11577azPPXz4MAMGDODee+9l8uTJlZCdiEj1p57jIlJj5OTkOGwnJyfz8ccf06VLl0ovjP/72rm5uSxdupTmzZs7pTCem5tbrB/3ypUrSUlJoVu3blWej4iIiIiIiIhITaO2KiJSY1x55ZV069aNVq1akZiYyPLly8nIyODWW2+t9GvfdtttNGrUiLZt25KRkcHHH3/Mvn37eO655yr92iX5448/mD17NkOHDsXf358dO3bw4Ycf0qZNG4YOHeqUnEREREREREREahIVx0Wkxrjooov4/PPPWbZsGSaTiXbt2vHkk0/StWvXSr92nz59+PDDD1m9ejVWq5Xw8HBeeOEFLr744kq/dkkaN25MgwYNWLhwIampqfj5+TFixAjuvvtu3NzcnJKTiIiIiIiIiEhNop7jIiIiIiIiIiIiIlLnqOe4iIiIiIiIiIiIiNQ5Ko6LiIiIiIiIiIiISJ2jnuPlcMEFF5CXl0dISIizUxERERGRCpaQkICbmxu//vqrs1ORKqRnfBEREZHa6Wye71UcL4fc3FysVquz0xARERGRSlBQUICW4al79IwvIiIiUjudzfO9iuPlUL9+fQDWrVvn5ExEREREpKINGDDA2SmIE+gZX0RERKR2Opvne/UcFxEREREREREREZE6R8VxEREREREREREREalzVBwXERERERERERERkTpHxXERERERERERERERqXO0IKeIiEg1ZLVayc/Pd3YaIjWeq6srFovF2WmIiIiIiEg1pOK4iIhINWIYBsePHyclJcXZqYjUGv7+/jRo0ACTyeTsVEREREREpBpRcVxERKQaKSqM169fH09PTxXzRM6DYRhkZWVx4sQJABo2bOjkjEREREREpDpRcVxERKSasFqt9sJ4UFCQs9MRqRU8PDwAOHHiBPXr11eLFRERERERsdOCnCIiItVEUY9xT09PJ2ciUrsU/Z1SH38RERERETmdiuMiIiLVjFqpiFQs/Z0SEREREZGSqDguIiIiIiIiIiIiInWOiuMiIiIiIiIiIiIiUueoOC4iIiLVTmxsLI8//niVnVceM2bMYPjw4ZUytoiIiIiIiFQ9F2cnUBUeeughPvjgA/766y9npyIiIiLlMHfuXHx9favsPBEREREREal7an1x/Mcff6SgoMDZaYiIiEg55OTk4O7uTrt27c7p/HM9T0RERESkMlhtBjv2JXEyLYdAX3fatQzCYtZi4VVJ74GcSbVrq3Lw4EFmzpzJiBEjaNeuXalfX967dy/XX389HTt2pHfv3jzzzDPk5eU5xGRlZfHCCy9w3333VUXqIiIi8i9ffPEFI0aMIDo6mj59+jB79mxyc3MB2LRpExEREXz77bfcfvvtdO7cmTvuuAMouT3KkiVL6N+/Px06dOD6669nx44dRERE8NFHH9lj/n1eUSuUTZs2MXLkSDp27MiYMWPYtm2bw9hvvfUWo0ePpkuXLvTs2ZMpU6awf//+yrotIiIiIlIH/PjnUSbP+oIHXt3Ac+/9xgOvbmDyrC/48c+jzk6tztB7IGWpdsXx3bt3s379epo1a0arVq1KjElNTWXixInk5+czZ84cpk+fzrJly3j66acd4v773/9y7bXXEhAQUBWpi4iIyGnWrVvH7bffTnh4OPPmzeOGG25gyZIl3HPPPQ5xDz/8ME2aNGHevHlMmjSp1LEeeeQRevfuzdy5c+nZsyd33nlnufJISEhg1qxZTJ48mRdffJHc3Fxuu+028vPz7THHjx9n/PjxvPLKK8yaNQubzca4ceNISUk515cvIiIiInXYj38eZfY7v5CUmuOwPyk1h9nv/KLibBXQeyDlUe3aqsTGxjJw4ECgcLbXv2d2QeHMsczM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6n7/VRwXERERkQrx7rvv0q9fvwotjouIiFSVpNRstu0tnBW+fV8iPaIacu3F7QBo2cgPE9AoxJuoVkFEtQyifctgQgLKv0Ch1GwFNitrd3/DB9s/ITs/B4DeTS/gmg6Xn9VimSJSvag4LiIiItVGXl4eLi4u1eJrdjk5Obi7uzs7DacyDIP8/Hzc3NycnYqIiEiFK7DaWP/7YbbtTWL7viSOJWU6HPf2SLL/7OXhyqLHh+Hjqf8m1lU2w8ba3d+SnZ9Di4AmXN9pLG1Dwp2dloicJ+f/5ikiIiK10owZMxg+fDjr169n+PDhREdHM2rUKP744w97TGxsLI8//jhvvPEG/fv3JyYmhpSUFGw2G6+88gqxsbFERUUxdOhQlixZ4jD+nDlz6NSpE3/++SdjxowhOjqaYcOG8c033xTL5dtvv+WKK64gJiaGHj168Mgjj5CVlWU/vmnTJiIiIvj222+5/fbb6dy5M3fccUexcb7++msiIiI4cOCAw/7U1FRiYmJ47733ynVv0tPTufvuu+nUqRM9e/bkv//9L2+99RYREREOcWlpaTz66KP06dOHqKgoRo0axQ8//OAQM2HCBKZMmcLatWsZMmQInTp14tprr+Xvv/92iMvLy+O///0v/fv3JyoqimHDhrF69WqHmNPfs8suu4zo6Gi+/vprsrKyePzxxxkyZAgdOnQgNjaWmTNnkp6ebj83NjaWI0eO8N577xEREUFERAQfffSR/fhHH33EpZdeSnR0NH379uWFF17AarU6XP/3339n1KhRREdH2/MQERGpCIZhcCQhgy27E+z7LGYTb63ezle//M2xpEzMJggP82PEha148PpuPDSpu8MYKozXPcfST2C1FT6vuFlcmdR5HDd3ncDsQTNUGBepJTRzXERERCpNQkICjz32GNOmTcPX15c33niDyZMn88UXXxAUFATAF198QbNmzXjwwQcxm814enryzDPP8O6773LLLbfQqVMnvv32Wx555BEKCgoYP368ffz8/HymT5/OpEmTCAsLY/Hixdx222189NFH9kLz2rVrmT59OqNGjWLatGkkJCTw/PPPk5aWxgsvvOCQ78MPP8xll13GvHnzSpy9ftFFFxEaGsry5cu566677PvXrFkDwKWXXlqu+3L//fezceNG7rnnHho3bsyyZcvYvn27Q0xeXh7XX389SUlJ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Xbp04dZbb+XkyZMOcXv37mX8+PFER0czcOBAVqxYUWIuv/zyC+PGjSMmJobu3btz//33k5KSYj9++PBhIiIiWLlyJTNnzuSCCy6gZ8+evP322wB88sknDBkyhM6dO3PbbbeRlpZW6uueNm0a48aNK7b//fffJzo62uG6Z/Lrr78ycuRIoqOjufTSS9mwYQMjRoxgxowZDnGbN2/m2muvpWPHjnTp0oW77rqLpKSkYq9t1apVPP7443Tt2pU+ffrwn//8h4KCAoex9u7dyy233EKXLl3o2LEjN910E3///bdDTEREBK+//jrPPvssvXv3pmfPnvY8br75Zvr06UPHjh0ZMWIEK1eutJ+3adMmrr32WgDGjBlDREQEERER9uNpaWk8+uij9OnTh6ioKEaNGsUPP/xQ7L688sor9O7dm06dOnHbbbc5vFap2dLS0vD19S2238/Pj9TUVABCQkK47777uOGGG7jssst46623ePLJJ6s6VREpw8ZTs8bbtwzGz7uek7OR6qjAZuXTXV9zxycz+XLv9+Rb8/nlyBZnpyUidZAaf4mIiEilOXHiBLNmzeKWW26hYcOGeHl58ccffzB9+nQCAwM5duwY8+fP59Zbb2XhwoUO53799dccPHiQmTNnkpyczOzZs3niiSd44YUXAMjNzWXSpEl4eHjwzDPPAPDyyy+TkZFB8+bN7eNs27aN66+/nu7du/PSSy+RmJjI888/z549e1iyZAkWi8Ue++KLLzJ48GBeeuklvvrqK55++mlOnjzJzz//zD333ENGRgazZs3i2Wef5YknnijxNV9xxRXceOONxWbBLl++nEGDBjm0jDjTfbvxxhtp164dL774Iunp6Tz66KOkp6cTGRlpj9u8eTMTJkzgoosu4oUXXiA7O5sXX3yRW2+9laVLlzqM+eKLLzJgwABefPFFNm/ezJw5c2jatClXXXUVAIcOHWLcuHG0bt2ap59+GpPJxPz587nuuutYu3Ytbm5u9rHeffddOnTowJNPPmkvsB89epTOnTtz1VVX4ebmxu+//85DDz2EYRhcfvnltG/fnpkzZ/L4448ze/Zsh3uTl5fH9ddfT1JSEnfeeSehoaF8/PHHTJkyhY8++sheRF+0aBEvvfQSkyZNolevXvz44488+OCDZd5PqV1Gjx7N6NGjnZ2GiJzBT1uLWqo0dHImUh39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PM4/uIkwTLOiNYdSYsyYMQBERUW5OImIiIiI1DR9r9c0NZU/9/jvPuP/otczc/QjtA/v5uo4IiJNTm5uLgkJCXTs2LFMYdaen1vxjRYLFrffC5i23GyOvvIQtswzFd5i9Q+h3az/YBae492whoHF3bPS+UubN28ee/fuZe7cubzwwgscPnyYrl27Mn/+fC6++GKgqGXJqFGjaN26NW+//TYnTpxg+/btBAYGsnz5ct577z1OnTpFWFgYd955J9OmTXPMv2TJEv773//yxhtv8Mwzz7Bv3z7CwsL485//zOWXX+6U5auvvmLZsmXs27cPHx8frrrqKh577DF8fHwA2LVrF7fffjuvvPIK77//Pt988w39+/fnlVdecWScP38+X3zxBTNmzGDjxo106NDBMX9aWhrDhw/nscce49Zbbz3v5yYjI4MFCxYQFRWFl5cXN954I4GBgTz//PPs2/f73l/p6en84x//YPPmzaSmptKtWzf+9Kc/MWzYMMeYP/zhD/j4+DBx4kReeuklTp06Re/evXn22Wdp166dY1x+fj5Lly7lo48+IikpifDwcGbOnMn48ePL/TNbvHgxBw8e5MUXX2TEiBG8+OKLbNu2jZMnTxISEsKwYcOYO3cufn5+jj/LY8eOOb3O5557jkmTJgHw/vvv89prr3Ho0CECAwOZNGkSDz74IFbr75uB/fjjjzz77LPEx8fTvn175s6dyz/+8Q8iIiJYuHDheT+v53Kur62qfJ+nleMiIiIiIiKN0E9b32HpkSgyvKz884vlvHTHP1wdSURESjn0QsVFV+/Ol9B62l8cx4f/eTfYzt0C0paeTO6RGBLfX4w9O73cMZ6tO9P27kXVCwwkJSWxYMECZs+ejb+/P6+++ip//OMf2bRpEyEhRa08N23aRPv27fnLX/6CxWLBx8eHRYsW8eabbzJjxgz69evHV199xVNPPUVhYSG33XabY/6CggLmzJnD3XffTVhYGKtXr+aBBx7g/fffp3v37gBs2LCBOXPmMGnSJGbPnk1SUhKLFy8mPT2dl156ySnvk08+yfXXX8+yZcvKXb0+cuRIWrZsydq1a3nkkUcc5z/++GMAp0LzuTz++OPs3LmTuXPn0rZtWyIjI/n111+dxuTn53PXXXeRnJzMww8/TMuWLfnwww+ZPn260+sDiImJ4cyZMzz66KPYbDYW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/lJxXEREREREpIE4GLODF75/jWRPK16FJhPCbmLyyMtdHUtERKTBeuqpp/j5558ZPnw406dPL3O9sLCwwnsNw8BqteLj48MHH3zAoUOHKCgooFOnTrzwwguMHTu2NqNLDVBxXEREREREpAE4fiSev//4OukeVpoVwC097mXsZZe6OpaIiDQRCxcurNX5Z8+ezezZs2v1GeU5V9uTo0ePOlp0lGfAgAG89dZbDB8+nOHDh9dGPKllKo6LiIiIiIg0AC3bdqFdXhBHbenc0/8hBkR0d3UkERGRRq1Fixa89957FV739fWtwzRSG1QcFxERERERqcfstkIsVjesFoPHbvsbR5OS6dy2latjiYiINHoeHh707t3b1TGkFllcHUBERERERETKMk2T9z74J/NWPUR2TiYAnh7uKoyLiIiI1BAVx0VEREREROoZ0zR5491neTcnlkNedl79aIWrI4mIiIg0OmqrIiIiIiIiUo/YbYX8e82TbHVLBcOgU1YQ99zygKtjiYiIiDQ6Ko6LiIiIiIjUE7aCPF5Y/Tg/euYAEJHdhr/84XE83PWjm4iIiEhN03dYIiIiIiIi9UBedjp/f/cvxHgVYpgm/Qq6MfeOOVgthqujiYiIiDRKKo6LiIiIiIjUA7/Gx5Dgno/FNBhmuZRZt92DYagwLiIiIlJbtCGniIiIiIhIPXBJ34FMan4143xG8sDUe1UYFxGRctntdn49Fcc3h7/j11Nx2O12V0eqVTNnzuQPf/hDnT1v165ddO/enT179tTZMxuqo0ePsmTJEhITE2tszpiYGLp3786uXbtqbM5zadQrxw8cOMCf//xnMjMzadmyJS+++CItWrRwdSwREREREREADh+K5rdThxk+4GoAbrjyBtcGEhGRem3X0Z94/cdIknNSHedCvAO585KpDAzr57pg0iQdO3aMpUuXMmrUKFq2bOnqONXSqFeOP/XUU8yYMYONGzcyZswYFi9e7OpIIiIiIiLSBNlsBfz4y0Y2b3uLH3/ZiM1WwK/RO/nbNy/zyv4P+G73VldHFBGRem7X0Z9YvG2FU2EcIDknlcXbVrDr6E91msc0TfLz8+v0mVL7cnNzXR2hTtW74vjhw4eZP38+EyZMoGfPnlx33XXljjtw4AB33XUXF198MUOHDmXRokVOX5CnT5/m0KFDjB07FoApU6bw+eef18lr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PphMpj81npLjIiIiIiIiIiIiJaRq1aoA1gS5iPx5Pj4+1u+tP0PJcRERERERERERkRJiMBjw9/encuXKZGVlOTockTueq6vrn14xnkvJcRERERERERERkRJmMpmKLaEnIsVDN+QUEREREREREREREaej5LiIiIiIiIiIiIiIOB0lx0VERERERERERETE6Sg5LiIiIiIiIiIiIiJORzfkLITY2FhycnLo0KGDo0MRERERkWJ2/vx53RzLCek1voiIiMjd6VZe32vleCGUKVMGFxe9jyAiIiJyN3JxcaFMmTKODkNKmV7ji4iIiNydbuX1vcFisVhKOB4RERERERERERERkduKVo6LiIiIiIiIiIiIiNNRclxEREREREREREREnI6S4yIiIiIiIiIiIiLidJQcFxERERERERERERGno+S4iIiIiIiIiIiIiDgdJcdFRERERERERERExOkoOS4iIiIiIiIiIiIiTkfJcRERERERERERERFxOkqOi4iIiIiIiIiIiIjTUXJcRERERERERERERJyOkuMiIiIiIiIiIiIi4nSUHBcRERERERERERERp6Pk+B3qxIkTdO/enU6dOjFw4EBiY2MdHZLcISZPnkybNm0IDAx0dChyB0lMTGTo0KF06tSJJ554ghdffJGrV686Oiy5A5jNZnr37k14eDhPPPEEY8eOJTU11dFhyR3mlVde0e8tuaOdOHGCZ555hqZNmxIWFsasWbP0e7QUnT59msmTJxMeHk5QUBBdunRxdEhO5aOPPmLkyJG0bduWpk2bEh4eznvvvYfFYnF0aE5h79699O/fnwceeIDg4GA6dOjAjBkzSElJcXRoTufKlSu0bduWwMBAvv/+e0eH4xS2bdtGYGCg3b/Zs2c7OjSnsn37dp588klCQkIIDQ1l6NChZGRkODosKxdHByBFM2XKFEaOHEnHjh1Zs2YNc+bM4c0333R0WHIHyE1OhYWFOToUuYMYDAYiIyNp0aIFZrOZv/3tb6xbt47Bgwc7OjS5zRmNRlauXImHhwcAM2bMYMWKFYwbN86xgckdY//+/WRnZzs6DJEiS0pK4umnn6Z27dpERUVx8eJFZs6cSUZGBpMnT3Z0eE7h2LFj7N27lyZNmmA2m5WULWWrV6+mevXqTJo0iQoVKrB//35effVVLly4wJgxYxwd3l3v8uXLNG7cmAED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jx6lYcOGACQmJvLDDz8waNAgxwaXh5LjtxmtLJGi0tyRotLckaLS3JGi0twRZ9KnTx/Wrl3L6NGjiYyM5OLFi8yaNYs+ffooSVhK0tPT2bt3L3CtzEFqairR0dEAtGzZEl9fX0eGd9ebOnUq//3vf5k0aRKpqakcPnzY2hYUFISbm5vjgnMCY8aMITg4mMDAQMqWLctPP/3EypUrCQwM1L3LSpiXlxehoaH5tjVq1IhGjRqVckTOZ8iQIYSGhhIYGAjA7t272bx5MwMHDtR9bEpBx44dCQkJYezYsYwfP54yZcqwbNky3Nzc6Nevn6PDs1Jy/DajlSVSVJo7UlSaO1JUmjtSVJo74ky8vb1Zs2YNb7zxBqNHj6Z8+fL06NGD8ePHOzo0p5GQkMBzzz1nsy93+5133ikweSXFY9++fUD+5R13796t1cslrHHjxnz44YcsW7YMi8VC9erV6dmzJ0OGDNEbE3LXq1OnDlu3buXChQuYzWZq167NSy+9xIABAxwdmlMwGo0sW7aMGTNmMHnyZLKysrj//vtZv379bfXmhMFisVgcHYSzyLtiYf369Zw5c4ZJkyYBf6xYSEpKonPnztSpU8e6smTmzJk88cQTTJ482ZHhiwNp7khRae5IUWnuSFFp7oiIiIiIyJ1CyfFSdPbsWTp06JBvW94VCydOnOCNN97g0KFDlC9fnvDwcMaPH693dZ2Y5o4UleaOFJXmjhSV5o6IiIiIiNwplBwXEREREREREREREadjdHQAIiIiIiIiIiIiIiKlTclxEREREREREREREXE6So6LiIiIiIiIiIiIiNNRclxEREREREREREREnI6S4yIiIiIiIiIiIiLidJQcFxERERERERFxkAMHDhAYGEh0dLSjQymU+Ph4xo4dS2hoKIGBgaxevTrffmfPniUwMJCVK1eWboAiIrdAyXERERERERERuatt27aNwMBAQkJCuHjxol37gAED6NKliwMiu/PMmDGDzz77jOHDhzNr1izatGnj6JBERIpMyXERERERERERcQpXr15l2bJljg7jjvbll1/SoUMHhgwZQnh4OPXq1XN0SCIiRabkuIiIiIiIiIg4hYYNG7J58+Z8V4/f7dLS0oplnISEBLy8vIplLBERR1NyXEREREREREScQmRkJGazmeXLl9+wX2697G3bttm1BQYGEhUVZd2OiooiMDCQkydP8re//Y3mzZvzwAMPMG/ePCwWC+fPn2fkyJE0a9aMsLAwVq1ale85zWYzc+fOJSwsjKZNmzJixAjOnz9v1+/bb79lyJAhNG/enCZNmtC/f3++/vprmz65MR0/fpznn3+eFi1a0K9fvxs+5jNnzjB27FhatmxJkyZN6NWrF5988om1Pbc0jcViYf369QQGBhIYGHjDMXNt2rSJjh07EhwcTPfu3fnuu+/s+nzxxRf069ePpk2bcv/99zNy5EhOnDiR7+M6ceIEzz33HM2aNSM0NJRp06aRmZlp03ffvn307duX+++/n/vuu49OnToxd+7cQsUrIs7DxdEBiIjIzW3bto0XX3zRuu3m5oa3tzeBgYG0a9eOiIgIPDw8HBihiIiIiMjtLyAggPDwcDZv3sywYcOoUqVKsY09fvx46tWrx/PPP8/evXtZvHgxPj4+bNy4kQceeIC//e1vfPDBB7z55puEhITQokULm+MXL16MwWBg2LBhJCQksGbNGgYNGsSOHTsoW7YscC2BPGzYMIKDgxkzZgwGg4Ft27bx9NNPs2HDBho3bmwz5nPPPUetWrUYP348FoulwNjj4+Pp06cP6enpDBgwgAoVKrB9+3ZGjhzJ22+/zSOPPEKLFi2YNWsWEyZMICwsjPDw8EJdl3/9619cuXKF3r17YzAYWLFiBc8++ywff/wxrq6uAOzfv59hw4YREBDAmDFjyMjIYN26dfTt25dt27YREBBgM+a4ceOoXr06zz//PIcPH2bt2rUkJycza9YsAI4dO0ZkZCSBgYGMHTsWNzc3Tp8+zTfffFOomEXEeSg5LiJyBxk7diwBAQFkZ2cTHx/PV199xd///ndWr17NokWLuPfeex0dooiIiIjIbW3kyJHs2LGD5cuX88orrxTbuI0bN+b1118HoHfv3rRv356ZM2fy17/+leHDhwPQpUsX2rRpw9atW+2S40lJSXz44YfWRS9BQUGMGzeOzZs3M3DgQCwWC6+99hqhoaGsWLECg8EAQJ8+fejcuTPz5s2zW5V+7733MmfOnJvGvmzZMuLj41m/fj33338/AD179qRr167MmDGDDh06UKNGDWrUqMGECROoXbt2oZPjv/32G//+97/x9vYGoE6dOowaNYrPP/+chx9+GIBZs2bh7e3Npk2b8PHxAaBjx45069aNqKgo3nzz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y9rtM5vNhIWFMXTo0HyPyS21YjabqVixIrNnz8633/U3KhIRERERKWm1atWia9eubN++3a5t9OjRXLp0iV27dvHRRx/Rtm1bVqxYUeBijz9rxIgR/PzzzyxbtowrV67QqlUrpkyZQrly5ax9QkND2bRpE4sWLWLdunWkpaXh5+dH48aN6d27d5HPXalSJTZu3Mg//vEP1q1bR2ZmJoGBgSxZsoSHHnqoGB7djbVu3ZoVK1bw9ttv8/bbb+Pi4kKLFi144YUXbMqn5Jo3bx7z589nzpw5uLi40L9/fyZMmGBtb9++PefOnWPr1q0kJiZSoUIFWrZsybPPPounp2eJPx4RuXMYLMV5BwQRESkR27Zt48UXX+S9994jJCTErn3p0qXMnTuXadOm0b59e1q3bk1kZCR//etfbzhup06dqFChAhs3brTZP23aNNauXcvu3butq8Xbt29PgwYNWLp0qU3fzp074+npaTfG9aZOncqmTZv45ptv8k2yi4iIiIiI3EhUVBQLFizgiy++0OIaESkWqjkuInKH++KLL1i0aBEBAQF07dqVihUr0rJlSzZt2kRsbKxd/7y1CB988EEOHz7M0aNHrfsuX77MBx98UOjzP/bYYxw6dIjPPvvMri05OZns7Gxrv5ycHBYtWmTXLzs72+5mRyIiIiIiIiIiJUllVURE7iCffvopMTEx5OTkEB8fz4EDB9i3bx/VqlVj8eLFlClTBoApU6bQr18/nnjiCXr16kWNGjWIj4/n8OHDXLhwgZ07dwIwdOhQdu7cyTPPPEP//v1xd3dny5Yt+Pv7c/nyZQwGw01jGjJkCHv27GHEiBF069aNRo0akZ6ezi+//MKuXbvYvXs3vr6+tGzZkt69e7N06VKOHj1KWFgYrq6unDp1iujoaF5++WUeffTREr1+IiIiIiIiIiK5lBwXEbmDvP322wC4urri4+PDPffcw0svvURERAQeHh7WfvXr12fr1q0sWLCA7du3c/nyZXx9fQkKCmL06NHWfv7+/rzzzjtMmzaNpUuX4uvry1NPPUW5cuWYNm2aNdl+I+XKlWPt2rUsXbqU6Oho3n//fTw8PKhdu7ZdTb/XX3+d4OBgNm7cyFtvvYXJZKJ69ep07dqVZs2aFeOVEhERERERERG5MdUcFxERO9OnT2fTpk0cOnQIk8nk6HBERERERERERIqdao6LiDi5jIwMm+3ExER27txJ8+bNlRgXERERERERkbuWyqqIiDi53r1707JlS+rVq0d8fDxbt24lNTWVUaNGOTo0EREREREREZESo7IqIiJObu7cuezatYsLFy5gMBgICgpizJgxtG7d2tGhiYiIiIiIiIiUGCXHRURERERERERERMTpqOa4iIiIiIiIiIiIiDgdJcdFRERERERERERExOkoOS4iIiIiIiIiIiIiTkfJcRERERERERERERFxOkqOi4iIiIiIiIiIiIjTUXJcRERERERERERERJyOkuMiIiIiIiIiIiIi4nSUHBcRERERERERERERp/P/sgVFnbgpVQcAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from matplotlib.pyplot import set_loglevel\n", + "set_loglevel('warning')\n", + "_ = graph_analyser.compare_graph_plots(*all_graphs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "158eb71d", + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/performance/struct_generator.ipynb b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/performance/struct_generator.ipynb new file mode 100644 index 000000000..2f736ecc8 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/performance/struct_generator.ipynb @@ -0,0 +1,1311 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "2da8f4bf", + "metadata": {}, + "source": [ + "# Copyright 2023 NVIDIA Corporation. All Rights Reserved.\n", + "#\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# http://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License.\n", + "# ==============================================================================" + ] + }, + { + "cell_type": "markdown", + "id": "f987a4b2", + "metadata": {}, + "source": [ + "# Graph structure generation demo" + ] + }, + { + "cell_type": "markdown", + "id": "eb1caeed", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "In this notebbok we compare the performance (throughput) of graph structure generators presented in the SynGen tool. \n", + "\n", + "Available generators:\n", + "\n", + "1. [Exact RMAT generator (GPU)](#1)\n", + "1. [Exact RMAT generator (CPU)](#2)\n", + "1. [Approximate RMAT generator (GPU)](#3)\n", + "1. [Approximate RMAT generator (CPU)](#4)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f8a1adaf", + "metadata": {}, + "outputs": [], + "source": [ + "# Generator\n", + "from syngen.generator.graph import RMATGenerator\n", + "\n", + "# Others\n", + "import numpy as np\n", + "import pandas as pd\n", + "from matplotlib import pyplot as plt\n", + "from matplotlib.pyplot import set_loglevel\n", + "set_loglevel('warning')\n", + "\n", + "import time\n", + "from itertools import product" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cb6937d3", + "metadata": {}, + "outputs": [], + "source": [ + "def get_xy(data):\n", + " x = [edges for edges, _, _ in data]\n", + " y = [eps for _, eps, _ in data]\n", + " return x, y" + ] + }, + { + "cell_type": "markdown", + "id": "ad27d92d", + "metadata": {}, + "source": [ + "## Exact generator" + ] + }, + { + "cell_type": "markdown", + "id": "06dadc04", + "metadata": {}, + "source": [ + "\n", + "### GPU" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a8bf077d", + "metadata": {}, + "outputs": [], + "source": [ + "static_graph_generator=RMATGenerator()\n", + "static_graph_generator.gpu=True" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "01bc4461", + "metadata": {}, + "outputs": [], + "source": [ + "static_graph_generator._fit_results = 0.4, 0.25, 0.2, 0.15" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e52f19c4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "7.293178725987673\n", + "CPU times: user 6.46 s, sys: 828 ms, total: 7.29 s\n", + "Wall time: 7.29 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "start = time.perf_counter()\n", + "data_proper = static_graph_generator.generate(num_nodes=6_797_556, \n", + " num_edges=168_114, \n", + " is_directed=False, \n", + " has_self_loop=False)\n", + "elapsed = time.perf_counter() - start\n", + "\n", + "print(elapsed)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "7271985d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "32768 | 500000 | 0.001 | GOOD\n", + "32768 | 500000 | 30149058.191003423\n", + "32768 | 5000000 | 0.009 | GOOD\n", + "32768 | 5000000 | 66238388.90034665\n", + "32768 | 50000000 | 0.093 | GOOD\n", + "32768 | 50000000 | 41812037.20361726\n", + "1048576 | 500000 | 0.000 | GOOD\n", + "1048576 | 500000 | 18619575.259240218\n", + "1048576 | 5000000 | 0.000 | GOOD\n", + "1048576 | 5000000 | 59722279.57953148\n", + "1048576 | 50000000 | 0.000 | GOOD\n", + "1048576 | 50000000 | 53988712.53175938\n", + "1073741824 | 500000 | 0.000 | GOOD\n", + "1073741824 | 500000 | 19100514.208435934\n", + "1073741824 | 5000000 | 0.000 | GOOD\n", + "1073741824 | 5000000 | 56473505.243410945\n", + "1073741824 | 50000000 | 0.000 | GOOD\n", + "1073741824 | 50000000 | 41909925.854350075\n", + "1099511627776 | 500000 | 0.000 | GOOD\n", + "1099511627776 | 500000 | 19101824.4671729\n", + "1099511627776 | 5000000 | 0.000 | GOOD\n", + "1099511627776 | 5000000 | 63599937.77316937\n", + "1099511627776 | 50000000 | 0.000 | GOOD\n", + "1099511627776 | 50000000 | 48575986.96059752\n" + ] + } + ], + "source": [ + "n_range = [15, 20, 30, 40]\n", + "n_range = [2 ** x for x in n_range]\n", + "\n", + "edges_range = [1e6, 1e7, 1e8]\n", + "edges_range = [int(x // 2) for x in edges_range]\n", + "\n", + "gpu_res = {\n", + " int(np.log2(n)): [] for n in n_range\n", + "}\n", + "\n", + "# Random run\n", + "data_proper = static_graph_generator.generate(num_nodes=168_114, \n", + " num_edges=6_797_556, \n", + " is_directed=False, \n", + " has_self_loop=False)\n", + "\n", + "for n, edges in product(n_range, edges_range):\n", + " max_edges = (n * (n - 1)) // 2\n", + " density = edges / max_edges\n", + " \n", + " \n", + "\n", + " if density > 0.75:\n", + " res = \"FAIL\"\n", + " else:\n", + " res = \"GOOD\"\n", + " \n", + " f_string = f\"{n:<13} | {edges:<13} | {density:>8.3f} | {res}\"\n", + " print(f_string)\n", + " \n", + " if res == \"FAIL\":\n", + " continue\n", + " \n", + " start = time.perf_counter()\n", + " data_proper = static_graph_generator.generate(num_nodes=n, \n", + " num_edges=edges, \n", + " is_directed=False, \n", + " has_self_loop=False)\n", + " elapsed = time.perf_counter() - start\n", + " gen_edges = data_proper.shape[0]\n", + " edges_per_second = data_proper.shape[0] / elapsed\n", + " \n", + " calculated = (gen_edges, edges_per_second, elapsed)\n", + " f_string = f\"{n:<13} | {edges:<13} | {edges_per_second}\"\n", + " print(f_string)\n", + "\n", + " \n", + " l = gpu_res[int(np.log2(n))]\n", + " l.append(calculated)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "99412af6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(15, 6))\n", + "for n, data in gpu_res.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--x', label=f'{n}')\n", + " plt.xlabel('Total edges to generate') \n", + " plt.ylabel('Edges per seconds')\n", + " \n", + " plt.legend()\n", + "\n", + " plt.legend()\n", + " plt.yscale('log')\n", + " plt.xscale('log')" + ] + }, + { + "cell_type": "markdown", + "id": "7b20c540", + "metadata": {}, + "source": [ + "\n", + "### CPU" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "09ae86bd", + "metadata": {}, + "outputs": [], + "source": [ + "static_graph_generator=RMATGenerator()\n", + "static_graph_generator.gpu=False" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "a92affa3", + "metadata": {}, + "outputs": [], + "source": [ + "static_graph_generator._fit_results = 0.4, 0.25, 0.2, 0.15" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "f939a153", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 20/20 [00:19<00:00, 1.03it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "32768 | 500000 | 0.001 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.21it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "32768 | 500000 | 286622.14685093396\n", + "32768 | 5000000 | 0.009 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 15/15 [00:12<00:00, 1.23it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "32768 | 5000000 | 231044.87284503193\n", + "32768 | 50000000 | 0.093 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 150/150 [02:01<00:00, 1.24it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "32768 | 50000000 | 199421.84570897938\n", + "1048576 | 500000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:01<00:00, 1.13s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1048576 | 500000 | 254579.08768802948\n", + "1048576 | 5000000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 15/15 [00:16<00:00, 1.09s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1048576 | 5000000 | 215829.47480641145\n", + "1048576 | 50000000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 150/150 [02:42<00:00, 1.08s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1048576 | 50000000 | 185111.12465822973\n", + "1073741824 | 500000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:01<00:00, 1.65s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1073741824 | 500000 | 218091.72153399212\n", + "1073741824 | 5000000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 15/15 [00:24<00:00, 1.61s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1073741824 | 5000000 | 190558.21969355037\n", + "1073741824 | 50000000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 150/150 [04:00<00:00, 1.60s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1073741824 | 50000000 | 165485.3641681028\n", + "1099511627776 | 500000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:02<00:00, 2.23s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1099511627776 | 500000 | 185084.37433352097\n", + "1099511627776 | 5000000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 15/15 [00:32<00:00, 2.15s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1099511627776 | 5000000 | 164205.47140813377\n", + "1099511627776 | 50000000 | 0.000 | GOOD\n", + "Getting egdes\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 150/150 [05:22<00:00, 2.15s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing selfloops\n", + "1099511627776 | 50000000 | 146195.08370605359\n" + ] + } + ], + "source": [ + "n_range = [15, 20, 30, 40]\n", + "n_range = [2 ** x for x in n_range]\n", + "\n", + "edges_range = [1e6, 1e7, 1e8]\n", + "edges_range = [int(x // 2) for x in edges_range]\n", + "\n", + "cpu_res = {\n", + " int(np.log2(n)): [] for n in n_range\n", + "}\n", + "\n", + "# Random run\n", + "data_proper = static_graph_generator.generate(num_nodes=168_114, \n", + " num_edges=6_797_556, \n", + " is_directed=False, \n", + " has_self_loop=False)\n", + "\n", + "for n, edges in product(n_range, edges_range):\n", + " max_edges = (n * (n - 1)) // 2\n", + " density = edges / max_edges\n", + " \n", + " \n", + "\n", + " if density > 0.75:\n", + " res = \"FAIL\"\n", + " else:\n", + " res = \"GOOD\"\n", + " \n", + " f_string = f\"{n:<13} | {edges:<13} | {density:>8.3f} | {res}\"\n", + " print(f_string)\n", + " \n", + " if res == \"FAIL\":\n", + " continue\n", + " \n", + " start = time.perf_counter()\n", + " data_proper = static_graph_generator.generate(num_nodes=n, \n", + " num_edges=edges, \n", + " is_directed=False, \n", + " has_self_loop=False)\n", + " elapsed = time.perf_counter() - start\n", + " gen_edges = data_proper.shape[0]\n", + " edges_per_second = data_proper.shape[0] / elapsed\n", + " \n", + " calculated = (gen_edges, edges_per_second, elapsed)\n", + " f_string = f\"{n:<13} | {edges:<13} | {edges_per_second}\"\n", + " print(f_string)\n", + "\n", + " \n", + " l = cpu_res[int(np.log2(n))]\n", + " l.append(calculated)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "68c523f8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(15, 6))\n", + "for n, data in cpu_res.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--x', label=f'{n}')\n", + " plt.xlabel('Total edges to generate') \n", + " plt.ylabel('Edges per seconds')\n", + " \n", + " plt.legend()\n", + "\n", + " plt.legend()\n", + " plt.yscale('log')\n", + " plt.xscale('log')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "f45ad186", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAJpYAABDBCAYAAAAkfZD3AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAHsIAAB7CAF4JB2hAAEAAElEQVR4nOzdd7RtVXk34N97uBRBihoRKyoiYsWCDRWwx27sDbtGjX6aaOy9BzW2WGMBNVFMjN0Yo1iiIoq9xgZWrFERUSnv98c6SBG4Z++z9ln33Ps8Y+yBw7veOX9nnbnnmnPucfet7g4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABu3NHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBeLE0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgvViaOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHqxNHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID1YmnqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68XS1AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaLpakDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsF0tTBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWC+Wpg4AAAAA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4a3q09d1tLsAAAAAAAAAAAAAAAAAAAAAAAAAANB6e++9d63chAkTcuqppza3zD85/vjjM3PmzJbOnF/PPfdcLrnkkpbO7O7uzumnn14r269fv/znf/5nQ+auueaatXK33XZbQ+bV1dXVlV/84hctndkb7bPPPrVyM2bMyAknnNDcMv/k5JNPzksvvdTSmW/4wAc+kP79+9fKnnbaaU1uQ2+2xx571MpNnz49Z511VpPbMC8GDBhQKzdhwoQmN/lXJ598cstn/rNFF120Vu7ll19ucpM3t95662X55Zevlb3jjjty1113NbnRv+rq6sqFF15YO//e9763iW14K0sssUSGDh1aKztlypQmtwEAAAAAAAAAAAAAAAAAABY0He0uAAAAAAAAAAAAAAAAAAAAAAAAAAC03qhRo1JVVa3st771rTz55JNNbvSaW2+9NT/+8Y9bMqvRvvrVr6a7u7tl8y688MI8+uijtbLbbbddllpqqYbMXXvttWvl/vCHPzRkXl1nn312urq6WjqzN/rQhz6UYcOG1cr+6Ec/yh133NHkRq8ZM2ZMvvOd77Rk1ptZYoklsscee9TKXnvttS0/fuk93v/+92fEiBG1sieddFJefPHFJjeip+peA5955pkmN/lHv/3tb3P33Xe3dOabWXLJJWvlnn766SY3mbN99tmndvbrX/96E5u8udNOOy0TJ06sld18882z6qqrNrkRb2X48OG1cgMHDmxyEwAAAAAAAAAAAAAAAAAAYEHT0e4CAAAAAAAAAAAAAAAAAAAAAAAAAEDrrb766vnABz5QKztp0qTsv//+6e7ubmqnrq6ujBo1KrNnz27qnGZ5+OGHc8YZZ7Rk1qRJk/LlL3+5dn7UqFENm73xxhvXyt1+++159tlnGzb3rUyaNCnf+ta3WjKrt1t44YXziU98ola2u7s7o0aNyuTJk5vaadasWS2ZMzef+9znepSdOnVqE9vQW/Xv3z+HHHJIreyrr76ao446qsmN6KllllmmVu6Pf/xjk5v8f1OmTMlhhx3WsnlvZbnllquVe+ihh5rcZM56ct/ym9/8JrfeemsT2/yjl156Kd/5zndq5xt5D0bPdXd358UXX6yV7ezsbHIbAAAAAAAAAAAAAAAAAABgQdPR7gIAAAAAAAAAAAAAAAAAAAAAAAAAQHscffTRtbOjR4/OYYcd1rQu3d3d2WuvvfLYY481bUYrHHPMMRk3blzT5xx11FEZP358reyIESPyoQ99qGGzt9xyy1q52bNn5+yzz27Y3Ldy9NFH54UXXmjJrL7giCOOSP/+/WtlH3744ey7776ZPXt20/p89rOfzU033dS0/evaYostsvnmm9fKPvzwwzn00EOb3Ije6qCDDkpnZ2et7AUXXJCLLrqoyY3oiVVWWaVW7sorr2zqte/vfeELX8jYsWNbMmtuVl999Vq5O+64o8lN5mzdddetfb1OkgMPPDAzZsxoYqP/79Of/nReffXVWtnhw4dnr732anIj3srjjz+e7u7uWtmVVlqpyW0AAAAAAAAAAAAAAAAAAIAFTUe7CwAAAAAAAAAAAAAAAAAAAAAAAAAA7bH55ptnl112qZ3//ve/ny996UsN7zFz5sx89KMfzRVXXNHwvVutq6sre+yxR6ZOndq0GT/5yU9y1lln1c4feuihGTBgQMPmr7nmmlluueVqZb/3ve/l1VdfbdjsN/Ob3/wmZ555ZlNn9DUrrrhiDjnkkNr5yy67LPvvv39mzZrV8C5HHXVUr/p8Tj755NrZs88+O9/+9reb2IbeavHFF+/R990nPvGJXH/99U1sRE9ssMEGtXLPPvtsLrzwwia3SX7605/mBz/4QdPn1LX22mvXyl111VVN+V6o69hjj62dfeCBB3L00Uc3sc1rfvzjH+cXv/hF7fxnPvOZLLzwwk1s1PuUUjJ79ux21/ibH//4x7VyAwYMyOqrr97kNgAAAAAAAAAAAAAAAAAAwIKmo90FAAAAAAAAAAAAAAAAAAAAAAAAAID2OeWUUzJo0KDa+W984xv5yEc+kq6urobMf/7557PjjjvmZz/7WUP26w3uvvvu7LXXXpkxY0bD977mmmvyyU9+snZ++eWXzyGHHNLwHrvvvnut3Msvv5wvfelLDZ//hjvvvDMf/ehHU0pp2oy+6itf+UqWWGKJ2vkLL7wwO+20UyZMmNCQ+RMnTszee++dk046qSH7Ncrmm2+evfbaq3b+6KOPzje/+c0mNuqZUkouu+yyppzX/KPDDz88K6+8cq3s1KlTs8suu+Saa65pbqkemDp1ar73ve/l1FNPbXeVlttiiy1qZ4899tiG3dO8mSuvvDIf+9jHmrb/vNhss81q5SZMmJCf/vSnTW4zZ+9///uz8cYb186feuqpOe+885rW55ZbbsmBBx5YOz9s2LAcfvjhTevTW7366qtZd911c+GFF6a7u7utXV544YWcffbZtbJbbLFFBgwY0ORGAAAAAAAAAAAAAAAAAADAgqaj3QUAAAAAAAAAAAAAAAAAAAAAAAAAgPZZbbXV8qUvfalHa376059mgw02yKWXXjrPc7u7u/PDH/4w66+/fq699to55jbYYIN5ntFOv/3tb7Prrrvm1Vdfbdiel156aXbZZZdMmzat9ppvfvObGTZsWMM6vGHPPfesnT3jjDPyq1/9quEdbrrppmy//fbp6upq+N4LgkUXXTQnn3xyj9b84Q9/yHrrrZdzzz033d3d8zz7kksuyQYbbJCLL754jpl2ntunnnpqllpqqdr5Y445Jvvvv39bj7UpU6bknHPOyfrrr5/ddtstd955Z9u6vF0MGjQo55xzTqqqqpWfNGlSdtxxx5x22mkppTS53Zw999xz+epXv5qVV145hx56aJ5++um2dWmXddddNyuvvHKt7DPPPJMPfehDmTlzZsN7XHzxxdljjz0yY8aMhu89P9Zee+0sscQStbKHH3547rnnnuYWegunnHJKj/IHHnhgLrjggob3uPnmm7Pjjjtm+vTptdccd9xxtd/nBc3DDz+c/fbbL6uvvnpOOeWU/PWvf215h1mzZmXffffNiy++WCu/8847N7kRAAAAAAAAAAAAAAAAAACwIOpodwEAAAAAAAAAAAAAAAAAAAAAAAAAoL2OPfbYbLnllj1aM2bMmOyxxx7ZcMMNc8YZZ+S5556rte6JJ57IN77xjayxxho56KCD8uKLL84xu/vuu2e33XbrUa9WGzx48Bx/d/XVV2eTTTbJLbfcMl8zJk+enCOOOCJ77LFHpk2bVnvdlltumX333Xe+Zr/V3uuss06tbCklH/nIR3L55Zc3ZHYpJd/73vey7bbb5tVXX23Inguq/fbbL3vvvXeP1kyYMCGf+MQnstZaa+Xb3/52xo4dW2vdM888k+9///tZf/31s+eee2bcuHFzzG6yySb57Gc/26NejbT00kvn/PPPT1VVtddccMEFWW+99XLllVc2sdm/uuuuu3LYYYdl+eWXzyc/+ck88MADLZ3/drfddtvlC1/4Qu38rFmzcthhh2XbbbfNgw8+2MRm/2jmzJm58sors+eee2allVbK8ccfnwkTJrRsfm+011571c5effXV2XvvvdPV1dWQ2dOmTcuRRx6Zvffeu0ff261SVVU+8IEP1Mr+9a9/zWabbZajjjoqjz76aJOb/auRI0fmgAMOqJ3v7u7OAQcckC996Uvp7u5uSIcf/ehH2X777TNx4sTaa9Zbb70ceeSRDZnfl40dOzZHHnlkRowYkY9//OO5/vrrU0pp+twXX3wx22+/fa699tpa+UGDBmXUqFFNbgUAAAAAAAAAAAAAAAAAACyIqlb8ETUA0BhVVU1M0jmn33d2dvboQTMAAAAAAAAAAAAAAAAAAAAAAABvGD9+fDbZZJNMmDBhnvdYe+21s+6662bVVVfN8OHDM3jw4EyZMiV//etf8/jjj+fee+/Nk08+WWuvxRZbLH/+859z5pln5itf+cpc88cff3xOOOGEee7+z0aPHp1tttlmrrmRI0dmyJAhufrqq+eYqaoqH/7wh3PUUUdl4403rt2hq6srF154Yb7+9a/nmWeeqb0uSRZeeOHce++9WWmllXq0rifOOeecfPKTn6yd79evX4455pgcd9xxGThw4DzNvPnmm3PUUUfl1ltvnWNm7bXXzkMPPTTXvUaNGpXzzz9/nnr0JRMnTsymm26aRx55ZJ73WGWVVbLBBhtktdVWyyKLLJIhQ4Zk6tSpefXVV/PEE0/kgQceyKOPPlprr0GDBuXOO+/Mn/70pxxwwAFzzTfzc/rSl76Ub3zjGz1e9+53vztHHXVU3v/+96dfv34N7dTd3Z3bbrstV155ZS655JI89thjb5p75zvfmbvuuqshM1deeeVa1+axY8dm5ZVXbsjMnqqqqlauGc/anTlzZt7znvfkhhtu6NG6jo6O7LPPPvnc5z6Xd73rXQ3v1dXVlT/+8Y+54oor8qtf/Sp/+ctf3jR35JFH5qSTTprveePGjcsqq6wy19xKK62UcePGzfe8+fXUU09l1VVXzaxZs2qvWW211XLBBRdkiy22mKeZpZT88pe/zLHHHjvHczd57XgeOXJkRo8ePdc9G31/84Zrr70273nPe3q8bsUVV8xGG22UlVdeOYsvvniGDh1a+zq42WabZbPNNuvxzJdffjkbbrhhxo8f36N173znO3Pqqafm3e9+d49nJskTTzyRI488MpdddlmP1g0cODA333xzNtlkk3ma+1a23nrrXH/99XPNXXfdddl6660bPr+OV155JYsuuugcf7/iiivmgx/8YHbeeedsueWW6d+/f8NmT58+Peeee26+/vWv59lnn6297qCDDsqZZ57ZsB4AAAAAAAAAAAAAAAAAANCbDR8+PJMmTXqryKRSyvBW9enrGvcX0wAAAAAAAAAAAAAAAAAAAAAAAABAn7XCCivkiiuuyDbbbJOurq552uOhhx7KQw89NN9dBgwYkF/96ldZZpllaq/p6OiY77nz6oc//GHWXXfdOT4ws5SSiy++OBdffHE23HDD7Ljjjtlss82y9tprZ6mllspCCy2UGTNmZOLEiRkzZkzuv//+XHPNNfn973+fiRMnzlOns846KyuttNL8vKy5GjVqVE466aQ88sgjtfLd3d352te+lgsuuCCHHXZY9tlnn1qf8XPPPZff/OY3ufDCC3Prrbe+ZXbrrbfORz7ykXziE5+o1entYPjw4bn66quz+eab5/nnn5+nPcaOHZuxY8c2pM+5556b9dZbL3/6059q5Zt5bn/961/PM888kx//+Mc9WnfTTTflpptuyrLLLpvdd989O+20U7bYYossuuiiPe4wYcKEPPDAA7ntttty22235cYbb8wrr7zS431ongEDBuSyyy7LVlttlfvvv7/2utmzZ+cnP/lJfvKTn2S99dbLbrvtlve9733ZeOONM3jw4B51mD17dp566qncc889ue2223Lrrbfmtttuy4wZM3r6ct42Vlxxxey3334577zzaq95/PHH8x//8R8ZOXJkPvvZz2aHHXZIZ2fnXNc9+uijufTSS3P++efX+k48/PDD09nZmdGjR9fu1mjbbbddNtxww9xzzz09WvfUU0/lqaeemqeZxx9/fDbbbLMer1tsscXyy1/+MltttVWmT59ee92f/vSnbLnllhk5cmQOOuig7LjjjllkkUXecs306dNz/fXX59xzz82vf/3rzJw5s8d9/+d//iebbLJJj9e9XTz11FM55ZRTcsopp2T48OHZcsst8+53vzubb7551ltvvSy22GI92m/GjBm54YYbcvnll+eSSy7Js88+26P1iyyySL72ta/1aA0AAAAAAAAAAAAAAAAAAMAb+re7AAAAAAAAAAAAAAAAAAAAAAAAAADQO2yyySa59NJLs+uuu2bq1Klt6/HDH/4wW2+9dY/WDBw4sDllalhhhRVy1llnZZ999plr9p577sk999zT1D5f/vKX8+EPf7ipM5JkwIAB+e53v5uddtqpR+vGjx+fI488Mp///OezzjrrZMMNN8zKK6+c4cOHp1+/fpkyZUpefvnljB07Nvfdd1/Gjh1ba9+llloqF110UX7/+9/Py8tZoK288sq56qqrsv322+ell15qW48TTjgh++67b4/WNPPcrqoq5557bl599dVcdtllPV7/3HPP5fTTT8/pp5+e5LX3ec0118yIESOyzDLLZOjQoRk8eHC6u7szffr0TJ06NX/5y1/y/PPP57nnnsujjz6aV155pcGvimZYZJFFcvXVV2fkyJF5/PHHe7z+/vvvz/3335///u//Tv/+/bPmmmtm1VVXzYgRI7LEEktkyJAhGTRoUGbMmJHp06dnypQpmTBhQp5//vk8/fTTeeyxxzJt2rQmvLIF2ze+8Y1ceumlPT7Prr/++lx//fXp169f1ltvvWy00UZZfPHFs+iii2bQoEGZPHlyXnzxxTz++OO5995789xzz9Xee/3118+JJ56Yb3zjGz18NY33jW98IzvuuGO7a9Sy6aab5owzzsjHPvaxHq/9+89zgw02yDrrrJOVVlopnZ2d6devX7q6uvLcc8/l4Ycfzl133ZUpU6bMc8+DDz44Bx544Dyvf7uZOHFirrjiilxxxRV/+7+ll146a6yxRpZbbrkst9xyGT58eAYPHpyBAwdm6tSpmTx5crq6uvLkk0/mkUceyRNPPJFZs2bNc4ezzz47SyyxRCNeDgAAAAAAAAAAAAAAAAAA8DbUv90FAAAAAAAAAAAAAAAAAAAAAAAAAIDeY/vtt8+1116bnXfeOS+//HJLZ/fv3z9nnnlm9t9//7/9X3d3d621gwcPblKrevbee+88+uijOeGEE9ra44ADDshXvvKVls3bcccdc+CBB+aHP/xhj9eWUvLnP/85f/7zn+e7R2dnZy6//PIsu+yy873XgmrDDTfMTTfdlPe+97158sknWz7/+OOPz/HHH/+3f/eWc7t///755S9/mYMPPjjnnnvufO01bty4jBs3rjHF6HWWW2653HLLLXn/+9+fO++8c573mTVrVsOufby1pZZaKmeddVY+/OEPz9P67u7u3HPPPbnnnnsa0mfEiBG5/PLLM2jQoIbsN7/e9773Zf/998/555/f7iq1HHDAAZk0aVIOPfTQeVrf3d2du+++O3fffXeDm71mv/32yw9+8IOm7P128sILL+SFF15oyaxjjjkmH/zgB1syCwAAAAAAAAAAAAAAAAAAWDB1tLsAAAAAAAAAAAAAAAAAAAAAAAAAANC7bL755rn11luz0UYbtWxmZ2dnfvvb3+bjH//4P/z/1KlTa60fNGhQM2r1yPHHH5+DDjqobfMPOeSQnHPOOS2fe9ppp+Wd73xny+e+YfDgwfntb3+bd73rXW3r0Fesueaaue2227Lddtu1bObAgQNz7rnn5oQTTviH/+9N53b//v1zzjnn5Ktf/Wo6OjyulTlbcsklc91112W33XZrdxVq2nPPPfP5z3++3TWy2GKL5fe//31WWGGFdlf5B2eeeWa22Wabdteo7XOf+1xOO+20XnetPuCAA/KjH/2o1/Vizg477LCceOKJ7a4BAAAAAAAAAAAAAAAAAAD0cf7KHAAAAAAAAAAAAAAAAAAAAAAAAAD4F2ussUZuu+22fOELX8iAAQOaOut973tfHnjggey4447/8rtp06bV2qOzs7PRtebJmWeemeOPP76lMzs6OvLf//3fOf3009PR0fpHTQ4ePDhXX3111l577ZbPXmyxxXL11Vdn6623bvnsvmqZZZbJH/7wh5x00kkZNmxYU2dtuumm+dOf/pSPfexj//K73nhuH3fccRk9enRWWmmlls2k7xk2bFh+/etf54wzzsjQoUPbXYcavv3tb+eTn/xk2+avssoqueGGG7LOOuu0rcOcDBo0KFdffXU+/vGPt7tKbZ/73Ody+eWXZ+GFF253lfTr1y8nn3xyzjvvvLbcg9Fz/fr1y3e/+91897vfbXcVAAAAAAAAAAAAAAAAAABgAeAvzQEAAAAAAAAAAAAAAAAAAAAAAACANzVw4MB861vfyoMPPpg999wzVVU1dP/1118/F198ca666qqsuOKKb5p54YUXau219NJLN7LafDnhhBPys5/9LIsttljTZy233HK59tpr81//9V9Nn/VWllhiiYwePTr/8R//0bKZa621Vm6//faMHDmyZTMXFFVV5cgjj8zjjz+egw46KAMGDGjo/u94xztyxhln5JZbbsm//du/vWmmt57bW265Ze6999587nOfa/j70iirr756DjzwwHbXeNs7+OCD83//93/Zaaed2l1ljrbccsvssssu7a7RdlVV5Yc//GGOP/74ls/eaqutcscdd2Tddddt+ey6Bg4cmHPOOSfXXHNN3vWud7W7Ti077rhj/vSnP7X1HmD11VfPH//4xxxxxBFt60DPrLnmmrnhhhty2GGHtbsKAAAAAAAAAAAAAAAAAACwgOhodwEAAAAAAAAAAAAAAAAAAAAAAAAAoHdbbbXV8vOf/zxPPPFEjjnmmKy44orzvNfCCy+cPffcM1dddVXuvffefPjDH37L/HPPPVdr32WWWWaeOzXDXnvtlQcffDAf/vCHU1VVw/cfOHBgjjjiiPz5z3/O1ltv3fD958VSSy2VP/7xjzn88MPTr1+/ps3p379/jjrqqNx9991ZbbXVmjbn7WCZZZbJmWeemfHjx+fEE0/MmmuuOc97DR06NLvsskt+/vOf59FHH83BBx/8lsdBbz63F1544Zx22mn585//nA9+8IPp6Gj/I1wXXXTRfOxjH8t1112XRx99NAceeGC7K5FkjTXWyBVXXJFrrrkmm266abvrJElWWWWVfPGLX8zDDz+cG264ISNHjmx3pV7jhBNOyJVXXplll1226bMWXnjhfP/73891112XJZZYounzGmG77bbLHXfckRtvvDGHHHJIlltuuXZXekurrrpqrrvuupx99tlZeumlWzZ3yJAhOfbYY3Pfffdlq622atncvmL48OH5+c9/no9+9KNZcskl210nyWvfoSeeeGLuueeebLHFFu2uAwAAAAAAAAAAAAAAAAAALED6t7sAAAAAAAAAAAAAAAAAAAAAAAAAANA3rLLKKjnxxBNz4okn5uGHH861116be++9N4888kiefPLJTJw4MV1dXUmSzs7OdHZ2Zqmllso666yTddZZJ+9617vy7ne/OwMGDKg98/HHH6+VW3bZZefpNTXT0ksvnYsvvjjHHXdcTjrppFx00UWZMWPGfO25yCKLZNSoUTn00EOzyiqrNKhp4wwcODCnnHJK9tlnn3zhC1/Idddd17C9q6rKLrvskq985SvZcMMNG7Yvrx2rxxxzTI455pg8+eSTueaaa3L33XfnkUceyZgxY/Lqq6+mq6srs2fP/tu5vfjii2ettdbKuuuum4033jhbb711hgwZUntmXzi3V1999VxyySUZN25cTj/99PzoRz/KSy+91LL5K6ywQnbcccd84AMfyPbbb5+BAwe2bDY9s9122+X222/Prbfemu9///v51a9+lenTp7ds/gYbbJCddtopu+22WzbddNOWze2Ldtxxxzz00EP51re+ldNOOy1Tpkxp6P7Dhw/Pxz72sRx99NFZZpllGrp3q7z73e/Ou9/97px++ul54oknctttt+XBBx/MY489lqeffjovvvhiXn755UybNi3Tp09Pd3d327pWVZVPfOIT2XfffXPOOefk5JNPzpNPPtmUWQsvvHAOOeSQHHHEEVlyySWbMmNB0NHRkT333DN77rlnZs+enTvuuCNXXHFFrrzyytxzzz2ZPXt2y7qsuuqqOfDAA3PggQdmkUUWadlcAAAAAAAAAAAAAAAAAADg7aMqpbS7AwBQU1VVE5N0zun3nZ2dmThxYgsbAQAAAAAAAAAAAAAAAAAAAAAANM+LL76YpZZaaq65RRddNC+//HJDZ48ePTrbbLPNXHMjR47M6NGja+05ceLEXH311bn88stz8803Z9y4cZk9e/Zc16200kp5z3vek/e9733ZaaedMnTo0FrzeoM77rgjZ599di699NJ5/oxWWGGF7Lrrrvn0pz+dtdZaa675888/PwcccMBcc6NGjcr5558/T52YP6WUdHZ2ZvLkyXPNvvLKK1l44YVb0GruZs2alRtuuCGXXXZZrrrqqjz22GMN27uqqqyyyirZbLPNsuWWW2arrbbKOuus07D9aa1JkyblqquuymWXXZZrr702L7zwQsP2HjBgQNZZZ51sscUW2XLLLbP11ltn2WWXbdj+bycvv/xyzj///Fx44YW555575nmfQYMGZcstt8zuu++e/fbbLwsttNBc19x1112566675prbZJNNsskmm8xzt7eb2bNn54YbbshFF12U3/3ud3n++efna7/hw4fnPe95T/bee+/svPPOGTx4cIOavj1NmjQpd9xxR2677ba//bz00ksN27+qqqy77rrZcccds+uuu2aLLbZIVVUN2x8AAAAAAAAAAAAAAAAAABYEw4cPz6RJk94qMqmUMrxVffq6qpTS7g4AQE1VVU1M0jmn33d2dmbixIktbAQAAAAAAAAAAAAAAAAAAAAAANA8l19+eXbZZZe55v7jP/4jN910U0Nnjx49Ottss81ccyNHjszo0aPnacbUqVPz8MMP5+mnn86kSZMyadKkzJo1K8OGDUtnZ2dWWGGFrL322unsnOPjp/qMmTNn5s4778wtt9ySe+65J2PGjMn48eMzceLE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AAAAAAD0FR3tLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Fd0tLsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBf0dHuAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfUVHuwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQVHe0uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQV3S0uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQF/R0e4CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9RUe7CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9BUd7S4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBXdLS7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAX9HR7gIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH1FR7sLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0FR3tLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Fd0tLsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBf0dHuAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfUVHuwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQVHe0uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQV3S0uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQF/R0e4CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9RUe7CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9BUd7S4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBXdLS7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAX9HR7gIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH1FR7sLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0FR3tLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Fd0tLsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBf0dHuAgAAAAAAAAAAAAAAAAAAAAAAAAAAAP+Pnb8Psuy878PO77kvfc683IvhC7oJakRiaImSLFmgCFOULVuOLHLzYscGpFluolQqrvUm0ipxKUgy2dXYqa2kHEQbOEHRJJ1VsqkklVhJIS0Rydq7dkR5I1mxQ3MH5kiWFJE2eggPOewekBzcO5g553b3PftH9wxmgAEw3eg+3YP5fKpuPc95znme7+88fafvbVThAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL2id9AFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcK3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAAvN399tdeOugSOnG/3CcAAAAAAAAAAAAAAAAAAAAAAHB/6x10AQAAAAAAAAAAAAAAAAAAAAAAAADwdvb0r3wpf/JTv5HlcxcPupR9tXzuYv7kp34jT//Klw66FAAAAAAAAAAAAAAAAAAAAAAAgH01OOgCAAAAAAAAAAAAAAAAAAAAAAAAAODt6ulf+VI++atfTpKcWT6fJDn96MmDLGlfLJ+7mDPL59O2uXm/T3z8gwdcFQAAAAAAAAAAAAAAAAAAAAAAwP7oHXQBAAAAAAAAAAAAAAAAAAAAAAAAAPB29PSvfCmf/NUv3zxu2+TM8vksn7t4gFXtveVzF3Nm+Xza9pWxT/7ql/P0r3zp4IoCAAAAAAAAAAAAAAAAAAAAAADYR4ODLgAA7gdFUfyrSX5mD5Y6tgdrAAAAAAAAAAAAAAAAAAAAAAAA++zpX/lSPvmrX37NeNsmZ5bPJ0lOP3qy67L23PK5izmzfD5tHw69DAABAABJREFU+9pzN+7/iY9/sOOqAAAAAAAAAAAAAAAAAAAAAAAA9tfgoAsAgPvEg0l+/0EXAQAAAAAAAAAAAAAAAAAAAAAA7L+nf+VL+eSvfvl1z7dtcmb5fJLk9KMnuyprzy2fu5gzy+fTtq9/zY19eOLjH+yoKgAAAAAAAAAAAAAAAAAAAAAAgP3XO+gCAAAAAAAAAAAAAAAAAAAAAAAAAODt4ulf+VI++atfftPr2jY5s3w+y+cudlDV3ls+dzFnls+nbd/82k/+6pfz9K98af+LAgAAAAAAAAAAAAAAAAAAAAAA6EjvoAsAAAAAAAAAAAAAAAAAAAAAAAAAgLeDp3/lS/nkr375rq9v2+TM8vksn7u4j1XtveVzF3Nm+Xza9u7nfPJXv5ynf+VL+1cUAAAAAAAAAAAAAAAAAAAAAABAh3oHXQAAAAAAAAAAAAAAAAAAAAAAAAAA3Ot++2sv5S//rS/veF7bJmeWz2f53MV9qGrvLZ+7mDPL59O2O5/7l//Wl/PbX3tp74sCAAAAAAAAAAAAAAAAAAAAAADoWO+gCwAAAAAAAAAAAAAAAAAAAAAAAACAe933vveBPHX6kRTFzue2bXJm+XyWz13c+8L20PK5izmzfD5tu/O5RZE8dfqRfO97H9j7wgAAAAAAAAAAAAAAAAAAAAAAADo2OOgCAOA+cTnJ7+zBOt+dpLcH6wAAAAAAAAAAAAAAAAAAAAAAAHvs9KMnkyRnls+nbXc2t2235t26zmGyfO7iru4rSYoieer0I4fyvgAAAAAAAAAAAAAAAAAAAAAAAHajaHfzVCYA4EAURTFJMnq986PRKJPJpMOKAAAAAAAAAAAAAAAAAAAAAACAV1s+dzFnls9nN4/7K4rkqdOP5PSjJ/e+sF16u90PAAAAAAAAAAAAAAAAAAAAAADcj8bjcabT6RtdMm3bdtxVPfe63kEXAAAAAAAAAAAAAAAAAAAAAAAAAABvJ6cfPZmnTj+Sotj53LZNziyfz/K5i3tf2C4sn7uYM8vn07Y7n1sUyVOnH8npR0/ufWEAAAAAAAAAAAAAAAAAAAAAAAAHqHfQBQAAAAAAAAAAAAAAAAAAAAAAAADA283pR0/mqdOPpCh2PrdtkzPL57N87uLeF7YDy+cu5szy+bTtzucWRfLU6Udy+tGTe18YAAAAAAAAAAAAAAAAAAAAAADAAesddAEAAAAAAAAAAAAAAAAAAAAAAAAA8HZ0+tGTeer0IymKnc9t2+TM8vksn7u494XdheVzF3Nm+XzadudziyJ56vQjOf3oyb0vDAAAAAAAAAAAAAAAAAAAAAAA4BDoHXQBAAAAAAAAAAAAAAAAAAAAAAAAAPB2dfrRk3nq9CMpip3PbdvkzPL5LJ+7uPeFvYHlcxdzZvl82nbnc4sieer0Izn96Mm9LwwAAAAAAAAAAAAAAAAAAAAAAOCQ6B10AQAAAAAAAAAAAAAAAAAAAAAAAADwdnb60ZN56vQjKYqdz23b5Mzy+Syfu7j3hd3B8rmLObN8Pm2787lFkTx1+pGcfvTk3hcGAAAAAAAAAAAAAAAAAAAAAABwiPQOugAAAAAAAAAAAAAAAAAAAAAAAAAAeLs7/ejJPHX6kRTFzue2bXJm+XyWz13c+8JusXzuYs4sn0/b7nxuUSRPnX4kpx89ufeFAQAAAAAAAAAAAAAAAAAAAAAAHDK9gy4AAAAAAAAAAAAAAAAAAAAAAAAAAO4Hpx89madOP5Ki2Pnctk3OLJ/P8rmLe19YkuVzF3Nm+XzadudziyJ56vQjOf3oyb0vDAAAAAAAAAAAAAAAAAAAAAAA4BDqHXQBAAAAAAAAAAAAAAAAAAAAAAAAAHC/OP3oyTx1+pEUxc7ntm1yZvl8ls9d3NOals9dzJnl82nbnc8tiuSp04/k9KMn97QmAAAAAAAAAAAAAAAAAAAAAACAw6x30AUAAAAAAAAAAAAAAAAAAAAAAAAAwP3k9KMn89TpR1IUO5/btsmZ5fNZPndxT2pZPncxZ5bPp213PrcokqdOP5LTj57ck1oAAAAAAAAAAAAAAAAAAAAAAADuFb2DLgAAAAAAAAAAAAAAAAAAAAAAAAAA7jenHz2Zp04/kqLY+dy2Tc4sn8/yuYtvqYblcxdzZvl82nbnc4sieer0Izn96Mm3VAMAAAAAAAAAAAAAAAAAAAAAAMC9qHfQBQAAAAAAAAAAAAAAAAAAAAAAAADA2139u7/7mrHTj57MU6cfSVHsfL22Tc4sn8/yuYu7qmf53MWcWT6ftt353KJInjr9SE4/evI15+50nwAAAAAAAAAAAAAAAAAAAAAAAG83vYMuAAAAAAAAAAAAAAAAAAAAAAAAAADezi5/6tNZ+fGfyJXPPvuac6cfPZmnTj+Sotj5um2bnFk+n+VzF3c0b/ncxZxZPp+23XlmUSRPnX4kpx89+ZpzVz77bFZ+/Cdy+VOf3vnCAAAAAAAAAAAAAAAAAAAAAAAA95DBQRcAAAAAAAAAAAAAAAAAAAAAAAAAAG9Xlz/16bz4mc8kSS6dPZskOfH4Y7ddc/rRk0mSM8vn07Y7W79tt+bdus4bWT53cVc5SVIUyVOnH7ljzpXPPrt1f217834f/HP/2s5DAAAAAAAAAAAAAAAAAAAAAAAA7gG9gy4AAAAAAAAAAAAAAAAAAAAAAAAAAN6OLn/q03nxM595ZaBtc+ns2Vz57LOvufb0oyfz1OlHUhQ7z2nb5Mzy+Syfu/iG1y2fu5gzy+fTtjvPKIrkqdOP5PSjJ19z7spnn82ls2dz68IvfuYzufypT+88CAAAAAAAAAAAAAAAAAAAAAAA4B7QO+gCAAAAAAAAAAAAAAAAAAAAAAAAAODt5vKnPp0XP/OZ155o21w6ezZXPvvsa06dfvRknjr9SIpi53ltm5xZPp/lcxfveH753MWcWT6ftt352kWRPHX6kZx+9ORrzl357LO5dPZs7rTwi5/5TC5/6tM7DwQAAAAAAAAAAAAAAAAAAAAAADjkegddAAAAAAAAAAAAAAAAAAAAAAAAAAC8nVz+1Kfz4mc+8/oXtG0unT2bK5999jWnTj96Mk+dfiRFsfPctk3OLJ/P8rmLt40vn7uYM8vn07Y7X7MokqdOP5LTj558zbkrn302l86ezRst/OJnPpPLn/r0zoMBAAAAAAAAAAAAAAAAAAAAAAAOscFBFwAAAAAAAAAAAAAAAAAAAAAAAAAAbxeXP/XpvPiZz7z5hW2bS2fPJklOPP7YbadOP3oySXJm+Xzadmf5bbs172q9nn/y+96TX/md1fzf/sff3vE6SVIUyVOnH7lZz62ufPbZrfrvYuEb+/Hgn/vXdl4EAAAAAAAAAAAAAAAAAAAAAADAIVS0u3m6EwBwIIqimCQZvd750WiUyWTSYUUAAAAAAAAAAAAAAAAAAAAAAMANlz/16bz4mc/sbFJR5KEnn8yJxx97zanlcxdzZvl8DuKxgUWSf/3j35kf/4GTGVWDHC8HGfR7SZIrn302l86ezU4Le/e/+q/mwT/3r+1DtQAAAAAAAAAAAAAAAAAAAAAAwJsZj8eZTqdvdMm0bdtxV/Xc64r2IJ4QBQDsSlEUkySj1zs/Go0ymUw6rAgAAAAAAAAAAAAAAAAAAAAAAEiS+nd/Nys//hPJbp7xVxR56Mknc+Lxx15zavncxZxZPr+rZffa0YV+/qmvnsuf/V/+anrZ3X2e+uVfSvU937P3xQEAAAAAAAAAAAAAAAAAAAAAAG9oPB5nOp2+0SXTtm3HXdVzrxscdAEAAAAAAAAAAAAAAAAAAAAAAAAAcK+rvud78tCTT+bS2bNJ2+5scttuzUty4vHHbjt1+tGTSZIzy+d3vOxe+8P/8H/Nn33umfSy80LmKfL0D3wi/8svfiWj6qsZVYOMqmFG1SDj7fbWsdEtY+NXjQ37vX24OwAAAAAAAAAAAAAAAAAAAAAAgLtXtAf9ZCgA4K4VRTFJMnq986PRKJPJpMOKAAAAAAAAAAAAAAAAAAAAAADg/jOft/nGy7OsTuqsTeusTZqsTpr84e94V77z7/96Lp09m+zmWX9FkYeefDInHn/sNaeWz13MmeXzu1p2L3zshS/kieeeSS87L2CeIk9/+BP53Ps+8pbr+EMfeFf+23/lh97yOgAAAAAAAAAAAAAAAAAAAAAAcL8Zj8eZTqdvdMm0bdtxV/Xc6wYHXQAAAAAAAAAAAAAAAAAAAAAAAAAAHAbzeZtvvDzL2rTO2qTJ6qTO2nSrXZ00uTzdbq822Zy3d1jhg/nI448lSS6dPZu0d7rmDbTt1rwkJ7bXueH0oyeTJGeWz+942bfqYy98IU8890x62XnwPEWe/vAn8rn3fWRPahlV3T1G8Te+/GK+9tL1jKtBRtUwo9vaQcpBv7NaAAAAAAAAAAAAAAAAAAAAAACAw6W7JyIBAAAAAAAAAAAAAAAAAAAAAAAAwAGYz9t889osq5M6a9Mma5M6q5Mma9Ptdnv88rTJxrzddc7qtE6SnHj8sSTJpbNnk3aH67Xt1rxb1rnh9KMnkyRnls/veNnd+tgLX8gTzz2TXnYeOE+Rpz/8iXzufR/Zs3pG1XDP1noz/+3feyF//bcuve75hUEv42qQUTXMqBpsvcob/VfGxtVrx270q2G/s/sBAAAAAAAAAAAAAAAAAAAAAAD2zuCgCwAAAAAAAAAAAAAAAAAAAAAAAACA3ZjP23zr2iyrkyar0zqXJ01WJ3VWp3XWJk1Wp03WJnUuT5tszNt9r2dtUt/sn3j8sSTJpbNnk3aH2W27Ne+WdW44/ejJJMm/9d+f33Wdd+tjL3whTzz3THrZ+d7NU+TpD38in3vfR/a0plHV3WMUJ/X6G56fbczz4tVZXrw623XGQr+XUTXYfg3v0B9mfIexG9eNq2HKQS9FUey6BgAAAAAAAAAAAAAAAAAAAAAAYOe6eyISAAAAAAAAAAAAAAAAAAAAAAAAANyF+bzNt67NsjZtsjqpszZpsjatszrZPp42WdtuN+btQZd709q0ue34xOOPJUkunT2btDuss2235t2yzg2nHz2Zv/OPXswvP/fV3Zb6pj72whfyxHPPpJed7+88RZ7+8Cfyufd9ZM/rGlfdPUZxWm/se8Zsc55vvDzLN16e7XqNYb/IqBpmVA22XuWN/lY7vqV/23XV8Oa5athLURR7eGcAAAAAAAAAAAAAAAAAAAAAAPD21t0TkQAAAAAAAAAAAAAAAAAAAAAAAAC4r7Vtm29dW8/atM7qpMnqpM7l6Va79WpyedpkbVpnfbM96HJ3bHVSv2bsxOOPJUkunT2btDu8p7bdmnfLOjf809/3UH75ua/upsw39bEXvpAnnnsmvez8ZzBPkac//Il87n0f2YfKklE13Jd172Rar3eW9Vasb7b55suzfPPl2a7XGPSKjKpBvu0dR/LX/twf3cPqAAAAAAAAAAAAAAAAAAAAAADg7Wlw0AUAAAAAAAAAAAAAAAAAAAAAAAAA8PbzC7/2j/K1K9ezOmmyOq2zNmlyedpktjk/6NL2zeVpk815m36vuG38xOOPJUkunT2btO3OFm3brXm3rJMk/+CrL72VUl/Xx174Qp547pn0ssM6k8xT5OkPfyKfe99H9qGyLaOqu8coTuuNzrIO2sa8zbeurefoQnf7+7Ur1/P1SZ1xNcioGmZUDXJk2E9RFG8+GQAAAAAAAAAAAAAAAAAAAAAADlh3T+wBAAAAAAAAAAAAAAAAAAAAAAAA4L7xX/2dC/naS/VBl9GpeZt84+Umi6PqNedOPP5YkuTS2bNJ2+5s4bbdmre9zvK5i/nLv/rlt1rua3zshS/kieeeSS87rC/JPEWe/vAn8rn3fWTP67rVqBru6/q3mtYbnWUdFqOqu8dUfvbvfzVP/c3fu22s3ysyqgZbr3K43R9mfGOsGr6qvfX81tjRhX6KoujsPgAAAAAAAAAAAAAAAAAAAAAAuD9198QeAAAAAAAAAAAAAAAAAAAAAAAAAO4bi+MqX3upPugyOrc2abI4qu547sTjjyVJLp09m7TtzhZu21w6ezZfuPDNnFlbyg5nv6mPvfCFPPHcM+ntYuV5ijz94U/kc+/7yB5X9VqjqpvHKK5vznN9fbOTrMNkXA07y5rWG68Z25y3uXJtPVeurSe5vqt1+70ix8tBRtUgo2qYUTXI+Jb+6Lb+nc4Pc2yhn6Io3uIdAgAAAAAAAAAAAAAAAAAAAADwdtbNE5EAAAAAAAAAAAAAAAAAAAAAAAAA2Hdt22ZSb2RtUmdt2mR1Umd10mRtWmdt0uSPfOe788//4Ps6qWVxVHaSc9isTup837c98LrnTzz+WJLk0tmzSdvubPG2zXt/4S/lxz78iXzufR95C1Xe7mMvfCFPPPdMetlhPUnmKfL0HtfzRkZVN49RvFpvdJJz2HS1v0kyrdf3Zd3NeZuXrq/npevrSa7vao1ekRwvBxlVw4yqQcbb7dZr+Kr21vOvjB1bGKTXK/b25gAAAAAAAAAAAAAAAAAAAAAAODS6e2IPAAAAAAAAAAAAAAAAAAAAAAAAALvStm2mzUbWJnVWJ03Wplvt6qTO2rS5bbxen7/uOkcW+vnnf/B9ndS8NK46yTlsVifNm15z4vHHkiSXzp5N2nZH6/fS5onnnkmSfO59H9lxfa/2sRe+kCeeeya97KyOJJmnyNMf/sSe1HG3RtWwk5xpvdFJzmEzqrp7TOVh3uN5m0zqjUzeQo1FkRwvBxlXw4yqwfZrmKdOf3/edbzcw2oBAAAAAAAAAAAAAAAAAAAAADgI3T2xBwAAAAAAAAAAAAAAAAAAAAAAAIDbtG2babORtUmTtUmd1WmdtUmT1UmT1Wmdy9vt6qROvT5/y3mrk3oPqr47S+Oys6zDZG16d3t84vHHkiSXzp5N2nZHGb20eeK5Z5Ikn3vfR3Y091Yfe+ELeeK5Z9LLzvKTZJ4iT3/4E28pfzfGVTePUZzU653kHDajathZ1vRtvsdtm0zrjUzrjdvG+72ik/xmYzP1+jyjcpBeR5kAAAAAAAAAAAAAAAAAAAAAAPeTbp6IBAAAAAAAAAAAAAAAAAAAAAAAAHAfads2V5uNrE6arE3rrE2arE7qrE232+3x1UmT6+ubndV1edp0lrU4rjrLOkxWJ3e/xycefyxJcuns2aRtd5TTS5snnnsmSfK5931kR3OT5GMvfCFPPPdMetlZbpLMU+TpD39iV7lv1agadpIzrTc6yTlsRlV3j6m8X/f4eNnNHv/df/SN/Jn/4gs3M0fVjdfwVe0g41v6o/L28+NqmOPVIP1e0UndAAAAAAAAAAAAAAAAAAAAAAD3iu6e2AMAAAAAAAAAAAAAAAAAAAAAAADwNnC12cjqpM7qpM7labPdb7K23V+b1FmbNrk22zzoUl9jdVJ3lrU4KjvLOkzWdrjHJx5/LEly6ezZpG13NLeXNk8890yS5HPv+8hrzi+Ny6xOmteMf+yFL+SJ555JLzvLS5J5ijz94U/cMW+/DXpFqmGvk6xpvd5JzmEzqoadZU3rjc6yDotjC/0M+l29h1/Z36vNRq42G7n00u7XO7bQz6gaZlQNtl/Dm+34DmM3rhtv94+Xg87uHQAAAAAAAAAAAAAAAAAAAACgC4ODLgAAAAAAAAAAAAAAAAAAAAAAAADgMLjabGRtUmd10mRtWmdt0mR1Umd12mRtUmdtunV8bbZ50KXu2reurafZ2Ew56O971tK42veMw2ht2ux4zonHH0uSXDp7NmnbHc3tpc0Tzz2TJPnc+z6SJCmK5KnTj+T0oyezfO5iziyfv7nsx174Qp547pn0srOcJGlT5Jkf+5fy5Yd/MO+sNzKt17O+ufN1dmtUDVIURSdZ03qjk5zDZlR195jKab3eWdZhMaqGnWXt9Xv45dlmXp5t5uuT3a9xdKGfcTXMqBpsv4Y32/Edxm5cd2PO8XKQQb+3dzcFAAAAAAAAAAAAAAAAAAAAAPAWdPfEHgAAAAAAAAAAAAAAAAAAAAAAAIBD5C/+td/Jb331pVyeNlmd1Hl5tnnQJXXi8rTJyXcc3fecpXG17xmH0eqk3tW8E48/liS5dPZs0rY7mttLmyeeeyZJ8qvv/0ieOv1ITj96MklutmeWz+fHvvKFPPHcM+llZ+snSYoi733yyfy723UmSdu2aTbmmdTrmdYb26/129rJHcZe3Z9tzu+qhFE13HnduzSt1zvLOkxGVXePqZzWG51lHRbd7u/hew9fm23m2mwzX5/sfo2jC/2MqkFG1fC2drzd/8Qf/PZ8x+LxvSsaAAAAAAAAAAAAAAAAAAAAAOB1dPdEGQAAAAAAAAAAAAAAAAAAAAAAAIBD5De/+lL+3so3D7qMzq1Ompx8x9F9z3nH0WGG/SLrm+2+Zx0mL15tsjlv0+8VO5574vHH8oUL38x7f+EvpZed7VsvbZ547pn8Hz7yvnz80ZO3nTv96Mk88Ov/U9772Wd2vG6SzFPka//Kv5Xvefyx28aLokg17Kca9rM42vGyN9Xrm5nU65nWG9uv9dvayXZ/XA13H7JD03qjs6zDpKs9ns/bXJ3df3s8qrp7DOjb9T18bbaZa7PNrE6aO57/Yx98MN+xeLzjqgAAAAAAAAAAAAAAAAAAAACA+1F3T5QBAAAAAAAAAAAAAAAAAAAAAAAAOESWxtVBl3AgLk/rTnKKosjiqMpXr1zvJK8L1bCXpXGVxVGZxXGVpVGVxXGZpXG53d867hW7W3/53MWcWVvKj334E3niuWfSS7uj+b20Ofmf/qVcefidOfH4YzfHr3z22Zz8T/9SssP1kmSeIk9/+BP51bWlPHXuYk4/enLHa7yZathPNexncbTnS+/atNk46BIOxKjq5jGVV2cbaXf+drznjaphZ1nTer2zrMOkq/fwN642+ac++bczqgYZVcOMq8FWvxzeHBvdGKuGGR8ZZFzdfm7Y73VSKwAAAAAAAAAAAAAAAAAAAACwP7p52gkAAAAAAAAAAAAAAAAAAAAAAABw37s+28zqpM7atMnqpM7qpM7lm/0ma9M6P3jqnfkPfvz7O6lncVR2knPYrE6azrIWx2W+euV6Z3m7VQ56WRpXWRqXWRxVWRyXWRpXWRyVN8cfHFUZV4MURbEvNSyfu5gzy+fTtsnn3veRJMkTzz2TXtqdLdS2uXT2bNa//vUc/0M/lKu/8b/kxc98Jml3uE6SeYo8/eFPbNXTJmeWzydJTj96csdr3Wv+xR96f/7YBx/MtF7PpN7ItN7ItF5/VftKf7LdbzbmB136WzKqhp3kTOuNTnIOm1HV3WNA79897uY9PKk3cnna5PJ095+p1bCXUTXMqBpkVA0zrgZb/fKVsdGNsZvnbx9bGPT28K4AAAAAAAAAAAAAAAAAAAAAgJ3o7okyAAAAAAAAAAAAAAAAAAAAAAAAwNvS9dlm1qZ11qZNVid1VifN1vHkxvHWuWm98aZrPTgqO6h4y9K4u6zDZHVSd5a12OHP804WBr0sjcssjaosjsssjqosjass3eyXWRxXGVeDFEVxYHUun7uYM8vn07avjH3ufR9Jkjzx3DPppX2dma+jbfPiJz+ZFz/5yV3X1Cb5hw+8Nx9e+1K+9xsrmfUGmfWHOf87fyPvfuR9+f7ft5iiLHPkQx9K9d3fveucw+rb33k03/7OozueN9uYZ1qvZ1pvbL/WM9lubx2b1huZNlvt7efXU6/P9+GO7s6o6uYxldN6vZOcw2ZUDTvLmtzFZ+7b0b30Hq7X56nXm1yeNrteoxz0MqqGGVeDjKpBRtVwu721v9WO7zA2qgYpB/23fC8AAAAAAAAAAAAAAAAAAAAAcD/q5mknAAAAAAAAAAAAAAAAAAAAAAAAwD2nXt/M2qTJ6rTeaid1Vqd1Lm+PrU6arE3qTOqNPctcmzR7ttabWRpXnWUdJmvTe3+PFwa9LI7KLI2rLI3LLI6qLI7LLN1ox1WWRlXGRwYpimJfatgry+cu5szy+bTta8997tv/YI6sN/np33o2vY7rKpJ88KWv5oMvffW1J38vWd3uLv5b/2aq7/7uTmq68ku/lHY2S1FW6VVlirK8pX+HsapKsbDQ6XtgYdDLu46XedfxctdrzDbmudpsZFqvZ1pvZLLdbr3WX9Xeev6Vsevrm7vKPl5185jK6R5+btxLxh3tb5JM6/XOsg6TUUd7PLl+ON7DzcY8zdUmL17d/Wf7wqCXcTXIqBpmVA22XuWN/itj42qYD73vRD64NNrDOwAAAAAAAAAAAAAAAAAAAACAe1d3T5QBAAAAAAAAAAAAAAAAAAAAAAAADoV6fTOXp01WJ3XWttvVSZO1247rTOqNzmtbmzadZT04KjvLOkxWJ3VnWUvjakfXL/R7eXBUZmlcZmlcZXFUZnFc3ewvjassjcs8cGSYoij2qeruLJ+7mDPL59Pf3Mh7r76Yk1cv59uuXs7Jq2s5efVyvn26ltH69YMu8w0V5c5+xm/F5U/+5Wysre14XlGWKaoqvVvbskxRlemV1euMlelVVYqFV42VZYqySq/aWqsoy9vX3R57K+/PhUEv7xws5J3HFna9xvrmPFfrjUzrjUzq9UzrjUxf3TZb/cn2dVfr9Rxf6OYxldN6vZOcw2ZUdfcY0OkBfIYftIVBL+Wg30nW2+k9PNuY58Wrs7x4dfam1579Z747H1wadVAVAAAAAAAAAAAAAAAAAAAAABx+3T1RBgAAAAAAAAAAAAAAAAAAAAAAANhXzcZm1iZN1qZ1VidN1iZ1VqdNVid1Lm+3q5MmL11fP+hSX9fVZiNXm40cL/f/UWlL42rfMw6jtUnTWdaDozJJMuwXWRxVWRyXWRpVWRqXWRxXWRyVWRq/Mn7i6DBFUXRWX5fats3mN76R2cpKmpWV/IO/+5t5+bnfyX929XLec+2b6bfzgy5xV/7+16/lxzrKmje7e++2TZO2adLlDhcLCymqKr2y3GqrMsVC+TpjZXpl9dqxqsrgPe/J8R/+4R3nD/u9vOPYQt5xbGEf7u6tm9YbB13CgRhVw86yps3h/azfL+Oqu8eseg/vv5/5q+eysdlmVA0zqgYZV4Ob/Vfarf6Nc9Ww97b9HgEAAAAAAAAAAAAAAAAAAADA4dPdE08AAAAAAAAAAAAAAAAAAAAAAACAXWk2NnN52mR10mRtUmdt2mR1Um8dT+usTZqsTutcubZ+0KXuibVJneMPHt/3nKVxte8Zh9HatO4s60/8gYfyse9ZyjuODlMURWe5B2k+m2X9K19J8/xKZitbr+bCSmbPr2Q+nd687t3br3vdX/3i1/Otcxdz+tGT+57V1t29d9+qdjZLO5tl/hbXOfqDP5jjP/zDe1LTm7n2hS9k9pWvpCjLFGWZXlWlKKv0qvL2sapKb/u46Pd3lfUHvu2B/Ht/+nszrTcyub6eSb2Rab2e6W3tVv/l2eYe3+nBGVXdPQZ0Wm90lnVYjKphZ1mT+u3xnWununwP/3//t8u5vr6zf/+DXpFRNcioGm63r/THdxh75dwr/SPD/n3znQUAAAAAAAAAAAAAAAAAAACAt6a7p3EAAAAAAAAAAAAAAAAAAAAAAAAAO/Jzv/yb+Rv/4Ov51rX1gy6lU2vTJh948Pi+5xwvBzm60M+12ea+Zx0m37q2nmZjM+Wgv+9Zx8pBjpX7HnPgmudXsvrz/0FmKxey/tWvJvP5QZfUmaY3zJnl80mS04+eTC79ZvLQ9+95Ttu2aZtmz9c97Iqqu39AV559Ni/90i/vbNJwmF5ZpqiqrbYsU1RlemW11S5sn6vKFDfGyjKjssqfeNVY8a5XrutVx7bWKqu0Cwu5Vgxyte3natvLdL3NtN7ItFnfauuNTOpX+tOb/VfGrjYb+7NpOzSqhp3ktO3WHt1vRlV3j1m9H/c36e49vL45z/X1nX8/25i3+da19bf03bnfKzKqBluvcrjdH2Z8Y6wavqq99fzW2NGFfoqi2HUNAAAAAAAAAAAAAAAAAAAAANwbunviCQAAAAAAAAAAAAAAAAAAAAAAALAjzcY837q2ftBldG51UneWtTSusvLiy53lHbRBr8iDozIvXVvP4rh/0OW8bfTKhbz863/7oMs4ELP+MG2bnFk+n/f/42fzkS/+heSP/V+SH/25Pc1pZ7M9Xe9e0SurzrLautn5pPX1zNfXk6tXs7n3Jb1GkWQ8GOREWaaoqvTKMsWt/apKUS6kV1YpqnK7rZLjC1kfDDPrDzPrDVP3hrle9HOtGOTS9/1gJuttpvVGpvX6q9pX+ldnG2nbt1b/qOrmMaDX1zezOX+Lxd6DutrfJJnWG51lHSZd7fHVA9zfzXmbK9fWc+XaepLru1qj3ytyvBxkVA0yqoYZVYOMb+mPbuu/cn5pXOXkO47u7Q0BAAAAAAAAAAAAAAAAAAAAsG+6e+IJAAAAAAAAAAAAAAAAAAAAAAAA3OPWN+d5udnIiaMLneQtjqpOcg6btUnTWdbiqMzKiy93lrdf+r0ii6Ny6zWusjQuszjabsdVlkZVFsdl3nl0Ib1ecdDlvu0MHnooRVWlreuDLqVzTX+YJPnx4tfz6N//haRok1/7+a2TP/pze5ZzP+5tkhRVd58D7ay7371vycZG5hsbycsvZ3OXS1Tbr3ck+eO/eT69hTf/XJ/P21ydbWRab2Rar9/WTu4w9ur+wjdWM/71X8nkSydSlGV6ZZmiqrb6VZWirNIrF1JUVXplmQyHKYrd/b6e1hu7mnevG5XDzrKm9XpnWYfJuOrmUbb3+nt4c97mpevreen6epLrdz3vT3/ovfnkP/cD+1cYAAAAAAAAAAAAAAAAAAAAAHuqm6dxAAAAAAAAAAAAAAAAAAAAAAAAwCG2vjnPi1ebrE6arE7qrE2brE3qrE7qrE6am8ffeHmWD7/vRH75Z364k7qWxmUnOYfN2rTuLGtxXHWWtRv9XpEHj5dZGpd5cFRlaVxmaVxlcbTdjsssjqq869hCer3ioMu9bxW9Xhbe//40v/d7B11K52b9YX6i9+t5avgL6RXtKyd+7ee32h/9uT3JmdfNnqxzr+lV3X0O3Jd7XBQphsO7urTXKzKuhhlXwyRHdhw1+Rt/I1/915/IV+92Qq+XoqrSW1jYassyRVWlqMr0Frb6vapMUb527MpGkcf+4cXM+oPM+sM0/WFmva12/ebxYKvdPjfrD7Pe6yfFvftZMqq6e8zqtN7oLOsw2Xr/779Jvd5JzmHT5Xv4v/5fv5JLV65nVA0zqgYZVYOMb/ZfGTu2MPAdEwAAAAAAAAAAAAAAAAAAAOB1dPe0CAAAAAAAAAAAAAAAAAAAAAAAAOjY+uY8L15tsjZpsjqpszptcnlSZ3XSZHVaZ23SZG1a5xsvz9K2d7fm6qTZ36JvsTSuOss6TDrd41HZWdat+r0i7z6+kKVxlcVRlcVxmaVRlaVxmcVxmcVRlaVxlXceW0i/VxxIjfeitm2z8fWvZ7aykmZlJUf+wB/Ike///k6yF06dSvN7v9dJ1mHyRwe/mZ8b/nfpFXf4JfprP7/V/ujPveWctqnf8hr3oqLs7nOgre+/PS6qKkXRze/YttnhZ9t8nvbatWxeu7arvJ/axZx5isz6g8x6w8z6wzT9G+0g671bj4fb1wy2jm+5fr0/uO34S+/49nyrGu/qHnZqVA07yUmSabPeWdZh0tUeT+uNTnIOmy7fw//jF7+aL1z41pteVxTJ8XKQcTXMqBpsv+7UH2Z8h7FRNcjxhUF6vs8CAAAAAAAAAAAAAAAAAAAAb0ODgy4AAAAAAAAAAAAAAAAAAAAAAAAAdmpjc54Xr86yNq2zOmmyOqmzNm2yNqmzOtkaW5s2+cbLTdp2b7MvT5u0bZuiKPZ24TtYHJX7nnEYrU7qzrKWxtWertcrkgdHZRZHVZbGZRbHVRZHZZbG28ejKovjMu86Vqbf2//30NvV/Nq1zC5cSPP8SmYrW6/mwkpmKxfSXr9+87p3/fRP5cj3f38nNZUfOJVpJ0mHy79Z/vfpFW/wi/bXfn6r/dGfe0s5bdO8pfn3qqJc6Cxrfh/uca/s7nN2Xh/+/e2lTbW5nmpzPVnfmzX/3Y/+mfyvD33f3iz2BnrtPN/5238n0yNfS1FW6VVliqpKUZbplVv9G21Rlm/5e9y03tijyu8dg16RatjrJGta79Eb8B4zqrp7VPDdvofbduvat/KeL4rk+MIgo2qQUTXcbm/tb7XjO4zd6B8vB747AwAAAAAAAAAAAAAAAAAAAIdOd0+LAAAAAAAAAAAAAAAAAAAAAAAAgDexsTnPN16eZXVSZ23SZHVaZ3XS5PJ2uzqpszZt8uLVJm17MDXONue5cm097zi2sO9ZS+Nq3zMOo8vTprOsxXF5V9f1iuTdx8ssjassjsosjqssjcssjrbaG+PvOl6m3yv2uer7QzufZ+PSpTQrFzJbWclsZSXNyvOZrVzIxte/fldrzFYu7G+Rt1g4daqzrMOkP7iLX8a/9vNb7Y/+3K5z5nV3vxcOk17Z3edAW9edZR0WRXl3nwF7oW3uv/1Nkj/2B07mve/7tkzrjUzr9e32lf7GfG++0C1srudD/+V/lIv/5d1dXywspKiq9Mpyq63KFAvl64yV6ZXVbWM/8NwLec/1Nk1/mPXeIE1/mFl/uNX2hpn1B685boventzrQRlVgxRFN99xpvVGJzmHzagadpbV5R63bTJtNjJtNpKXdv+78Hg5yKi68Rq+qh1kfEt/VN5+flwNc7wa+J4OAAAAAAAAAAAAAAAAAAAA7KnBQRcAAAAAAAAAAAAAAAAAAAAAAADA29/mvM03rjZZnTRZm9ZZnTRZndRZmzZZm9RZ3R77xtUm8/agq31za9Mm7zi2sO85D47Kfc84jFYndWdZ7xlXeXBUZmlcZmlUZXFcZnFUZWlcZXFUZmlcZWlc5l3Hy/R7RWd13U82r76c2YULma08n9nKSpqVlcxWLmR24ULa+q29F2YrK3tU5ZtbePhUZ1mHSdG/y1/av/bzW+2P/tyuctqmu98Lh0lRVZ1ltU3TWdZhUVTdfc7O6/tvf5PkX/onvitH/+CH7niubdvU6/NM6/VM6o1M6/VM643t1/rNdvLqseb269Y325Sb6zuqq53N0s5mme/yvv65XcxZ7/XT9IaZ9Ydp+lvtrDe47bjpD7PeG9x2POsNM+tvX7c9f+s1yNePvisXR4u7vIudGVXDTnKSZFrv7Of5djGuuntU8OQe3OOrzUauNhu59NLu5n/H4vF87t/4Y3tbFAAAAAAAAAAAAAAAAAAAAHBf6+5pEQAAAAAAAAAAAAAAAAAAAAAAALztbM7bfOPlJmuTJquTOmvTrXZ10uTydKtdndR58WqTeXvQ1e6d1Umd73rPaN9zqmE/DxwZ5qXr6/uedZi8PNvM1WYjx8v9f1zaRz/wrnzhz39s33Pud+3mZtYvXcpsZSWzlZU0KyuZPb/V31hb27fc2YULaTc3U/T7+5Zxw8KRq/uecRj1+jv45f5r//fku/9E8tD37zhnXjc7nvN20KvKzrLmzf23x72y6iyrrevOsg6Tonz993BRFDmy0M+RhX4Wx7tbv23bNBvzfOvCC7ny/9llkR0ZzjcznG8mG3v3XvjrD/+hfPpDP7Fn672RP/CtlVz9tV6KskqvKlOU5Sv9qkqv3B4bvPXvb9N6Yw8qvveMqm4eFTyft7na3H973NX+JslzL3wrK5dfzqgaZFQNM6oGGW+3o2qQQb/XWS0AAAAAAAAAAAAAAAAAAADA/unuaQYAAAAAAAAAAAAAAAAAAAAAAAC87fyFZ38r/+3f+8cHXUbnVid1Z1lL4zIvXV/vLO+wWJvUOf7g8YMugx3avHo1s5WVzFZW0jz/fGYrF7aOv/KVtE3TeT3tbJb1S5eycPLkvmf1v+OHMh8dTW96bd+zDpOi397VdfO2yLkf+Iv5yEPfv6ucdtb9++cwKMqqs6y27u6z7bAoqg739759D5f7u35RpBr2885+cmVfkw6nWb+7R8v+qc9/Nv/4s//wzS8cDNIryxRVlaJcSK+sUlTVHcbKW84tpLhl7F1f/lb++AtXMusP0vSHmfWHafrDrPeG28fb472tc5u9/v5vQAdG1bCTnJdnG2nv7uP7baWr/U2S/+HvfzX/1d/9yuuePzLsZ1QNtl/DjKpBxtvtrWOjW8bGrxob9nud3Q8AAAAAAAAAAAAAAAAAAABwZ909/QMAAAAAAAAAAAAAAAAAAAAAAIC3nQdH1UGXcCDWpk1nWUvjKl9avdpZ3kF617GFLI6rLI3LtAddDK+r3dzM+te+ltnzz6dZWcls5UJmKytpVp7P5uUXD7q815itrGTh5Ml9z/ntr72U3yofyiPTf7TvWYdG0abovfll87bImfWfyi9//lT+2g++lO997wM7jmrrehcF3vt6VdlZ1rzp7rPtsOiVHe5vff/tb5L0qm6+K7az+3N/m/6ws6xyvnF3F25sZL6xkbz88q6zfmD7dbc2i16a/jCz3iBNf5j1/jBNb5hZf5imP3jV8VY76w1uP75l/o3jlwdVvvyOb9/1fezUqOrmUcGT+i5/lm8zXe1vkkzfZI+vr2/m+vrmW/q7shr2Mq6GGVWDjLbbV45fGRvdMvbq64f9u/giBwAAAAAAAAAAAAAAAAAAALyu7p5mAAAAAAAAAAAAAAAAAAAAAAAAwL6Zz9t889osq5M612ab+cjD7+wkd2lcdpJz2KxN6s6yHhzd+3v8rmMLeXBUZmlcZWlcZnG03Y6rLG6Pv/t4mYVB76BL5Rabk0lmKytpVlYye34ls5WVzC6sZPaVF9LOZgdd3l2brawkf/SP7nvO9773gVz87u9MfuMf7XvW3Rp+27dl/atf3bf1e/32Ta+Zt0XOrP9Ufmn+I/nZH/vOfO97H9hV1rxudjXvXleU3XwGtG2btrn/9rioqs6y2qa77w6HSVF2s8dtfX/u70MPPpBHTj6Qab2RSb2Rab2eZmO+L1kLm+v7su5e6LfzHN1ocjR7+3ts9cg78mf+yT+/p2u+nodefjFHzp/Lta+OU5RVelWZoqpSLCykV1Vb/eEwRVG85axpfXh/lvtpXHX3KOZJvbHvGfX6PPV6k7Xp7t/31bCXUTXMqBpkVA0zrgZb/fKVsdGNsZvnbx/zNxwAAAAAAAAAAAAAAAAAAAD3s+6eZgAAAAAAAAAAAAAAAAAAAAAAAMCOzedtvnltlrVJk9VpnbVJfbO/OmmyNm2yNqlzedpkY94mSRZHZf7en/9YJ/UtjapOcg6b1UnTWdbS+PDu8TuPLWRxVGZxXGVpVGZpXGVxXGZxVGVpvDX+4PEyC4PeQZfK62g3NrL+1a+mef75zFYuZLayktnKSpqVlWx+4xsHXd6eaFZWOsv6yB/9UFZ/4290lve6iiIPPflkTjz+WK589tlcOns2adtdrfOe/9M/k/GL/3nm86TdKDLfLNLeeL3JkvO2yJn1n8ovzX8kP/tj35knPv7B3d1Pkrapdz33XlaUZTdB6+vJfN5N1iFSlAudZc3r7r47HCa9qpv38P26v//7P/wd+ek/+0duG2s2NnO13sj05ms9k3ojk3r95vHt7Sv9yXa/2Xjt74Ph5npXt3VoNP1hZ1l/7OIXc+1nfz5feaOLiiJFVaW3sJCiqlJUZXpl9TpjZXplmaJ87dj16UZ+5OILafrDzPrDzHqDzPrDm8dNf5j13uBmm6Loahv21ajq7uc5re+Nfy/1+jz1epPL093/Di0HvYyqYcbVIH/ziR/JsO9vPwAAAAAAAAAAAAAAAAAAAO4fg4MuAAAAAAAAAAAAAAAAAAAAAAAA4H40n7f51rVZVidN1qZ11iZNVid11qZb7eq0yeXt4415u6O1X7zaZHPept8r9qn6VyyOy33POIzWpnVnWUuj7vf4HUeHWRpXWRxXWRyVWRqXW8ejMovjKkvjKg8eL7Mw6HVeG7vXrKzk+t//YmYrK2lWns9s5UJmL7yQrK8fdGn7avb8SmdZC6dOdZb1uooiDz35ZE48/liS3GwvnT2btDv7PEnb5uv/2V9L8dEyJ05d39HUeVvkzPpP5ZfmP5Kf/bHvzBMf/+DOsl9l9PGPp/zgBzOv67RNk7ZpMq+btE29NVY3aWfbY3WdeXOnsa22bZqb/RvtjvemI72q6iRn3jSd5Bw2vbKb/U2S9j7d46Kj93DbdPfd7DApqtd+TywH/ZTH+3nX8d1/h5xtzDOt1zOtN7Zf6zn+65tvpdR70qw/7Cyr3LyL72Ntm/b69Wxev5689NKus6okP3eX185TZNYfZL03SNMfZtYfbrW9YWb9wdZxb2t86zW47Xjr2sHtx7eMXRg/1Nk+j8ruHsU8rTc6yzpozcY8zdUmk3o9w343fx++eLXJV791PaNqkFE1zKgapBr2O8kGAAAAAAAAAAAAAAAAAACAW3X3NAMAAAAAAAAAAAAAAAAAAAAAAID7QNu2+da19axO6qxO6qxNm6xN6qxOmqxNt9tJnctXm6xvtvtSw7xNvnG1yeK42pf1b7XUQcZhtDppOsvayz1+x9FhFkdVFsdllsZVFkdb7dK4zIOjG22ZctDfs0wOj8lf/3/nxU9/+qDL6NxsZaWzrIVTp3Y+qWgzPLaZcryRhdFGNpsiL104mqTYxVpFHnryyZx4/LHbhm8cXzp7Nml3+tlT5NLnT2ytc+r6Xc2Yt0XOrP9Ufmn+I/nZH/vOPPHxD+4w87UG7353Bu9+91te507atk3W1zNvmrR1fXt7o183aZsb57b79db5eVOnrV9pX3/s9vUzn79pbUXZzedsW9ed5Bw2RVV2ljVv7tM9XljoJGded/fd7DDpVfvzO2Jh0Mu7jpd51/FX/o383vosb/5b6+2l6Q87yzqWzc6ydqKXNtXmeqrN9YzW7+57wE78yz/2b+fiaHHP1321aqPJe7/yu7n+m9dTlFV65UKKqkpRlultt0Wvt2d502Z9z9a6V4yr7h51/bf+t7X828u/edvYQr+XUTXYfg3v0B9mfIexG9eNq2HKQS9FsYvv4AAAAAAAAAAAAAAAAAAAANy3uvu/7QEAAAAAAAAAAAAAAAAAAAAAAO5hbdvmW9fWszatszppsjqpc3m61a5O6qxNm6xNmqxN66xvtgddblYnTRbH1b7nvOvYQnpFMj/4W+7U5WmTtm1TFMW+Zy2Oyze95sTRYZZGVRbHZRZHVZbGZRZHZZbGVRbHVRZHZR4clamG/X2vl8Nr4dTDB13CgdhYW8vm1ZfTP35s37OG731vioWFtLPZa871FuYpRxtZGG1kYbz1KkcbGR7fSG/7n+aVlSO59PkTSXbxu6Uo8tCTT+bE44/d8fSN8UtnzybtTn9pF9t1JSdOXX/DK+dtkTPrP5Vfmv9IfvbHvjNPfPyDO8zqXlEUycJC+gsLyWjUSWbbtsnGRuZNk7auM6+btE2dtmlu9ud1nfL3faCTeubNa9+z94Neuf/flW5o66azrMOiKMtOvislSTu7//Y3SYqFN/+euFfauu4s67CY9YedZR0vNjvLOkxm/W4ej/zt07X8/v/wk7nwBtcUw2GKqkpRlemV2+1CmaKq0qvKFG80Vm71b4x995d/N0sbRZreMLP+ME1/mPX+8JbjQdb7w8yLXif334VR1d2/l2m98Zqx2eY833h5lm+8vPvvNMN+kVE1zKgabL3KG/2tdnxL/7brquHNc9Ww19lnHwAAAAAAAAAAAAAAAAAAAAevmycnAAAAAAAAAAAAAAAAAAAAAAAAHFJt2+bKtfWsTZusTuqsTuqsTZusTeqsTpqsTuusTZpcnjaZbc4Puty7tjatkzyw7zmDfi/vOl7m8rTZ96zDZLY5z5Vr63nHsYV9z3rviSP5o9/57jw4KrM0rrI0KrM4rrI0LrM4qvLgqEw17O97Hdz7ylOnDrqEAzO7cCFHvu979z2n6Pdz7Id/OEmycOpUFk49nP/hxUGe/tIsH6vO5amF/zS9or3j3CsrR3Lp8yeSFLsILvLQk0/mxOOPveFlN85fOns2ae9cxxuEbNeXnDh1/Y5XzNsiZ9Z/Kr80/5H87I99Z574+Ad3mHH/KIoiGQ7THw6T48cPupwM3v2uvO+//C/SNk3mdZO2qTOv67R1k3Z261iTtq5fGavrzJvtdtZsXX/b2CxZXz/o23tdRVV1ltXWdWdZh0WX+zu/D/c3SYqq7CSnnc/THuJ/y/ulWFjIsYV+Xp5t7nvW0XZj3zMOo6Y/7CRnYf7m+9uur2+9z6fTvNWf+L9xl9etF/3M+sM0/WFm/UFm/WFmvRvHw8x6g1f6t52787WvrLXVvnjkgUwXjr3Fu7k7o6q7R11P6/35fbS+2eabL8/yzZdnu15j0CsyqgYZVcPt9pX++A5jr5x7pX9k2N/6rggAAAAAAAAAAAAAAAAAAMCh193/bQ8AAAAAAAAAAAAAAAAAAAAAAHAAvv5SnS+vTbM6abI6qXN5utWuTuqsTZusTZrMNucHXeaeW500nWUtjctcnnaXd1isTuu849jCvuc89MCR/Nd/9qP7nkP32rbN5je/mf6JEyn6/X3PW3j44X3POKxmKys58n3f20nWt/8nf+W24z+T5Fu/8qX85b91PP/cD7wvH/niX0jS3nbNlZUjufT5E0mKnQcWRR568smcePyxu7r8xnWXzp5N2vaNL35t2HadyYlT119z7twP/MX88udP5Wd/7DvzxMc/uMO1OUi9qsqxH/qhfVm73dhI2zSZN81WW9dpmyZtXWdeN2lnr4zN6zrtrWN1k3mzPXZjjbp+nbGttm2atOvrd3nf5b7c853MZ7POsg6LXtnd/rb1/fddNNn6t9uFtrk/9/ePft/J/Pa/909lc97mar2RSb2eab2R6Y22uXF867lbzt8ydrXZeMOso3nj829Xs96wk5yFzbv7XOjasN3McGMzxzbqfVn/F77vT+XZ7/iRfVn71b7zysXUv/M7KaoqvbJMUVUpyiq9ciHFcG9/ztP68P572Zi3+da19Xzr2u7fc4NekePVIKNqkFE53GqrYf6dP/k9ef+7ju1htQAAAAAAAAAAAAAAAAAAALxVg4MuAAAAAAAAAAAAAAAAAAAAAAAAYD8tn/vH+Uv/05cOuozOrU7qzrKWRlX+QSad5R0Wa5Mm3/2eg66Ce8F8Nsv6Cy+kef75zFYuZLayktnKSpoLFzJ/6aX8vr/5N7Lw/vfvex29o0czeOihbFy6tO9Zh81s5fkDzX/i4x/M/+57l/K97/0TycPvTJ79mSRtkuTKypFc+vyJJMXOFy6KPPTkkznx+GM7mnbj+ktnzyZtu9PQ7XqTE6eu3xzLY38lH/nQT+av/eBL+d73PrDDNXk7KwaDFINBeseOdZbZbm6mbZrMmyZtXd/Wn9dN2lmTeV2nfPjh7mqqu/tudlgUVdVZVtvcf/ubJEVZdpIzvw/fv0nSq7b2t98r8sDRYR44Otz1WpvzNlebjUzr9Uzrje3X+s32Axd3v/a9bNbv5r4XNtc7yTlsmo72N0l+8pf/46z8N9M7n+z30yvLFFWVoirTW9jq3xwrF9Irq62xqkxRvsFYVeWBL34tH7o8SdMbZtYfZNYfbvdvvAbZKPpJsYvv14fAxrzNlWvruXJtPcn1m+P/13/6u7rJ35yn2Zjn6EI/xT26hwAAAAAAAAAAAAAAAAAAAF0ZHHQBAAAAAAAAAAAAAAAAAAAAAAAA+2lxXB10CQdibdp0lrU4LjvLOiijapClcZWlcZnFUZXFcZmHHrg/31vcWdu22XzxxTQrK5mtXMhsZSXNyvOZrVzI+sWLyXz+unOblZUsvP/9ndRZnno4G5cudZJ1mDQrKwddQr73vQ9sdT70k1vtsz+TKytVLn3+RJJi5wsWRR568smcePyxXdVzY96ls2eTtt1p+HbdyYlTdfLYX7l5XzfvEw5Q0e+nOHo0vaNHD7qUmx769/7dbL70UuZ1k7apM2+atDf6dZO2aTJv6rsca9LWddqmu+97u9ErFzrLmh/yvdgvvaqb76OH/b22X4py7/a33yvywJFhHjgyvOP5F/6fRV7es7R7w2bRy2av30lWubneSc5hs97v7vHTw43Z65/c3Mz82rXk2rU9yfr49uuNbKbIrD/MrD9M0x9m1hu8yfEws/7gtuOmP8x6f3Db8Y05s94g04Wj+VY13pN7uhuj6s6/P/ba//b1af7kp34j/V6R4+Ugo2qQUTXMqBpkfEt/dFv/TueHObbQT1Hs4m8dAAAAAAAAAAAAAAAAAACAe0R3/2c/AAAAAAAAAAAAAAAAAAAAAABwX2rbNtNmI2uTOmuTJqvTOt96eT3/xz9yqpP8pXHVSc5hszapO8taHN27ezwqB1kcl1kaV1kcbbfjKkvjMoujV9ojC/2DLpVDYt40mX3lK5mtXMhs5fnMVlbSrFzIbGUl8+l0V2vOVi4k/8Selvm6Fh4+lZf/zt/tJuwQWX/hHx90Cbf70E/myq+dz6X/7n9IUuxigTYP/fSfyonHH3tLZZx4/LHkhb+bS//JbuoocunzJ5IP/+mc+NBPvqU64H5w9CMf2fM127ZN2zRpmybzuknb1JnX9Z3H6ibt7A3G6jrzZqttm+Zmf7691q3n71ZRdvcdsa2bzrIOk672eCc/97eToio7y5o3998eN/1hZ1kL8/XOsg6Tzva4bTNYP1x73E+bI5uzHNmc7VvG/2/xu/Lv/OF/ed/Wv9XitW+mvHghs9GxFAtlelWZoqpSLCykKHbz98Trm9YbSZLNeZuXrq/npevrSa7vaq1ekRwvBxlVw4yqQcbb7dZr+Kr21vOvjB1bGKTX29t7BAAAAAAAAAAAAAAAAAAA2CuDgy4AAAAAAAAAAAAAAAAAAAAAAAC4N7Vtm6vNRlYnTdYmddamTVYn9dbxtM7apMnqdnt9ffM18/+FH3pfykF/3+tcHJX7nnEYrU7rzrKWxlVnWXdrVA7y4LjM0qjK0rjM4rjK4qjM0q3tuMzRBY/j4rXats3G5cuZPb+S2YWVzFZW0qysZPb8Sta/+tWkbfc0b/b883u63htZ+MAHOss6CP13vzvlww9n4dSpLHzgA1k49XDKU6cy/LZvO+jSbnPls8/m0v/j/5Wk2MXsNg999EpOfOsXki8+knzoJ3dfyBd/cWudj1a59PkTu6in2LqP9/2hnHj8sd3XAexKURQpqiqpqvQf6Cazbdu0s1napsm8rtM2Tdq6zrxu0s5uH+sdP95NUUnmTXfffQ+TXrnQSc68mXWSc9j0yu7+zmnrprOsw2LW6+5vsYXN9c6yDpNZb9hJzqDdTNHOO8k6TLp8D/9Lv/s3c+nHn3ztiaJIUZYpyjK9skxRVTfbolxIr6xeZ6xMr6pSlK8dm339Wr7vxZXM+sM0/WFm/WFmvVv7g6S4u78b5m0yqTcyqTd2fe9FkRwvBxlXw4yqwfbrTv1hxncYG1WDHF8YpNfbzd9eAAAAAAAAAAAAAAAAAAAAb8yT7AAAAAAAAAAAAAAAAAAAAAAAgNu0bZurzUbWpk1WJ3XWJk3WpnVWJ9vH0yZrk63j6+ubu85ZmzT59nce3cPK72xpXO17xmG0Omk6y1oal51lHS8HWRyVWRyXWRpXWRxtt+MqS6Myi9tjx0qP2eLNzes6s698JbOVlcxWVtI8v3KzP3/55c7qmK2sdJa1cOrhzrL2SzEcZuHh92fh1AeycOpUFk49nPLUqSycOpX+eHzQ5b2pK599NpfOnk3adhez2zz00Ss5cer61uGzP7PVfugnd77UF39xe357c71Lnz+RpNhhSe3W/SQ58fhjO68DuKcURZGiLJOyPFS/c0/8xE/k6Ic/nHldp62btE2ded2kbZrMm62xG+3rjzVp6/pmm/n8oG/rTRVVN3/rtE3dSc5hU5Td/Z1zP+7xu941zt/9uT+eab2Rab2eSb1xs397+/rn53f5depYdv/fLu5lTX/YSc7C5kYnOYfNrKP9TZJjeZ09btu0db31+bVHWYtJnnqTa5reILP+cOvVG6bpv/p4q9/0B1m/7XiY2S1zm1uuX+8Pbjue9Yf5RjVOm+Lm74LdKork+MIgo2qQUTXcbm/tD/Mnv/+hfN+3PbDrDAAAAAAAAAAAAAAAAAAA4P7kiXcAAAAAAAAAAAAAAAAAAAAAAHAfudpsZHVSZ23SZG1a3+yvTpusTupc3m6vzTb3vZa1aZ1vf+fRfc95x9Fhhv0i65vtvmcdJt+42mRjc55Bv7fvWYuj6i2vcXShn6VxlcVRmaVxlaVxmcVRlcVxeXN8cVzleOnxWexM27bZWFvLbGUlzfPPZ7ZyIbOVlcxWVrL+ta8l7cH/bmguXOgsqzx1qrOst2rw4INZOHVq+/Vwyg98IAunTmX43vem6PcPurxdufLZZ3Pp7Nldvu/aPPTRKzlx6vptY3n2Z7a6H/rJu1/qi7+4Pe+VOm6se+nzJ5IUOyyt3bqvJCcef2xncwH2QPVd35Xqu75rz9Zr2zbZ2Mi8adLWdeZ1k7ap0zbNzf683jq+fazZHqtfMzZv6rT19nrNnceyubO/w4qy3LN7fiPzuu4k57DpVd3sb5LMm1lnWYdFv6ry0ANH8tADu5vftm2uzTYzrTcyrdcz2W63jm/tr+f3Xz+XnN/b+u8Fs/6wk5yFzfVOcg6brvY3SY62G51l3Y1yvpFyvpGsX3/zi9+Cf+ZP/4dpd/q3yR20bTJtNjJtNpKXXvuZdnS9zvfnpXxX//0pyjK9qkpRlil6+//f1AAAAAAAAAAAAAAAAAAAgHubJ+MBAAAAAAAAAAAAAAAAAAAAAMDbwMvNRlYndVYnTdamddYmTVYnddamr7RrkzovzzYPutSb1iZNJzlFUWRxVOWrV653kndYzNvkGy/PsjSu9j1raVy+7rkjw37e80CVB0dllsZVlkZlFsdb/cVRdbN/vPRYLN6a+fXrmV24kNnKSpqVlcyeX8lsZSWzCxcyv3btoMt7Q5svvpjNyST98XjfswbveU+Kqkpb1/uedTeKsszC+9+fhQ98IAunHk556lQWtl/948cPurw9deWzz+bS2bNJ2+5idpuHPnolJ07d6bOsTZ79ma3uh37yzZf64i9uX//aOm6sf+nzJ5IUOyyx3bq/JCcef2xncwEOmaIokuEw/eEw6fDzqN3YyLxu0jZ12rrOvGnSNk3mdf1KWzdpZ1v9/rFj3dTVdPO322FTlPv/t9QNh+W7WZeK8vX/jryr+UWRY+Ugx8pB3vPAG/+sLn/lb+XFt5R2b2r6w05yFjbXO8k5bLra3ySp2sPz3/O6MusN0ha9TrI++vXfyakn/kL+4avGi+EwRVWlqMr0yipFWaZXlimqKr2qTLGw3X/NWJleVaUoqxTlwnZ/aywLZX76md9K/8iRLBytUh47murYkRw5fixHR0cyOlpmVA0zqga3tIOMt/vHy0EG/W72BQAAAAAAAAAAAAAAAAAAeHOeoAcAAAAAAAAAAAAAAAAAAAAAAIfYy81G1qZNVid1Vid1Lt/sN1mb1lmbbB2/PNs86FJ3bHVSd5a1OC7z1SvXO8s7LFYndZbG1b7nvOt4mT/7R05lcVRmaVxlcbzdjsocLwcpimLfa+D+0LZtNr7+9cxWVtI8v5LZytarubCSja9dOujy3pLZykqOPPLIvucUvV4WTp1K87u/u+9ZtxosLWXh1KksnHo45alTWTj1gSycOpXhex9K0et1WstBuPLZZ3Pp7NmkbXcxu81DH72SE6fe6HOsTZ79ma3uh37y9S/74i9uX/f6ddzIufT5E0l2+Pu7bbfuM8mJxx/b2VwAUgwG6R8fJMePHXQptyk/+F1571P/YeZ1nbZu0s6am/15sz3WNJk3Tdq6fp2xrbZtmrTr6wd9S3elqMrOsuZN01nWYdErO9zf+v7b3yRZ73Xz+Olyfm/8m95rs/6ws6zqPtzjpsP9Xdi88/626+tbn1nTafbyv7z++Tc4t170M+sPM+sPMusN81J/mMu3HDf9YTaHC2kXFpKFMkVZpqiq9Koyg6rK4MiRDI9WWTh6JOWxo6mOVTly/FiOHD+aY6NjOT46muMPHMvw6JH0x+MUw+72GQAAAAAAAAAAAAAAAAAA3o66+T/7AQAAAAAAAAAAAAAAAAAAAACA1/UP167mf/69taxNm6xO6qxO6qxNm6xNmlxtNg66vH2zOm06y1oaVZ1lHSZrk272uN8r8u/8yd/fSRb3h/nLL6e5cCGzlQuZraxktrKSZmUlswsX0l6/ftDl7YtmZSVHHnmkk6zy1MNpfvd393zdoqqy8PDDWTj1cMpTH8jCqVNbr4cfTv/4sT3Pu1dc+eyzuXT2bNK2u5jd5qGPXsmJU3fzvm+TZ39mq/uhn3zt6S/+4vb5N6/jRt6lz59IUtxtsdtltFv3m+TE44/tbC4Ah9JwaTEP/LP/7J6t125upm2azJsmbdOkreutfl1nXjdpZ03mdZ22btI222NNk3mzs7FXzjVpZ7Md19mruvs7sq3rzrIOi8L+7rumP+wkZ2Hz7fvfrt7IrNfd473L+f23x7OO3r9JsjBf7yzrzQzbzQw3NnNsH37k9fbrxe3j/+iP/3RWft8jGVXDjKpBxtvt1mt4Wzt+VXu8GmTY791VbjufZ+PSpRRVlaIs0yvLFMPufr4AAAAAAAAAAAAAAAAAALCfuvs/zwEAAAAAAAAAAAAAAAAAAAAAgDv67a+9lL/413/3oMvo3Nqk6SxraVx2lnWYrE7rgy4BduzCT/4Luf7ccwddRudmKxc6y1p4+NRbmj94z3tSfuBUFh4+lYVTW6/yA6cyeM97UvR6e1Tl28OVzz6bS2fPJm27i9ltHvrolZw4dX1Hc/Lsz2x1P/STrwx/8Re3x+++jhu5lz5/IkmxgxqStO3WfSc58fhjO5sLwNte0e+nOHo0vaNHO8ts5/O0TZN5Xadtmu1+k7apt8dm2/1Xxqrv+75uamvbtE13fx8fFkXV3d/p8+b+/Nv4P/4XP5rJkXGm9UYm9Xqm9cb2a7vf3D42qTcy25jvOGdhc30fqj/8Zv1hZ1n34x7PevZ3v602yT+6/PKu5x8Z9jOqBtuvYUbVIOPt9taxExvX890/9RO3T+730yvLFFWVoixv9ntlmaIsU1RlemW1NVaVKRZeNVYupCirrbFXrVGUrx3rlWUyHKYodvi3LQAAAAAAAAAAAAAAAAAAvInBQRcAAAAAAAAAAAAAAAAAAAAAAAD3u8VRddAlHIi1ad1Z1uL47bvH5aCXpXGVxVG51Y7LLI6qLI3LPPr+dxx0ebBjvWPHDrqEAzF7/vnOshZOnXrTa4ojR7Jw6uGUD5/KwqlTWfjAqZSnTmXh4YfTO3q0gyrvfVc++2wunT2btO3OJxdFHvrpP5UT3/qFXSS3ybM/k1z6reTb/2Dylb+TfOE/3xrfoROn6uR7/3gu/Rf/887vo2237j/Jiccf23E2AOylotdLceRIekeOHHQpr9W2eejf//fTzprM6yZtU2de12mb2Xa/SVvXmTdN2uaW/uuM3St6ZXd/p7d101nWYfJD3/Pe9EejHc1pNjYzrTe2X+s328kdxm5ct9h+bZ/u4HBr+sPOsoab651lHRazfnePTy/vw/1NktlbfA9fX9/M9fXNrE3f+Hfsu66/lP/m1YObm5lfu5Zcu/aWatiRXi9FWaZXlimqaqu9tV9V6VVlioUyRVWmV1YpqipFubDdL9OrqhRllV65sH1ue2yh3Jp7y9jW+EJ39wcAAAAAAAAAAAAAAAAAwIHo7v+MBgAAAAAAAAAAAAAAAAAAAACAQ+j6bDNr0zpr0yarkzqrk2breNLkLz72fTlW7v+jehbH5b5nHEark7qzrMXRvbfHC4NelsZllkZVFsdlFkdVlsZVFkdllsZVlrbHxkcGKYrioMuFPbNw6uG8/Lf/9kGX0bnZhZXOshY+cOpmf/Deh1I+fCoLH/hAFk49nPLUqSycOpXB0lKKXq+zmt5urnz22Vw6ezZp251PLoo89OSTOfH4Y8kXH0me/ZkkO12nTT7/V5LP7zz+1eucuPZXkx88kkufP5Fkh583bbu1D8nW/eyV+Wby7P85KfpJr5f0Btv9/na/t9Uvto9v9vt3GO/dMu/V19x6be9N1rt1jVfV9LrZ29cCcF8rer2c+Ikf35O12rZNO5ulbZrM6zpt06St68z//+z9e5wc2V0f/H/Oqeqqmku3pJlRj7Ur7aoleVnf1sJ+sMHry7NgribRmjsbJ0ASksdLyMOTEMAmQ8ijJ9gQkhA/8ZoQ4OFHfo8DcQK7JNwJZg0bY4Px+n6TpkcaaXe7pdGley5V1VXnPH9UTU93T480l67TPVOf9+tVr3P61KnzPX10prq6qlXlB9DhHcr8ACpIUh1s5LvL0u0CHzoI03xStptjHuGa+56uw8BYrFEidzHGrm3BnbQwM7n9bZsfXMWVp3Ycat8LrYKxWHYrNBZrVAQGx9dVkbFYo8TUHHbilpE4d6UU9Noa4rU1I+GO/M2/iRf9+DuNxIpu3oSQEsLzIByH54qJiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIDMr+bpVEREREREREREREREREREREREREREREREREREREREREREREREPgt2LUGwHqTR+1RoBaw0et6eNaI0AtLas3fDT8aMs2fvCrz+DU0cnM+zpb8jKPMYpqjcBYrFEaY8eSKJdczJY8lItpWnIxW/Ta5bNFD6UxG0KIYXeXyDi3Uhl2F4YivHQZOo4hLCvzWO6LX4zKk78J5/77IcfGMo+XN7d+80k8/853AlrvfGMhcOynfgqH3/oooBRQeRPw8D8EnnkPgF20NyCHK2sAgOc/chjADj+btE7GA0je1yDELeCTvz6YtkaBtAFhAdJK8zLJi/S1tJKyB78Z+IafMtOnT/0XYOlCR7/69Kfd3946nXVlz3Z96rbbkN3tbRk7rUtERJsIISBcF3BdWKWSkZhaa+hWCzoIoH0faj31A+iwIx+sp0neOXnSSP8AQPnmzj+MDCmBQsFIKB2ERuKMmkCaGV8AsKL8jXFomRvfCcTGYo0SU2Psxi0jcUaN9FxjsRb/3t+H/6lPJS/SYwHhupCuC+F5Seq6EJ4L6XpblKX12/nuMuklbQnHbefX2xeOA8HvaERERERERERERERERERERERERERERERERERERJRT9rA7QERElAdCiB8A8PgAmpoYQBtERERERERERERERERERERERERERERERERERERERERE+5rfinGtGaDW8FFP01ojQL3po97YKL+91tpzrFojwKmjkwPo9Z1NujYmHAsrYZx5rFFye60FvxXDK1iZxyqX3MxjOJbE0aKL2ZKL2ZKHctFFueS187MlD7MlF4fGChBCZN4fot3ScYzW1asIq1UE81WE1SpEoYAXzf1TI/GdSsVInFGjwxCt556Dc+JE5rGk48B78MHM4+TRrd98Es+/852A1jvfWADH3vZaHG79JvC+nwVuXARaq4Pv5C4drqwBAJ7/yGEAO/wc0zoZFwCH3/ro3jujD9gxk4oARMDd3tbqkoneJD71AeCLv2cu3m5IGxAWIK00L5O8SF9LKy2ze8plz3ZWUmaPAX/jP5vp+415YPGjHf2w+r+Xzve4qe5W77Ffe+tlPAYlosETQkA4DuA4QLE47O70deSx78bkG14P5QfQQQAd+Gneb5epwIf2A2jfhwr6lyHeP8cgwnWNnXvQgW8kzqgJrYKxWFYrNBZrVITS3PhOIDIWa5QEhsbYUXs/T78f/eanr+Hj//FjKHo2il4hTW2U2vmNsvX8bs+Ta79jP6w1tO8nn10Dei/bIRwHwvMgXTf5DPJcSNfbosxNy7ytyzwPwnEhPXejDc+DcN2NvJQG3yERERERERERERERERERERERERERERERERERERFRf/awO0BERJQTRwG8dNidICIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIhplQRSj3ghQb/qoNwLUGj5qzSS9lqa1RoDbay1jfao3fWOxZkse5q+vGIs3Kq41A5yYGs88zmzR2/W2BUugXPRQLrmYXU9LHsrFNE3LD48XIIQYYK+JshXfvo2wWkVQXUBYrab5ebQuXYZude9rrcOH8aK5f2qkX07llJE4oyicn4dz4sSwu0G75H/uc3j+ne8EtN7F1hrHXnMLh1u/AXx24F0bmMOVNQDA8x85DGCHn3la4/l3vhPeg18G7yUv2VtHVLy37fcraZmLtR/GWEUAImBQXbXHBtTQNlz6MPDU4+bitQlA2slcElaal2k+fS2spKydtzrqd25nAUL2tNdTt7M9YQGv+X5g9mXZv02lgCsf3eK92Gm/re7yTf3veI88xifa94qPPDKQdnQUQfkBdOBD+z5UEEAHAZTvb6R+AB1u5FXgQwchdOAn2/r+Rtl6Gx1t9ZYhinbVV+m6A3nP26H8wFisUfKtX1nBV7zkATSDCE2/hcZahIbfQtNPXidphLXW3g5WpIoh4n1wbDZggVUwFmt8YAeU+0toaIyd2Nz5/FFy4XYLv/eZF3a0jWNJFD07XQp98gWU+pR5q2sZvYvt02EIHYZQhuI599+P07//e0ZiKd8HlIJwXQjL4PdyIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi2hfsYXeAiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiA62IIpxrRmg1ghQb/ioNwPUGn7yuumj3ghQa/q4tdoadlc3qTcCY7GOFl3MX18xFm9U1Bo+TkyNZx7n8HgBjiURxqpdVrAEykUPR4suZksuZkseykUX5ZLXzs+WPBweK0BKkXkfibKgowitK1cQVKsIqwsIq/PtfLy0tO124lu3EN28CfvIkQx7m7DLRyHHx6FWVzOPNWqCahWTb3rTsLtBu+S95CWYefxxXH/ve3e4pcax197C4cpaJv0atPV+Pv+RwwB29vk48/jj8F7ykr13QkV7b2M/EtJcrDyOsbTMxdKxuVjdgQHVSpZh+LJvAmZfln2caA345a8fXHtCAtIGhJXME2lt5IWVrJOyI2/1ryvttC2ru7319nfVnrVRd/blwIvfPLj3fSerNwAV37lPRAeQsG1YkzYwOWEspo4i6CCACgJo34fyA+iwIx9slCnfh07LYJu79bQOfGOxRsnXnL0fk69/8V3rtWKFZT9C04/Q8Fto+hGavWmQ5Btpvc71rWb+zhcCQGgVjMUa1zk89gUQWGb2E06c1/Hd+RwOY4WllRBLK+GOtvv12yso7Tja/iY8z1ispV/4BVx/4n3Ji0IB0nUhPK+dCteBdD0Iz01TD9J1IDrLXBfSczfKPA/C2SiTXtrWelln+5bB76pERERERERERERERERERERERERERERERERERES0Y+b+dz8RERERERERERERERERERERERERERERERERERERERERERERHShhpHBtOUCt4aPe8FFvJvlaI0mvpa9vrraG3dVdqzV8Y7FmS56xWKOk3gyMxBFC4Ge/45UoeTbKRQ+zJRdHxh1IKYzEJ8pafOsWgmoV4XwV4UI1yVcXEF6+DLQGsx8Oq1XYR44MpK07EULAqVTgf+YzmccaNlkqwamchHuyAqdSwfhXfMWwu0R7dPQH/wGwXMP1/99/2eYWGsdeewuHK2uZ9mvQ1vv7/EcOA9jeZ+nMD/xAMj6DoNVg2tlvpGUulo7NxRoVJsdX5XB8AUBKM3FUNNj2tALicLBtZuHs24AXv9lMrP/6d4GL/+POdYQFSDv52xJWkrbz6+UyLbf71OmsK/u0J3u2s/u3J2TPdp3t7SC27QJf9o1mxpeog7BtCNuGnJgYdle2NPaqV6P8T34Yyveh/QAq8KGDENr3oYIgTfuUhQG0n+T1gL63miQ9d1v1CpbEkQkHRyacXcWJbtzAl35zV5vua6E0d/t0Tw/42GGfaFkFI3HceP/9fQ9CaGh8AaCQwzEW29wHD4LyO65htFpQrRawvAxj3+psG9J1ITyvnQrX7VPmQLpeUua5EG5nmQvpeRCOu5F3O9J2G+m2Nh9hQUREREREREREREREREREREREREREREREREREtF38X3lEREREREREREREREREREREREREREREREREREREREREREREdFdfrDXxHz40j1ozQL3ho94McGMlHHa3MldrBsZizZZcY7FGSa3hG4v11195j7FYRFnQrRbCxSsIF6oIq1UE1SrC+SQf37yZefywWsX4q16VeRwAcCoV+J/5jJFYmbMsFI7fC/dkBc6pU3AqJ+FWKnAqFVjT0xBCDLuHNGBH/9GP4i8+/X5UPubcsZ4CUH/jGl5yz5qZjg3Y4coaPu66KH9oHPIudavf+hq85Af/weCCq3hwbe0n0uAtJJUyF2tUCMtcLBWZizVKTI1xbvcRBuew3sYY6xiIY+Cg/HO4JeAdi2ZiPft+4Ld/OPk3lVbytyOt5HNAWICUaWr3rO+tK3u2s9Kyzu3sLdqT3dt1ttdVt7e9O8TurNMv9pH7AbdoZoxpoMZe/jKMvfxle2pDxzF0EEAFAXQQQPt+O698fyP1A+hwI68CHzoI0/r9ypK2km2CnrK9ndsUrren7bdL++bOnY2S0CoYi+Xm8NisJSwocbdvcoPhqJaROKMmMDiHC9HBv1bTSxraBwOADsxdJ+oriqCiCFhZMXdobVk4/fu/B+f48cxD6Tj93lAo8DwpERERERERERERERERERERERERERERERERERHtSwbvCkRERERERERERERERERERERERERERERERERERERERERERERE+1XTb+EDH7sy7G4YV2/4xmKVi56xWKOk1giG3QWikRPdvImwWkU4P4+gWkVYXUheLy4CUTS0foXVqrFYzqmKsViDIg8dglupwGkvJ+GeOgXnxAkIxxl298igJz73q3jf143j28difPuf6b51FID3vUXiQ68o4vz1Fs4tr5jt5AA8NTmBudcV8caixtt/W0FuUe8Drxf4wAN/hYVnn8DjZx8fTHAdD6ad/UZY5mKp4X3eDI00OL5amYs1SqSh26DmdnxN7iNyuB8WW33SZSDygdb+OzbYs7f9BnDma7KPEzSBX/q65HNVpks7byf/1u38+nqZvG7XtQEpO/Lr5bJ7u872uur2tneH2J117hi733vp6JPlALab/fjukrAsiPFxyPFxYzG1UtBhCO37UEEAHQRQvg8dBEmZH0CHaZkfQAU+dBBCBz6U78OeLRvppwryee4ssArGYrlxy1isUREaHF8nh+MLAC1jx74adis0E2uEXLjdwn/+/c+j6BVQ9Ox2WurIF70CJhwLQog9xVKBuetEIyOOjZ3PXPvEJ3HpsccAKSE8D9J1IVw3ST0PwnMhXS8p81wIt39Ze11vmedBOG47327XdSEKhT3PDyIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIkP/q5SIiCj3rgH47ADaeRDY8t6JRERERERERERERERERERERERERERERERERERERERERJkpF71hd2Eo6s3AWKxyyTUWyxRLChyddFEuuSgXPcx2pLMlD0eLLk4cGR92N4mGQochwsVFhNUqgmoVYXUB4fw8wmoV8e3bw+5eX0F1wVgst1IxFmtHLAvOiRNwKhU4pypwK5UkX6nAOnIEQohh95B6qRi4vQgsXQCmTgNT2c6tJ559Au/7xPsAAB94gwUgxrf/me7uEoD3vUXi6YeS2wnNzUwBAM4tr2Tat0F6anICczNT0ELg6YeSef/231abbpD0gdeLdBzQHpfHzz6+9w6oaO9t7EfSMhdLx+ZijQpp8BadKofjC5ibw3kdX2FwH5HHMTa5D87j+ALm9sNxC6gP4vaQ+8yrvxf4a//WTKwP/hRQ+0zydyPtZP8k06Wd7ygXMnndXm8DUvapK3u2623X3qJ8vQ3Z1Z6QFkQa2/IsYKwAyLEt+pSWDeE7n3XoEI7+0P8O5fvQQQgd+FB+AO37UEEAHXTkfR8qDKD97rL96IH7pnHu7D1o+hGafitNIzT8FpaDCFrfvY3tcuLW4BrbJwKrYCxWHscXMDfGhZx+P55vRHjvBy/etZ4UwKRro+gVUPRslNI0WQo9aef6jTK1tj/3o3slPTPXBXWYXodTCnp1FfHqqpG4AAAhIDwP0nUhPA/CdSBdb6PMdSE8Ny1L094yz4NwXEhvvY07lLkuhOPwHDIRERERERERERERERERERERERERERERERER0QFj8K41RERE+aW1fi+A9+61HSFEA0Bx7z0iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiKi/SCKFa4vh6g1fNQaPurNAPWGj1ojQK3po94I8J7vPosz5ez/K/rRopt5jFFUa/jGYs2WPGOx9kqKZE6Uix5mSy7KJQ/loovZUvq66KFccjE94cKSYtjdJRoarTXiGzcQVqsIqlWE81WE1XS5cgWI42F3cUfCatVYLKdSMRarH+vwYTinTsGpnIRbqcCpVOBUTsE5cRyiUBhq36gPrYGVa8DShY7lYpLemAfiMKn3df8X8LofzKwbn7/xefz8J36+q+wDb7AAxPj2P9MAAAXgfW+RePohudF9ITA3MwUAOLe8kln/BuWpyQnMzUxBi43P+PX38/bfVlh/Zx94vUjf/4af/8TP46vv+2o8OPXg3jqh9tf+c2Ckdfc6g5LHMRYmxzcyF2uUmBrjvI6vyX2E5j4iU1qZizVKTM3hvO4jTM7hS/8TWPhTc/FMElYyV6Wd5mWSjk8DP/iXmYS0p6Yw87/9bxsFlz8CfO63ADkByEMdfbI28iLto7SgIaCVgI40VEtBRxo6Ukm+FUNFCjqMoaMYqhVDhzFUK0rKWhFU2IIO07QVQQctqDDcSMMQOgihghA6CNop1N72ZY88dALf/l1f3nedUhorYYSmv7600PQjNNK0s6zZUdboKFsOIiidjnHc2lNf96PQMnd7+gnk8LgBQGiZOX/kxPn8XGttcw4rDTT8CA1/9+P0zz+xiNfseuv9S3hmrlkp39x1uE20hl5bQ7y2Zi6mEBCuixf90x/H4W/7NiMhtdYQgtfqiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiyYu5/7hIRERERERERERERERERERERERERERERERERERERERERERERACCKFa4vh6g3fdQaAWoNH/VmgHrDb+drjQBLKwG0vnNbV2/5OFMuZt5nr2Dh8HgBt1ZbmccaJathjOUgwqSb/e16ykU38xh3IwUwM+lituShXHRRLnmYLbkoF5N0vXx60oUl+RB6onUqDNG6fBnB/DzC6gLCahVhtYqgWoVqNIbdvYEJL1+GbrUgCoXMYzn33595DNg2nPvug1OpwK2chFM5BadSgVM5CfvIkezj0875DeDGRWDpIrB0oWO5CATb+FtbupBp9x6cehDnHz6PuWfmoLFxEPeBN1gAYnzrn2m87y0STz8kN22rhcDczBQA4NzySqb93IunJicwNzMFLTYfB6y/r7f/tsJ/fb1I3/cGAYHzD5/Hg1MP7r0jWu29jf1IWHevMygqMhdrVMjNf5uZ0bG5WKNEGroNKsc3eyqHY2x0fHO4DwbMfc7lcf4CgDR5HHGAx1jHQBwDcdhdLgweR7zwSeDD/27b1UW6AMCuZoEE4KXLNmkNQAEqFtBKQikLWtlJqi3oeL1MQsUWtErrxQI6FlCxwNjlXwH+/X9K9g3SBr7pXwL3nE26JAWKXgFFb/fnJ7TWWAljNP0Wmt/yb3CAZ21foZX9uZ11RZG30U0EhsbYUfm6ZrPO1PgCwJjO4bGZEEbOAQOA9gMjcUaG1tC+b/TY4YuveS10GEK4LqTrQngepOdCuN4WZQ6k620u8zwI905lyZKUuRAmz7MQEREREREREREREREREREREREREREREREREQ2RwTtSEBERERERERERERERERERERERERERERERERERERERERERER1sUaywtBKi3ghQa/ioNX3UGgGupWmt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m5kCAJxbXsmih9vy1OTErvoPAAIC5x8+j3Nnzg2+YyoafJv7gTR4fJjHMRaWuVgqNhdrlEhDt0HN6/gancM53EeYmr9AfuewNDSHtTITZ9SY3EfoHM5hHqdlTxga430wvkICQmpIWwMDOmX/va8/je965BvQ9Fto+BGafgtNP0qXVjtt9JYF3fVa8ebrLbUzL8fUK49D+QF0EEB99vegl29BxwIqRpqKrlTHAlrt/HvoKBHWxlhEyG4f7MatzNoeZW8u/BW+q/Ch9utvCX4SS/pQJrGcHI6xtBReJz8NBYlIS7yAaVzRR9vrV8IYK2GMFxq7jzHuWCh6Nt76+c8hgzNHI096Zq65qjA0EmfUSNfcNW21vAy1sgKsrMDYUbBlQbouhOdBeC6k60G4bv8yz4VwvSR1kvVdZa6b1vN6ytK85yXjadsQuzhHTERERERERERERERERERERERERERERERERJQHBu9IQURERERERERERERERERERERERERERERERERERERERERERJSdS0sr+If/6eOoNQJcWw4QKz3sLhlRbwbGYpWL5h7CPUpqDXNjfKZcNBaL6KDQWiOq1RBWq7CPHoV75oyRuO7JCvxPfNJIrFESzFeNxZp8wxsw+YY3GItHdxC3gJuXgKULPctFoPncsHu3M0sXgGOvNBNr+gzOfekiAGBuZgpaiB1troXA3MwUAODc8srAu3c3T01O7KrfACAgcP7h8zh35lwGPQOgVDbtjjpp8BaSKjYXa1RIy1wsncPxBQBhaIxVZCbOqOEczpap+Qvkc3wBc59zefyMA3gckTWT+wgeC2dL53N8hbQx5lgYcyyUS7trQ2uNIFJo+C00/ShdWjg89nrMHj+0UfHfPwM8P7+N9gAdC6g4SZN8d7qRR5+y3nqAjtIylZZFHfXSskER1sY1KqXlwNrt5cStzNoeZdLqvgaokN0YF6L8jfEx+wbe7/xU+/V/iL4J/yJ620BjrIYxVsMYzdvLA213vxDhDeDWYvL5ZjnAxHQmcbTvZ9LuqBOeZyyWDoYwxnEMtboKrK6aiyklhOdBui7k5CTO/OEfmItNRERERERERERERERERERERERERERERERENOIM/m9+IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiouyMFSx84srtYXfDuHojMBZrtmTuIdyj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TP++8HvAtc/19FH29LdPH9t9l1u/j01t9Na1O8ait+5+PJFERERERJQzZx9L0icfB7DT74k63a6jnUF69v277BcACODRJ7LpFxEREbUZvJpKRERERERERERERERERERERERERERERERERERERERERAdBFCssrYSoNXzUGgHqzSQ9fXQC587ea6QP5aK5B7iNknrT3IO4yiUXy9f2143LpQBmJl2USy5mix7KJQ+zJRflYpLOljyUiy6mJ11YBh5USUQ0LDqK0Lp6FUG1irC6gHB+HmG1imBhAfH169trY20NUa2GwrFjGfcWsA4dgjU1hfjGjcxjjZqwWh12F2gQbl0C/szQQw1GSfN5IFgG3MnsYx25P3mAwm4fDnXoBDB9Gpg+07GcBg7dB1i8Hdt2tOIWri5fxWJzEZebl3GleaWdv9q8ilCFw+7ini02F7Nr/JF3JOnTPw08+gROrH4RH/3SpezijSDPMvOQ8LVozUicUWNqfAHA388PL9oD1zZzLiqv4+vZ5uZwEGdzfk1phdVoFavRaibtd/IsD67twrM8jNlj8GwPruXCsz2MWWPtdZ6drD8+eRzf+eB3Zt4vIiIiIiIiIjJDSoGiV0DRK+y6DaU0VsIITX99aaHpR2ikaWdZs6Os0VG2HERQGT1bveiZu37T9PfX76MGZS/zZye01lgO8jfGpsYXABoZz2Glkxh7iSMEMOnaKHkFFD07XfrlCyj1KSt6NiYdG3IEf/MnhAAcB5bjAMXisLszMPbUFOx7jkH7AbTvQwUBEO/yev0+IVxzv0vWobnfAo8S4ZkZY91qATqjg5QRJg2NLwAoP59zWP7QXwCHDmUeRwf5HF9h9fzdSplZrOYf/AFaV692lOztM1xIDWEli9yUonudrSE769tpKtN6dr82OttP6+31sEhkN76bqIN9DNGXNPibxDyOL5D8ntQElb/vswDMjS+QzzksDY7vbn93vd+Z2g/ndny5j8iWyPRYuEte57CpY2GtAa3MxBolpuYvkOM5zGPhTBn9nNvnY6xVsqjW9reZqmTXn16f+Q3gk79uLt52CZn8HUsrOW4VFtITQ8nr5ORPun6rvL2RF7J7u+/4VcB2sn8fjeeAxY/0fy9d/evtv93R7573Iu2N8t66ez4ZRkRERES0Q2cfS9InHwew09+g6HS7jnYG4dn377I/ACCAR58Y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P9akWb8KXPiOcbfi2Lrfu4923MZKZwXtuL1tee/+e7DYmoT45aWX8annPuWkXYuNRSdxJk07bjuL9b3nvxfffe67Matmi0lV6VDevPomlq8sb/u/sl8CApdfuoxLS5dKaNmjDeIepv0WFstXlrfVQ0RE5RNCoObXUPNrQOg29jMzz+B//N7/ETrVxZLpB/P9tJt2YTIzXN/NujCpeWC7QX6SqcDdWItOJ7svysD+LZ/y3fSxtRbdtOsk1iRxegxP+PnycfTyHnp5D3EvHlsb3u68jb/1q38LKlBQvto9DfYo76f1oA7pS0hf8ns2ERERERFVnucJNFQNDVUDUB93c3a1oas5aXukas5ixbrnLNYkiZSb67Hjyh7D7q53/wc/38JXbt5FpAJEqjZMGyp4oCxSAWbCAJ7H34WIqkjUavBrNWBmxllMm6bItYFNDDxHcXM9+dedl8GT7saDbBX72POAmpvPqMfh3okyCKfH8JM7prkXodzdX2pN9foXADzppo97q2tY+69/5HA712rwpISQskiVglASnlTbyjwlIQZl/fxWWQhPqUeUjewT8F5gIiIiIirJ/IeL5UmS50CeAjYD8qyfz4u87b+emXfTluk54DM/PNKWkTbk2Va7trU328oPt8137LfLtqPvc7Q+m+/Yb4/6jpLn8DvMUbf9OBC+u1hV7F8A8Bz1cV7NMWBn/QtU8xh2eQ7Oc3exJomzc0QFj1/A7d+5cZyHz307cPEV93GJiIjoUDhKS0RERERERERERERERERERERERERERERERERERERE9JjumxRrscFqR2O1o3F7mDdYizXWOsXr+8mjH7rTcDiR0XzD3UP/J8lq7O4B+fPRePu4XvMx35CYayjMRRLzDVW8jhTmGsXruUhiRgacvJyI6Alnswy9d99Fcv06TKuFpHUDSasF07qO7Pb7427eYzGtlrNYYfOcs1gAACFQe/ZZhM1mfzkHef48wmYTwdwc/367kmwCd64D61f7y7WtfPfO49e/fhU48dzj1/MoQgCzS8A7Xy4/1qRZvzbuFkw0ay0+MB9gpbOCdtzGzfgmVuIi347buKP3f5yvdFZKbOl2C9GCs1iTpB23ncU6IU84i/WkevPqm1i+sgwLe+B9BQQuv3QZl5YuldCy/RvEP8z7sLBYvrK8rR4iInpySV/iI7MfOfJ6c5sjyRLo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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwUtaoLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFLWqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBS1qgsAAAAAAAAAAAAAAADw/7NXd6+Wn9UBx9ezzj4nBj0EJjoWzQzSV/TCCklBKNSXC1+KhVyUFguSmt61UMH/wJvSqyr0egZMvTGFQkG8UogIgoXeCEJESj2cCYkDmTkzSfbMnLenNyEkUM4Z45m99jrz+cDDb8N69u/5btj8fgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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emTIrh8RtyZJcmCapm2VKpAkyboR8YuISDKO/CUiflOp/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Bka6msjIqKx3BJpmm82Tf8698FzOkO5ubVdfSMikiSiqaGuU/vCqmaLLbaIJEkizfAiXbp0acydOzf69+/fCc0+3Pjx42O//faL999/P1N+vfXWi9///vex4447FtapVCrFNddcExtssEGce+65mWZGjx4dhx56aNx9993Rq1evwrrByuqRRx6Jvffee7m5T33qU/HII48sN7dgwYK45ZZb4o477ojHH388lixZ8pHZuXPnxty5c2PGjBnx7LPPRkTEZZddFqVSKfbYY4848sgj45hjjonevXtnvp+uYNasWfHAAw/EmDFjYsyYMTFx4sRYtGhRptlSqRSbbbZZ7L777rHHHnvEsGHDYsMNNyy4ceXNnz8/7rjjjrjuuuviySefjLa2to/Mvvvuu/Huu+/Ga6+9FhMmTPjH1/v06RP77rtvHH300fFf//Vf0a1bt86o3ukWLFgQjz76aPzhD3+IP/zhDzFhwoSYOXNm5vmBAwfGbrvtFrvvvnvsv//+sf322xdXtoImTZoUo0aNirFjx0Zzc3O89NJLmV8nHzRgwIDYeOONY/DgwbHlllvGJz7xidhll11WyNcNFKGm2gUAOkuapq8kSXJZRJydcWS/iPhpkiQnplk+yVmOJEnWiIgHImK9HGNfSdP0o39TBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACALqqhvjYiIhrLLZGm+WbT9K9zHzynSOXm1nb1jIhIkoimhrpO6Qmrsl69esUaa6wR7777bqb8nDlzon///gW3+nB/+tOfYtiwYTFr1qxM+a222iruv//+GDx4cLHF/uacc86J2traOP7442Px4sXLzY8cOTL+67/+K377299Gz549O6Eh8K/mzZsXV1xxRVx99dUxffr0Dp3V1tYWjz32WDz22GPxzW9+M84666z4yle+EjU1NRVqW3ltbW0xYsSIuPXWW+O+++6LhQsXtvucSZMmxaRJk+Kmm26KJElijz32iCOPPDI+//nPR9++fSvcvLIWLlwYV199dVxyySWZfx5+lHnz5sXdd98dd999d2y22WbR2NgYJ5xwQpRKpQq1rZ40TeO+++6L22+/Pe66666YPXt2u8+aPn16jBgxIkaMGBGNjY2x/fbbx1FHHRUnnXRSrLHGGhVs3XHTpk2L66+/Pm6//faYOHFiRc58//3345lnnolnnnnmn76+/vrrxy677BL7779/HHbYYbHOOutUZB+saFb8d0yAfC6MiDdy5I+PiJuSJOnVkaVJkgyOiNERUZdjrJym6UMd2QsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANXUUF8bTQ11kST5Z9M0orHcEuXm1soX+4Byc2s0llsiTfPPJklEU0NdNNTXVr4Y8G/69OmTOZu250VdAX/+859j6NCh8d5772XK77rrrvGHP/whBg8eXGyxf3HMMcfE7373u+jXr1+m/H333RcNDQ2xaNGigpsB/+rBBx+M7bffPs4777yYPn16Rc+ePn16/M///E/svPPO8ec//7miZ1fCkiVL4sYbb4xtttkmhg8fHiNGjIiFCxdW7Pw0TePxxx+PU045JQYPHhwXXXRRvP/++xU7v5JGjRoV2267bXz961+Pd999t6Jnv/zyy3HyySfHbrvtFhMnTqzo2Z1p8eLFceONN8a2224bBx10UPz85z+P2bNnV3THs88+G2effXZsvPHG8Y1vfCNmzpxZ0fPbY8qUKXHiiSfGhhtuGOedd16n/BtOnTo1fvvb38ZJJ50U66+/fuy7777x05/+NObMmVP4buhKStUuABQjSZK9kiRJO/qIiBtzrL2gEjuTJPliQU9LpGk6LyJOiYg8n7gcExF/TJLkP/PuS/7q6IiYEBE75Bh9NyLOyLsPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6mob62mhqqIskyT+bphGN5ZYoN7dWvlhElJtbo7HcEmmafzZJIpoa6qKhvrbyxYAPNXv27MzZfv36Fdjkw02cODH23XffeOeddzLlDznkkBg1alSstdZaBTf7cPvtt1888sgjse6662bK33PPPfHf//3fsXjx4oKbARERS5cuja9+9aux3377xSuvvFLorpaWlthtt93it7/9baF78hg3blz853/+Zxx33HHx4osvFr7v7bffjvPOOy+22Wab+M1vflP4vqyWLl0a5557bgwbNiwmT55c6K4nn3wydtppp7j55psL3VOEkSNHxnbbbRfHHXdcPP/884Xvmz17dnz/+9+PrbfeOu64447C932YNE3jqquuii233DKuu+66qv18Xrp0aYwaNSpOPvnkGD9+fFU6QLWUql0AoLOlaXpvRFyWc6wuIp5MkuTXSZIMTZJkme+fSZL0T5LkixHRHBG3RsQaeSpGxOfTNC3m02QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOhkDfW10dRQF0mSfzZNIxrLLVFubq1op3JzazSWWyJN888mSURTQ1001NdWtBPw0RYvXhzvv/9+pmy3bt2iX79+BTf6Z3/5y19iyJAhMWPGjEz5k046Ke68887o3bt3wc2Wrb6+PsaOHRtbbLFFpvyIESPiyCOPjCVLlhTcDFZts2bNioMOOiiuvvrqTts5d+7caGhoiDvuuKPTdn6Ytra2OPfcc2OXXXaJp59+utP3v/nmm9HQ0BDDhw+P2bNnd/r+D5o/f34cdthhcfHFF0dbW1un7Fy0aFF88YtfjAsvvLBT9nXUrFmz4sgjj4xhw4bFpEmTOn3/tGnT4ogjjogjjzwy5s2b12l7Z82aFQcccECcfvrpnboX+Gc11S4AUCVnR8QuEbFHjpkkIhr+9ngvSZLxEfFsRLwXEfMjYkBEDIyIHSOiLiJ6trPbJWma/r6dswAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0CU11NdGRERjuSXSNN9smv517oPndES5ubVdPSIikiSiqaGuIj2A7CZOnBhpxhft4MGDo1QqFdzo/7z44osxZMiQmDZtWqb8d77znTj//PMLbpXdpptuGmPHjo2DDz44nnzyyeXmy+VydOvWLX7xi19Et27dOqEhrFpmz54dQ4cOjXHjxnX67ra2tjjmmGNi7bXXjn333bfT98+aNSuOOOKIuO+++zp997+688474/nnn48RI0bEFlts0en758yZEwcddFA89thjnb47IuL888+PJEni3HPPrcr+LJ555pkYPnx4TJo0qdpV4vbbb4/nnnsufve738WGG25Y6K4ZM2bE3nvvHRMnTix0D7B8nfcXB0AXkqbpkog4NCL+3M4j1oiIoRFxRkR8JyKaIuL8iDgpIj4eET3bee5NEdF1f3sFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAOaKivjaaGukiS/LNpGtFYbolyc2uHOpSbW6Ox3BJpmn82SSKaGuqiob62Qx2A/MaPH585u+WWWxbY5J+9/PLLsc8++8TUqVOXm62pqYkbbrghzj///E5ols/aa68do0ePjoMPPjhT/pe//GV84QtfiLa2toKbwaplwYIFccghh8S4ceOq1mHx4sVx1FFHxVtvvdWpe99999341Kc+Fffdd1+n7l2W5557Lnbbbbd45plnOnXvkiVL4vDDD4/HHnusU/f+q/PPPz/uuOOOqnb4KPfff3/ssssuMWnSpGpX+YeWlpbYa6+94o033ihsx5w5c2L//fePiRMnFrYDyK6m2gUAqiVN03eTJNk3Ih6JiG2rXCci4o6I+FKatucjXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWDE01NdGRERjuSXSNN9smv517oPn5FFubm3X3oiIJIloaqhr116g4+6+++7M2Y9//OMFNvk/r7zySuy9994xZcqU5Wb79u0bv/71r+OAAw7ohGbt06dPnxgxYkScfPLJcf311y83/4tf/CJqamrihhtuiFKp1AkNYeV3/PHHxyOPPJIpO2DAgNhpp51is802i0GDBkXfvn2jW7duMXfu3JgyZUq88MILMW7cuJg/f37uHtOnT4+TTz45RowYkXu2PWbOnBlDhw6NlpaWTtmXx9tvvx1DhgyJhx9+OLbbbrtO2fn//t//i/vvv7/d8+utt17suOOOsdVWW8Waa64Zffr0iXnz5sXMmTPjxRdfjKeffjpaW1uXe06apnHsscfGxz72sXZ3KcLdd98dhx9+eCxatKjaVf7N5MmTY6+99oqxY8fGuuuuW/HzTzvttJgwYULFzwXap6baBQCqKU3TGUmSfDIifhkR+1axSlNEnJ2maVsVOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQKdoqK+NiIjGckukab7ZNP3r3AfPyaLc3NqufRERSRLR1FCXax9QObNmzYoHH3wwc36vvfYqrszfvPbaa7H33nvHG2+8sdzswIED45577on//M//LLxXR3Xr1i2uu+662GCDDeLb3/72cvM333xz1NTUxHXXXRdJknRCQzpq4cKFMWHChBg3blw8/fTT8corr8Srr74as2bNirlz50ZbW1v07t07evfuHf37948NNtggamtrY/DgwVFXVxf19fWx6aab+vcuwPXXXx+/+MUvlplZf/314/Of/3x89rOfjR133DFKpdIy84sWLYr77rsvrrnmmhg5cmSuPnfddVeMGjUqhgwZkmsur6VLl8bw4cNjwoQJ7Zpfd911Y//994+99947tt122xg8eHD0798/unXrFrNnz4633nor/vKXv8Qf/vCH+P3vfx8vvPBC7h0zZsyIAw44IJqbm2OdddZpV8+sbr311rjuuutyz6255ppx3HHHxdFHHx11dXXLzU+cODFuv/32uP7662PatGkfmVuwYEEce+yxceKJJ+buVIQHH3wwGhoaYvHixe2a32GHHeJTn/pU7LzzzrH55pvHRhttFAMGDIjevXvH4sWLY/bs2fHaa6/F888/H2PGjIl77rknpkyZkmvH5MmTo6GhIUaPHh3du3dvV88Pc//998fNN9/crtmtttoqhgwZEltvvXVsttlmsemmm0b//v2jb9++0bdv30iSJBYuXBjz5s2Lt99+O2bMmBGvvPJKTJo0KZ577rkYN25ctLa2VuxeYGVRU+0CANWWpum7SZLsHxHfi4gzI6Iz/1KcExHHp2n6y07cCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVddQXxsREY3llkjTfLNp+te5D56zLOXm1nbtiYhIkoimhrpMe4BiXHvttbFw4cJM2dVXXz123XXXQvu0trbGPvvsE6+99tpys5tttlk88MADsdlmmxXaqdK+9a1vRW1tbZx88smxdOnSZWZ/9rOfRU1NTfzkJz+JJEk6qSF5Pf7443HIIYfE6NGjY+7cucvMzp49O2bPnh3Tp0+Pl19++d+ur7XWWrHffvvFQQcdFAceeGCsvvrqBbVedbz66qvxla985SOvr7XWWvHd7343jjvuuOjZs2fmc3v06BGHHnpoHHroofHggw/G8ccfH2+88Ubm+XPOOSeefPLJzPn2OOecc2L06NG553bcccc4++yz47DDDouampoPzay55pqx5pprxrbbbhvDhw+Pyy+/PMaMGRNNTU1x991359r3xhtvxOc+97l48MEHo1u3brn7ZjF58uQ49dRTc8107949zjjjjDjvvPOif//+mee22267uPDCC+O8886LSy+9NC655JKYP3/+h2afeuqpzD+Hi/TCCy/Ef//3f8fixYtzzQ0aNChOOumkOPbYY2PDDTf8yFy3bt2iV69esc4668TOO+8cRx99dKRpGqNGjYrvfe97ub5Px4wZE2eccUb86Ec/ytX1o6RpGmeddVaumXXWWSe++tWvxtFHHx0bb7zxcvM1NTXRt2/fWGeddWKbbbaJPffc85+uT506NUaNGhUPPfRQ3HPPPfHOO+/k6gMro1K1CwB0BWmaLk3T9OsRsVtETOiktb+OiK3TNP1lJ+0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAupaG+Npoa6iJJ8s+maURjuSXKza3LzJWbW6Ox3BJpmn9HkkQ0NdRFQ31t/mGgIhYtWhRXX3115vzhhx8ePXv2LLBRRG1tbbz88suRpulyHy+99FJsttlmhfYpyvHHHx9LlizJdJ//+7//G0l73szpNKNHj47f/e53MXfu3A6f9c4778Rtt90WRx11VAwaNCi++MUvxhNPPFGBlquu1157LebPn/+h1w499NB4/vnn45RTTunQ+9uwYcNi3LhxsdNOO2Weeeqpp2Ls2LHt3rk8I0eOjEsvvTTXTJ8+feJ///d/Y/z48XH44YdHTU1Nrvk99tgj7rrrrhg5cmTU1ub7HW/06NFx8cUX55rJ4+STT47Zs2dnzm+00Ubx+OOPx/e///3o379/u3b26tUrvvnNb8ZTTz0VW2211UfmWlpa2nV+pcyePTs+/elPx8yZMzPP9OvXL5qamuLll1+Ob37zm7Hhhhvm3pskSey7774xatSoGDFiRAwaNCjz7DXXXBMPP/xw7p0fZvTo0fHnP/85c/7rX/96vPbaa3HuuefGxhtvXJEO66+/fhx99NFx0003xVtvvRUPPvhgHHnkkYX/3gVdWanaBQC6kjRN/xgR/xkRx0XEM0WsiIj7I2LvNE0/m6bplAJ2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADACqOhvjaaGuoiSfLPpmlEY7klys2tH3q93NwajeWWSNP8ZydJRFNDXTTU1+YfBirmyiuvjNbWD3+Nf5hjjz22wDbAv5o/f37cfPPNsdtuu8WQIUPiySefrHallcrZZ58dv/3tb2PttdeuyHnrrrtuPPDAA7HZZptlnvnpT39akd3/av78+XHKKafkmtl0001j/PjxcdJJJ0WpVOrQ/n333Teefvrp2HvvvXPNXXTRRfHiiy92aPeHufvuu2PkyJGZ81tvvXU88cQT8YlPfKIi+7fffvt44oknYuedd67IeZXW2NgYkyZNypzfbbfd4plnnokzzzwzevXqVZEOhx56aEyYMCF23333zDMnnnhiLFiwoMO7b7755ky5UqkUv/71r+P73/9+9O7du8N7P0pNTU0MHTo0fvGLX8SUKVPi4osvjoEDBxa2D7qqjv0kArqsNE0fSdM0WUEfN1X5uWtL0/TGNE0/FhFDIuLmiJjWwWOfj4jLImKbNE0PSNP0kQ6eBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK42G+tpoaqiLJMk/m6YRjeWWKDe3/tPXy82t0VhuiTTNf2aSRDQ11EVDfW3+YaBipk2bFhdddFHm/J577hm77rprgY2AZRk9enTssssucdRRR8U777xT7TorvHPPPTcuvvjiSNrzC9IyrL322nHbbbdFt27dMuXvuuuuWLRoUUU7RERcfPHF8fLLL2fOb7XVVvH444/HNttsU7EOa621Vvz+97+P/fffP/PMwoUL45RTTqlYh4iIpUuXxplnnpk5X1tbGw8//HAMGjSooj3WWGONeOihhyr6HFfC6NGj49prr82cP/LII2P06NExePDgindZd911Y+TIkTFkyJBM+Zdeeil+/OMfd3jvgw8+mCl3wQUXRENDQ4f35bHWWmvF2WefHa+99lrsuOOOnbobqq1U7QIAXVmapqPTNP1iRKwfETtHxJcj4scR8UhEvBQR0yJiXkS0RcTsiHgzIv4SEfdGxA8i4tiI2CRN023SND0zTdMXOvseAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgRdBQXxtNDXWRJPln0zSisdwS5ebWiIgoN7dGY7kl0jT/WUkS0dRQFw31tfmHgYo6+eST4/3338+cP//88wtsA2R12223xXbbbRf33ntvtaussA4//PC48MILCzv/4x//eBx77LGZsrNmzYrRo0dXdP8777wTV155Zeb82muvHffdd18MGjSooj0iInr16hXlcjl22GGHzDOjR4+Ohx9+uGId7rzzzpg0aVKmbI8ePWLEiBGx3nrrVWz/B6222mpx9913x2qrrVbI+Xm1tbXFaaedFmnGX+yPPPLIuPXWW6Nnz56Fderdu3eMGDEitt9++0z5Sy+9NObNm9fufS+99FJMmzZtubna2to499xz272no3r16tVlvm+gs9RUuwDAiiD9629yzX97AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwkrvliVfj1ideq3aNTnfdMTvH4LX7Fr7n1bfnxgm3jP/QawP79YxpsxfmPjNNI878dUucP+LZmL94abu7DezXM3766Mvx00dfbvcZH+Xzu24cx+w6uOLnfpjjbx4Xr70zr1N2VUpnPj90fTfffHOMGDEic/7AAw+Mfffdt7hCQC7Tpk2LT3/60/G9730vzjrrrGrXWaFssMEGcf311xe+59xzz40bbrgh2tralpt99NFHY//996/Y7iuvvDLmzJmTKZskSdx+++2xySabVGz/v+rbt2+MGDEiPvaxj8X777+faea73/1u7L333hXZ/4Mf/CBz9oILLoj6+vqK7P0om2++eVx22WVx/PHHF7oni1tvvTX+8pe/ZMruuuuucdNNN0WpVCq4VUS/fv3izjvvjLq6upg/f/4ys9OmTYsbb7wxTj311Hbtev755zPlvvCFL0S3bt3atQNon5pqFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICu5p05i2LS9DnVrtHpFi1t67Q9RT2/8xcv7dD8tNkLY9rshRVq88/embOokHM/zGvvzFvhvoc78/mha3vppZfiK1/5SuZ8z54946qrriqwEdAeaZrGN77xjXjppZfi2muvjSRJql1phXDllVfGgAEDCt8zePDgGDp0aDzwwAPLzT7++OMV27tw4cK45pprMudPPvnk2HfffSu2/6NsvPHGcdlll8UJJ5yQKf/www/HhAkTYqeddurQ3gkTJsRTTz2VKbvNNtvE17/+9Q7ty+pLX/pS3HzzzRX9t89ryZIl8e1vfztTtn///vHLX/4yunfvXnCr/7PFFlvEd77znWhsbFxu9vrrr49TTz21XXtef/31TLldd921XecD7VeqdgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIiIefPmxX/913/F+++/n3nmnHPOic0337zAVkBHXH/99XHqqadWu8YKYYcddojhw4d32r6su1paWiJN04rsvOuuu+K9997LlF199dXjoosuqsjeLL70pS9FfX195vxNN93U4Z233XZb5ux3vvOdqKmp6fDOrC6++OJO2/Vh7r333njllVcyZS+66KLYcMMNC27077785S9n2vv000/HhAkT2rVj9uzZmXK1tbXtOh9ov1K1CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAREScdNJJ8cwzz2TOf/zjH49zzjmnwEaw4uvdu3fstNNO8fnPfz4uueSS+N3vfhdPPfVUPP/88zF16tSYO3duLFmyJGbPnh1vvfVWTJgwIe6666747ne/G4cddlisscYaHe7wk5/8JM4///wK3M3K7YwzzogkSTpt39ChQzPl5syZE62trRXZefPNN2fOfv3rX6/I919WSZLE9773vcz522+/PRYvXtzufWmaxi9/+ctM2c033zyGDx/e7l3tsccee8Qee+zRqTs/6Nprr82UGzx4cJxyyikFt/lwPXv2jNNPPz1T9re//W27dixatChTrqampl3nA+3nVQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVN0ll1wSP//5zzPn+/TpE7feemvU1NQU2ApWPKVSKXbdddc4+OCDY++9946dd945unXrtty5fv36Rb9+/WLdddeNHXfcMQ455JCIiFi6dGk88cQTceONN8Yvf/nLmDt3brt6XXTRRfGJT3wiDj744HbNr+z69+8fDQ0Nnbpz8ODBMXDgwJg+ffpysy+88EJsuOGGHdo3Z86cGDlyZKZs796946STTurQvvYYOnRobL/99vHss88uN/v222/Ho48+Gvvuu2+7drW0tERra2um7EknnRRJkrRrT0eccsopMWbMmE7f++abb8b999+fKXvmmWdW9XeBL3zhC/GNb3wjFi9evMzc/fffH9/97ndzn9+rV69MuTfeeCO222673OcD7VeqdgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYNVWLpfjnHPOyTXzox/9KLbccsuCGsGKp76+Pn74wx/G1KlTY8yYMfGNb3wjPvGJT0S3bt06dG63bt1ijz32iJ/97Gfx2muvxVlnnRW9e/fOfU6apnHMMcfElClTOtRnZTVkyJDo06dPp+/ddtttM+XefPPNDu965JFHYvHixZmyn/3sZ2PNNdfs8M72OOWUUzJnR44c2e49Dz/8cKZckiRx5JFHtntPRxx22GFV+b685557oq2tbbm5Xr16xVFHHdUJjT7aWmutFbvvvvtycxMmTIh33nkn9/lrr712ptzvf//73GcDHVOqdgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYNX15JNPxjHHHBNpmmaeOeGEE+LYY48tsBWsGHr37h3HHntsPP300zF+/Pg47bTTYuDAgYXtW2utteKSSy6JlpaW2GOPPXLPv/fee/G1r32tgGYrvmHDhlVl7xZbbJEpN3369A7vGjlyZObs4Ycf3uF97dXQ0BClUilTNs89/auHH344U27nnXeOQYMGtXtPR/Tu3Tv222+/Tt/7+9//PlNu//33j9VXX73YMhkMHTp0uZm2trYYP3587rM32WSTTLlbb7013nrrrdznA+2X7ScFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECFvfDCC3HwwQfH/PnzM8/U19fHD3/4wwJbwYrjrLPOihtuuCHq6uo6de8WW2wRDz/8cHzlK1/JPfurX/0qHn744QJardjq6+ursnfgwIGZcm+//XaHd40dOzZTrm/fvrHvvvt2eF97DRw4MHbfffdM2ZaWlpg7d2679owfPz5TrprPRUTEsGHDOnXfkiVLYtSoUZmy+++/f8Ftssn6+n366adzn11XVxdJkiw3N3PmzDjmmGNiwYIFuXcA7VOqdgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYNXz+uuvx9ChQ+Ptt9/OPLPRRhvFXXfdFT179iywGZBFTU1NXHXVVXHRRRflnv3Wt75V+UIruO23374qe9dee+1Mufnz53doz9KlS2PixImZsrvsskvV3+f32muvTLm2trZ49tlnc5//zjvvxNSpUzNld9ttt9znV9Kuu+7aqfuee+65mDNnTqbsnnvuWXCbbLbddttMuT//+c+5z15jjTXiYx/7WKbsyJEjY+jQofHGG2/k3gPkV6p2AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABg1fLWW2/FkCFD4o033sg8M3DgwBg5cmRssMEGBTYD8jrnnHOisbEx18xjjz0WTz31VEGNVjxrrbVW9OnTpyq7e/XqlSm3cOHCDu2ZNGlSzJ8/P1N2991379CuSsjToaWlJff5EydOzJzdeeedc59fSdtvv3307Nmz0/ZNmDAhU65v376x1VZbFdwmm/XXXz9KpdJyc6+99lq7zj/88MMzZ8eMGRNbb711/M///E+79wHZLP9VDwB0WJIkpyZJMrGjj4joW+17AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6Ii333479t1333jppZcyz6yxxhrx4IMPxpZbbllgM6C9vve978U+++yTa+aaa64pqM2KZ/3116/a7p49e2bKLVy4sEN7nn/++czZj33sYx3aVQl1dXWZs3nu7e8mT56cKbfaaqvFeuutl/v8SurWrVtsvvnmnbbvT3/6U6bclltuGaVSqeA22dTU1MRqq6223NyUKVPadf7xxx8fPXr0yJyfN29eXH755bHpppvG0KFD4/rrr48ZM2a0azfw0brGOxAArPzWiYhtK/DwsxsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhhzZw5M4YNGxYTJ07MPNO/f/+47777oq6ursBmQEd069Ytrr/++ujdu3fmmbvuuisWLVpUYKsVR58+faq2O0mSTLk0TTu0Z8qUKZmzW2+9dYd2VcJ6660Xq6++eqZsnnv7u6lTp2bKbb755rnPLsKWW27ZabtefvnlTLmNN9644Cb5ZHn/e/PNN9t19rrrrhunnXZa7rm2trZ46KGH4oQTToh11103Pv7xj8c555wTI0eOjDlz5rSrC/B/StUuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACs/GbPnh37779//OlPf8o806dPn7jnnnviE5/4RIHNgErYZJNN4mtf+1rm/KxZs2LkyJEFNlpx9OrVq9oVCvfmm29mzm666aYFNslus802y5TLc29/N3Xq1Ey59ddfP/fZRVhvvfU6bVdra2um3IgRIyJJki7zyPJ9sGjRoliwYEG7npdvfetbmb8nP0yapjFu3Lj43ve+F8OGDYvVV189dtxxxzj11FPj5z//eUyePLndZ8OqqlTtAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAym3u3Llx4IEHxpNPPpl5pmfPnjFixIjYc889C2wGVNLpp58effr0yZwfPXp0gW1WHEmSVLtC4d56661MuX79+kXv3r0LbpPNuuuumyk3derU3Ge//fbbmXLrrLNO7rOLMHDgwE7b1dra2mm7qmH+/Pntmuvfv3+Uy+UYMGBARXosXbo0nn766fjxj38cn//852OzzTaL9dZb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N29eoXuWZ7fddsv8vfL888/HV7/61YIbMWfOnJgyZUqm7MYbb1xwG6i+UrULAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACu+cnNrNJZbIk3zzyZJRFNDXTTU11a+WDs01NdGU0NdJEn+2TSNaCy3RLm5tfLFoBN9//vfjwsuuCDXzLBhw+LOO++MHj16FNQKiIh46623ql3hn1x66aVxySWX5JrZaaedYujQoQU1oqs799xzM2efffbZOOusswps81e33HJL/OpXv8qcP+2002K11VaryO6vfvWr0b1790zZP//5z3HqqadWZO9HOe+88+Lhhx8udEdWl112WebsddddF5deemmBbapjyZIl1a7wD7fffnvmPtttt13BbaD6StUuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKzYys2t0VhuiTTNP5skEU0NddFQX1v5Yh3QUF8bTQ11kST5Z9M0orHcEuXm1soXg05wxRVXxDe+8Y1cM0OGDIkRI0ZEz549C2oF/N0OO+wQX/7yl+PNN9+sao+lS5dGY2NjnHXWWblnzzvvvAIasaI46KCDYqeddsqcv/LKK+OGG24orM/YsWPjxBNPzJzv27dvnHHGGRXbv8EGG8Qpp5ySOX/99dfHRRddVLH9H/TTn/40Lr744kLObo9dd901Pve5z2XOn3XWWXHJJZcU2CifNE3jrrvuyvXv+6922mmn+OEPfxgLFiyoYLP85s2bF5dffnmm7ODBg2PjjTcuuBFUX6naBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAVV7m5NRrLLZGm+WeTJKKpoS4a6msrX6wCGupro6mhLpIk/2yaRjSWW6Lc3Fr5YlCga665Jr72ta/lmtlrr73i7rvvjt69exfUCvigBQsWxI9+9KPYZJNN4gtf+EJMmDCh0ztMnjw59t133/jBD36Qe3a//faLww47rIBWrEguv/zy/8+OncdbVdf743+tAyKzE844C85CYkqmoiCill77imZYlmXKpSy9ZabNg5qat2zALLX0V1RqXVLU600ZFKdAxFlBBWccUUYZDuv3B1BoDPsc9j4b9Pl8PNZjr73W+/15v9ZmncM+q0n1p5xySq666qqq57jzzjtz+OGHZ968eRX3fOtb30qXLl2qmuO73/1uNtpoo4rrv/nNb+brX/96Fi1aVLUMF154YQYPHly19arlpz/9aTbZZJOK688+++x85jOfyaxZs2qYauXmzJmTyy+/PHvuuWeOPvrojBs3rtlrPfvss/nSl76UbbfdNt/97nfz0ksvVTFp5YYMGZLHH3+8otqPfOQjNU4Da4aGegcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1k6PvPhWzrzugZRl03uLIrloYI8M7NW1+sGqaGCvrrloYI8URdN7yzI587oH8siLb1U/GNTAb37zm5x22mlN6jnggAMyYsSItG/fvkapgBWZP39+rr766vTq1St77713fvrTn2batGk1nTl9+vR885vfzB577JHRo0c3ub9du3b55S9/Wf1grHX69OmTk046qeL6xsbGnHTSSTnnnHPS2NhYlQy//e1v079//8yYMaPinj322CNf+cpXqjJ/WRtssEHOP//8JvVccMEFGTBgQJ599tnVmj1t2rR87GMfy1lnnbXCmrZt267WjNWx6aab5ne/+12KJnwhv+qqq7LHHnvkpptuqmGyfzd+/Picfvrp2XLLLfP5z38+Dz/8cNXWfvnll/O9730v22yzTY477rjceOONWbhwYdXWX5HZs2fn+OOPz1VXXVVxzymnnFLDRLDmaKh3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDttNsW6+VLfbs1ua8okosG9sjAXl1rkKr6BvbqmosG9khRNL33S327Zbct1qt+KKiBc889N2VZNqnnjjvuSMeOHVMUxRq1feYzn6nNh0Rd/e53v6vK/fG9732v4pknnXRSVWaOHj26dh9Mkvvuuy9nnHFGttxyy+y777753ve+l7Fjx2bu3LmrvfaiRYty55135pRTTsk222yTc889N3PmzGnWWr/+9a+zww47rHYm3ht+/OMfZ6uttqq4vizLnH/++dl3330zduzYZs996qmncvTRR+ezn/1sk35G2rRpkyuvvDKtW7du9uyV+fznP5+jjjqqST233nprdt5555x11ll57rnnmtT78ssv53vf+166d++e4cOHr7CuQ4cOOfPMM5u0drUdfvjh+frXv96knqlTp+YjH/lIDjjggFx//fVpbGyseq7Gxsbceeed+cY3vpHu3bvngx/8YC655JK8+eabVZ+11IIFC3Lttdfmox/9aLbYYosMGTIkN910U1V+3y9r0aJFGTZsWD7wgQ/kz3/+c8V9AwYMyJ577lnVLLCmqs3/BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMD7whn9uydJLrltckX1RZFcNLBHBvbqWstYVbc075nXPZCyrKzny/26/fPzAYCWsGjRovzjH//IP/7xj3z3u99N69ats+eee2b33XfPTjvtlG7dumWzzTbLpptumo022iht27bNuuuum6Io8vbbb2f27Nl58cUX89xzz+Whhx7KhAkTMmrUqLzxxhurne1LX/pSPvnJT1bhKnmv2HDDDXPdddflwAMPzLx58yruu++++3LAAQekT58+OfXUU3P44Ydn/fXXX2nPvHnzMmbMmFxxxRX5n//5nyxYsKDJeX/+859n7733bnJfU1xxxRX5wAc+kOeff77inrlz5+bCCy/MxRdfnD59+uTQQw9Nr1690r1792y44YZp37595s6dm+nTp2fy5Mm5//7783//938ZOXJkRZ/Deeedl86dO6/OZVXFueeemxdeeCFXX311k/rGjh2bsWPHZvPNN8/HPvaxHHHEEdlvv/2ywQYbNDnDK6+8kocffjj33HNP7rnnntxxxx158803m7xOtbz66qu59NJLc+mll6Zdu3bZb7/9sv/+++fDH/5w9txzz2y66aZNWq+xsTH33ntvbrjhhlx33XV58sknm9S/zjrr5Cc/+UmTemBt1rreAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC12xn9uydJLrlt8krriiK5aGCPDOzVtSViVd3S3Gde90DKcuW1X+7X7Z+fCwDUy8KFCzNhwoRMmDChrjlOPPHE/OQnP6lrBtZM++yzTy699NJ89rOfbXLvmDFjMmbMmLRq1So9evTIrrvumm222SadOnVKq1atMmvWrLz00kt5/PHHM378+MyZM6fZOQcPHpxTTjml2f2V6tKlS0aMGJEDDjggM2fObFJvY2NjRo4cmZEjR1YtzxFHHJEvfvGLufrqq6u2ZnMVRZErrrgib731Vv72t781uf+ll17K0KFDM3To0CTJtttum5122ildu3bNZpttlvbt26dt27ZpbGzMvHnzMnfu3Lz++uuZNm1aXnrppUyaNClvvvlmla+qeubOnZvbbrstt9122z+Pbbjhhtlpp52yxRZbZIsttsgGG2yQtm3bZt111828efMya9aszJ49O88//3yeeOKJTJ48OfPmzWt2hvPPPz+77LJLNS4H1gqt6x0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWPud0b97kuSS2yYv93xRJBcN7JGBvbq2ZKyqW5r/zOseSFkuv+bL/br98/MAgPe7z3zmM7niiivS0NBQ7yisoU466aTMnDkzX/7yl5vV39jYmAkTJmTChAlVTrbYiSeemF/+8pc1WXt5evTokeuuuy5HHnlk5s+f32Jzl5fjz3/+8xr1s9u6detcd911GTx4cK644orVWmvq1KmZOnVqdYKtod54443cfffdLTJr0KBB+cpXvtIis2BNseb8dgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWamf0754v9+v2b8eLIrloYI8M7NW1Dqmqb2CvrrloYI8Uxb+f+3K/bjmjf/eWDwUAa5hWrVrlggsuyG9/+9s0NDTUOw5ruC996Uu55JJL1rh75aSTTqrLPXzooYdmxIgR6dixY4vOXWrHHXes6/yVad26dS6//PJ8//vfX+Pul/erY445JldddVW9Y0CL8xsIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqJoz+nfPl/t1++f7okguGtgjA3t1rWOq6hvYq2suGtgjRfGvY1/u1y1n9O9ev1AAsIbYeuutc8stt+RrX/tavaOwFvnSl76UESNGZL311qt3lLRq1SoXX3xxrrzyyjQ0NNQlQ//+/XPbbbdlyy23bNG5++67b+6666507bpmf3//1re+ldGjR2ebbbapd5T3tTPPPDPXXHNNWrduXe8o0OLq878DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8J51Rv/u+XK/bimK5KKBPTKwV9d6R6qJgb265qKBPVIUyZf7dcsZ/bvXOxIA1FXr1q3zX//1X3n00UfTr1+/esdhLXT44YfnvvvuS58+feqWoVu3bhk5cmT+67/+q24Zltpnn30yceLEfPSjH635rKIocuqpp2bkyJHZeOONaz6vGg444IA88MAD+dKXvpR11lmn3nGWq1u3bjnllFPqHaPqtthii1x//fW58MIL09DQUO84UBfufAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKDqzujfPSNO2z8De3Wtd5SaGtira0actn/O6N+93lEAeJ846KCD0q5du3rHeId11lknn/vc5/L444/n4osvTocOHeodibXYDjvskFGjRuU3v/lNNt100xab265du3zjG9/Igw8+mAMPPLDF5q5Kly5dcsMNN+SPf/xjtt1225rM2GmnnTJy5Mj86le/Svv27Wsyo1bWW2+9XHLJJXnkkUcycODANDQ01DtSNthgg3z2s5/NqFGjMmnSpJxyyinNXmvYsGE59dRTs9VWW1UxYfO1a9cuZ555Zh599NEceeSR9Y4DdVX/3zYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAe9JuW6xX7wgt4v1ynQCsGYYPH57p06fn1ltvzVlnnZW99torDQ0Ndcmy00475Yc//GGefvrpXH755dlhhx3qkoP3nqIocvLJJ2fKlCn52c9+lm222aZms9Zbb718/etfzzPPPJMf/vCHadu2bc1mrY7jjz8+jz/+eC699NLsscceVVlzn332ybXXXptHH300Bx10UFXWrJdu3brl2muvzVNPPZUzzzwzXbp0adH5W221VU455ZSMGDEi06ZNyxVXXFGVz/SII47Ir371qzz77LOZOHFizj333Hz4wx/OOuuss/qhm2DzzTfPN7/5zTz11FO58MILs956/gaCoizLemcAACpUFMWMJJ1WdL5Tp06ZMWNGCyYCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgHdqbGzMpEmTKq7v3r17WrVqVcNEAADvfdOnT8+4ceMyYcKE3HfffZkwYUKmTJmSsiyrOmfdddfNfvvtl0MOOSSHHXZY9tprr6quDyuyaNGi3H777Rk2bFhuuOGGTJs2bbXW69y5cw455JB84hOfyEc/+tG0bdu2Sklbzr333psRI0bklltuycSJE7NgwYJV9nTp0iU9e/bMEUcckSOPPDI77rhjCyStj4ULF+b222/P3/72t9x8882ZPHly1dYuiiLbbbddevfunQMOOCAHHnhgdt1116qtX4m3334748ePzz333PPP7YUXXqjqjB133DEDBgzIf/zHf+Tggw9O69atq7r+mub98Dyjc+fOmTlz5spKZpZl2bml8qztimp/0QIAaqco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My+++GImTpz4jvMNDQ3p1atX+vXrl4EDB6ZXr141uoK1z7e//e384Ac/qKh2ww03zMiRI9OjR48ap1ozvPHGGxkzZkxGjx6du+++Ow888EDmz5+/yr65c+dm7ty5mT59ep5//vncd9997zi/zjrrpHfv3unfv3+OO+647LTTTrW6hLp59NFHc9NNN+WWW27JAw88kFdffbWivo033jg9evTIgAEDcsQRR2TXXXetcVIAgDVPUZZlvTOstYqi2LreGd5LyrJ8tt4ZANZ0RVHMSNJpRec7deqUGTNmtGAiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHinxsbGTJo0qeL67t27p1WrVjVMBEA1PProo7nxxhszYsSI3HXXXVm4cGHNZ+666645+eST8/nPfz4dO3as+bw11Q9+8IN8+9vfblJPly5dMmrUqOy+++41SlU/ZVlmwoQJGTFiRG688caMHz8+ZVnWfO4HP/jBnHrqqfnUpz6VNm3a1HxercyaNStXXXVVfv7zn+eJJ56oypo777xzvvjFL+bTn/70+/pnFd7LRo8enYMPPniVdX369Mno0aNrHwhq4P3wPKNz586ZOXPmykpmlmXZuaXyrO2KlvgS+l5VFMWiJD7A6ijLsmxd7xAAa7qiKGYk6bSi8506dcqMGTNaMBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvFNjY2MmTZpUcX337t3TqlWrGiYCoLkeeuihXHPNNbnmmmua9Lu92jbccMOcfvrp+epXv5p27drVLUc9/OhHP8rZZ5/drN5NNtkko0aNyq677lrlVPVx77335pprrsm1116b5557rm45unbtmq9//esZPHjwWvUdZv78+bn44otzwQUX5K233qrJjPXWWy9nnXVWvvKVr6RNmzY1mQHUx+jRo3PwwQevsq5Pnz4ZPXp07QNBDbwfnmd07tw5M2fOXFnJzLIsO7dUnrVdQ70DvAcUtqptAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANTRyy+/nP/+7//OnnvumT333DM//OEPM2nSpLpmeuONN/Ltb387u+22W2688ca6ZmlJF198cc4+++xm97/yyivp169fnnjiiSqmallTp07N97///eywww7p3bt3/vu//zvPPfdcXTM9//zz+eIXv5hevXrl7rvvrmuWSo0cOTJ77LFHzjnnnLz11ls1m/PWW2/lnHPOyZ577plRo0bVbA4AwJqgod4B3gNK22pvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANTZ3//+93Tt2jVf+cpX8tBDD9U7zr+ZMmVKPvrRj+a0007L/Pnz6x2npi655JJ89atfXe11pk2blr59+2by5MlVSNWyrrzyymy//fb5zne+k6effrrecf7NAw88kAMOOCDnnntuyrKsd5zlKssy5513Xvr3759Jkya12NwnnngihxxySM4///wWmwkA0NIa6h3gPaKwNXsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgveqlB+udoGW8X66T97y33norCxcurHeMVfrFL36RAw88MK+//nq9o9TE0KFDc/rpp1dtvRdffDF9+/bN008/XbU1W8Ibb7yRsizrHWOlGhsb881vfjNHHXVU5s6dW+847zB//vwcd9xx+cY3vpFFixa1+PxFixblnHPOybHHHpv58+e3+HwAgFprqHcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D1o1PnJZQcmE4fVO0ltTRy2+DpHnV/vJPC+cu+99+bAAw/MCy+8UO8oVfXrX/86X/ziF6u+7vPPP5+DDz44U6dOrfraJCNGjMiAAQMyY8aMekdJkixYsCDHHntsrrvuunpHyXXXXZfjjjsuCxcurHcUAICqaqh3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOA9ZtT5yZgfJSmT4UOSicPqnag2Jg5bfH0pF1/vqPPrnQjeVx599NEMGDAgb731Vr2jVMWVV16ZwYMHpyzLmqz/7LPP5uCDD86zzz5bk/Xf7+64444cffTRWbBgQV1zLFq0KCeccEKuv/76uuZY1t/+9reccMIJNbu3AQDqoXW9AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvIaPOT8b8aJkDZTJ8yOLdnoPqEqkmJg5bcl3lv44tve6Dz65LJKinoiiyww47ZO+9985ee+2V7bffPttuu2222GKLdOjQIR06dMjChQsze/bsvPjii3nqqacyYcKE3HbbbbnnnnvS2NjYrLmPPPJIjjnmmNxyyy1p1apVla+q5Vx99dX5/Oc/n7IsV128jE022SSvvPJKxfVTp05N3759M2bMmGy55ZZNjbnWaGhoyM4775y99947H/jAB7Lddttl2223zaabbpoOHTqkffv2WbBgQWbNmpXnn38+kydPzvjx43Prrbfm/vvvb/K/w1KjRo3KKaeckt/+9rdVvqLKnXvuubn22mub3Ne6desMGDAghx9+ePbee+9svfXW2WCDDVKWZaZPn56pU6fmvvvuy4033phbb721yT+z11xzTfbYY49885vfbHI2AIA1UdHcL40kRVEsyjueqNQnRhXWWNk11Hr9pTPKsizX3r+GAVpIURQzknRa0flOnTplxowZLZgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6psbExkyZNqri+e/fuadWqVQ0T0aJGnZ+M+dEKThbJ0UOTnoNaNFJNTByWDB+SpFz++T5fTw4+u0UjQTVcd911OfbYYyuu79KlSw4//PAMGDAghx56aDbeeONmzX355Zdz5ZVX5qc//WleeeWVZq3xox/9KGeddVazeutt2LBh+dSnPpVFixZV3FMURS6++OKcdNJJOfroozNmzJgmzezWrVvGjBmTzTffvKlxW8yPf/zjnHnmmRXXd+3aNUcccUQGDBiQfv36Zb311mvW3ClTpuTXv/51fvnLX2bmzJnNWuNPf/pTPv7xjzerd3WMGjUqhxxySJPupTZt2mTw4ME555xzsummm1bU89JLL+Xcc8/Nr3/96yxYsKDiWa1atcqtt96agw46qOIeYM0wevToHHzwwaus69OnT0aPHl37QFAD74fnGZ07d17V95uZZVl2bqk8a7uGegeg2YolW1OUK9ia07OqvtXNCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwNpk1PnJmB+tpKBMhg9JJg5rsUg1MXHY4utIueKaMT9a/HnAe1DHjh1z4okn5qabbspLL72Uq6++OieccEI23njjZq+56aab5uyzz87TTz+ds88+O61bt27yGt/5znfy+OOPNztDvVxzzTU58cQTs2jRoop72rRpkz/+8Y8544wzsv766+eWW27Jcccd16S5kydPTt++ffPyyy83NfIaZaONNsp//ud/5vbbb8+zzz6byy67LP/v//2/rLfees1ec7vttsv555+fKVOm5POf/3yz1vjC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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACANVfPQYtfhw9JUjaxuVzSt8w6LWnisGbmTpIiOXpofXLD+8ABBxxQce3UqVOzaNGiNDQ01DDRqt177705/PDDM2vWrIrqO3XqlL/85S/p379/1bO0bds2f/nLX3Laaadl6NChFfWMGTMmRx55ZEaMGJF27dpVPdPa7IADDshFF11UUe3TTz9dkwxPPvlkxo0bV1Ht5ptvnkMOOaQmOZZnwIAB2WSTTfLKK6+ssvbee+/NU089lR122KEFkr23zJ49O7fddlvuv//+PPzww3niiScyffr0zJgxI7Nnz866666b9u3bp0uXLtluu+3SrVu39O7dO/vvv3+22mqresevmrIsM23atEyZMiXTpk3LnDlzMnv27CxYsCDt27dPhw4dst5662WbbbbJdtttl7Zt29Y7clXNnDkzt912W+6555489thjmTRpUqZPn56ZM2dm/vz56dixYzp37pwNNtgg3bt3z6677poePXqkX79+6dy5c73j18WsWbMyZcqUPPvss5k5c2bmzJmTOXPmZJ111kmHDh3SoUOHdO3aNdtvv3022mijesetirIs8/zzz+fFF1/Mq6++mjfeeCPz5s3LvHnz0tDQkPbt2/9za9eu3T9/ZjbeeON6R4c1Wut6B2ClvpOkbRY/4SmWHFu6Xya5Z0nNGqssyylFUfxnkj/m359ULb2WIUVR/LgsyxdaPCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADV13PQ4tfhQ5KUTWwul/Qts05LmDismXmTpEiOHtqyeeF9plu3bimKImW56p/RxsbGzJ49O506dWqBZMs3fvz4DBgwIDNmzKiofrPNNstNN92UD3zgAzXL1NDQkF/+8pfZcsst841vfKOinpEjR+Y//uM/cv3116dt27Y1y7a22WmnnSqufeutt2qS4aabbqq49uMf/3gaGhpqkmN5WrVqlY9//OP5+c9/XlH9TTfdlNNOO63Gqepj6tSp2W677VZZt80222Tq1KmrrGtsbMy1116b3//+97ntttvy9ttvr7B2zpw5mTNnTl577bU8/vjjufnmm/Ozn/0sSdKrV68cf/zxOfnkk7P++utXejlrhDlz5uTWW2/N2LFjM3bs2EycODFz586tqLcoimy99db50Ic+lP333z/9+/dP9+7da5y4+hYuXJjhw4fnsssuy5gxY7JgwYIV1r755pt588038+yzz+aBBx745/F11lknffr0yfHHH59PfvKTWXfddVsieotbuHBh7rzzzowdOzZ33nlnxo8fn1dffbXi/vXXXz+9e/f+5/2yzz771DBt9Tz//PP5+9//nrvuuivjxo3LpEmTKv45WVb79u2zzTbbZNttt82OO+6YffbZJ717986OO+5Yg9Sw9ikq+eOEllcUxdZJnkzSaumh/OtpT5FkUZJ9y7K8rw7xmqwoijFJDsjiayiWHF66Xyb5SVmWX61TPICaK4riu0m+U+s5nTp1qvhBHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUQmNjYyZNmlRxfffu3dOqVasaJqKuJg5Lhg9JUjajuUiOHpr0HFTtVP9ubckJ73MbbbRR3njjjYpqX3zxxWy++eY1TrR8999/f/r165fp06dXVL/TTjvlf//3f7PtttvWNtgyrr766px88slZsGBBRfWHH354/ud//ifrrrtujZOtHWbOnJnOnTtXVNumTZvMmzev6hmOPPLIjBgxoqLaUaNG5aCDDqp6hpW59dZb079//4pqjzzyyFx//fU1TlQfU6dOzXbbbbfKum222SZTp05d4fmFCxfmsssuy49//OOV1jVV586dc9ppp+Wcc85J+/btq7ZuLfz973/PVVddlb/97W+ZNWtW1db9wAc+kE984hP53Oc+lw033LBq69bCokWL8tvf/jbf+c538sILL1Rt3c022yynn356Tj/99BX+nh89enQOPvjgVa7Vp0+fjB49umrZmuuOO+7IH/7wh/zlL3/Ja6+9VrV1t99++3ziE5/IkCFDssUWW1Rt3Wp46623ctVVV+X3v/99xo8fn7Jszt82ldloo42y7777pn///jnmmGOy1VZb1WxWS3o/PM/o3LlzZs6cubKSmWVZVvYlhzTUOwAr9J9JWi/ZL5Y5XmTxk5+/l2V5X4unar7zVnC8zOJr+nxRFG1aMA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC11nNQcvTQJEUzmstk+JBk4rBqp3qnicMWz0nZjOZi8fX1HFTtVMBytG/fvuLasmzOz/Tqe/DBB9O/f/9Mnz69ovoPfehDufPOO7PtttvWNti7nHjiibnhhhvS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7kkebbFEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtKyegxa/Dh+SpGxic7mkb5l1mmLisGbOTZIiOXpo8+YCq+3666+vuHafffapYZJ/mTJlSg4++OC88MILq6zt0KFDrr322hx++OEtkKx52rdvn+HDh2fw4MG5/PLLV1n/hz/8Ia1bt86VV16ZhoaGFki45qjn/bhw4cI89thjFdV26tQpW265ZVXnN0XXrl3TsWPHzJo1a5W1jz76aBYuXJjWrVu3QLI117e+9a0MGzasotp27dplr732yg477JCtttoqHTp0SJs2bTJnzpxMmzYtkydPzr333psZM2Y0OcfcuXNz4oknZty4cS3y8z1v3rx87GMfy9///veaz2qquXPn5sgjj8xNN92UPn36tMjM8847r6Lfwyuy4YYbZq+99srOO++cLl26pGPHjnn77bfz1ltv5cknn8yDDz6Yp556qqK1zj777PTq1WuN+tm89957c9hhh+XNN9+sd5R/8/rrr6dv37654447sssuu1R9/R/84Ae5+eabq74u0Dxrzm9GlrVNVv7UZ2ZLBamySnJvneTRWgcBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgjnoOWvw6fEiSsonN5ZK+ZdapxMRhzZyXJEVy9NCmzQOq5q233sr//d//VVx/0EEH1S7MEs8880wOPvjgPPfcc6us3WSTTTJixIh88IMfrHmu1dWqVav85je/yZZbbpnvfe97q6y/6qqr0rp16/zmN79JURQtkLD+nnjiiTz00EMV11f7fnz22WezcOHCimp33HHHqs5ujh122CEPPPDAKusWLFiQ5557Ltttt10LpFoz/f3vf89555230pr1118/n/zkJ3Pccceld+/eWWeddVZa39jYmFGjRuWyyy7LX/7yl5Rl5d+DJkyYkCuvvDInn3xyxT3Ndeqpp+Z///d/m9W7/vrr59BDD02/fv2y++67Z/vtt0/nzp3Tpk2bzJw5M6+++moef/zx3Hvvvbn55ptz//33N3nGnDlzctRRR2XcuHHp3r17s3JWasyYMfnWt77V5L4OHTrkhBNOyGc+85nsu+++aWhoWGn9008/neuuuy6/+tWvMmXKlBXWlWWZz3/+8/n5z3/e5Ey18OCDD6Z///6ZOXNms/q7d++efv36Ze+990737t2z9dZbZ4MNNki7du3S2NiYWbNm5bnnnsukSZNy55135uabb87kyZObNOP111/P0UcfnX/84x9Zb731mpVzeR5++OH88Ic/bFbvNttsk0MOOSS77rprdtxxx+ywww5Zb7310qFDh7Rv3z6tW7fOvHnzMnfu3Lz22mt59dVX8+yzz2by5Ml57LHHMn78+Dz11FNVuxZ4ryia8h8rLaMoiheSbLb07ZLXcsl+meTrZVleVI9sq6MoinWSzMu/rmWpZa/tE2VZXlOHeABrhaIoZiTptKLznTp1yowZM1owEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8U2NjYyZNmlRxfffu3dOqVasaJmKNNnFYMnxIkrIZzUVy9NCk56A1Zw5QExdddFG+9rWvVVS7/vrrZ9q0aVl33XVrluf5559Pnz598vTTT6+ydocddsgtt9ySHXbYoWZ5auXyyy/P4MGD09jYuMraU089NZdeemmKomiBZPX1hS98IUOHDq2oduedd85jjz1W1fm33XZbDjnkkIpqjzvuuPz5z3+u6vymOvbYY3PddddVVHvbbbelb9++NU7UsqZOnZrttttulXUbbrhhWrdunVdeeWW55zt06JBzzjknp512Wjp16tSsLOPHj89JJ52Uhx9+uOKeLbfcMlOmTMk666zTrJmVuPTSSzNkyJAm9+2www4555xz8olPfCLt2rWruO/BBx/Mf//3f+f/+//+vyxatKhJM3fbbbfcc8896dixY1PjVmT69Onp0aNHnnvuuYp7iqLI5z73uZx33nnZeOONmzyzsbExv/rVr/Ktb30r06dPX2Fdjx498sADD6xyvT59+mT06NFNzlGJV155Jfvss0+eeeaZJvVtsMEG+dznPpeTTz45O+20U5Pn3nvvvbnwwgvzP//zPynLyv+e+MhHPpIRI0Y0ed6KHHXUUbnhhhsqru/UqVNOPfXUZl/3u73xxhsZNWpUbr311txwww154YUX/q3mt7/9bT7zmc+s9qx6eT88z+jcuXNmzpy5spKZZVl2bqk8a7uGegdguVZ1Azfvm1T9VfLtY229NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJqq56Dk6KFJimY0l8nwIcnEYSsvmzhscV3KZswoFufrOagZvUA1zJ8/Pz/72c8qrj/22GOz7rrr1jBR0rVr1zz11FMpy3KV25NPPpkddtihpnlq5eSTT87ChQsrus5f/epXKYrm/C5fu7z22mv53e9+V3H9pz71qapnmDJlSsW1W2+9ddXnN1VTMjTl2t5r3njjjbzyyivLPbfffvvlkUceyTnnnJNOnTo1e8bee++du+++O4cddljFPS+88EKuvfbaZs9clUceeSSnn356k3pat26dH/zgB3n00Ufz2c9+Nu3atWtS/5577pnf/e53+cc//pHddtutSb2PPPJIvvzlLzeppynOOuusPPfccxXXb7jhhhkxYkR+85vfZOONN27WzFatWuULX/hCHnjggXzoQx9aYd0DDzzQrPWrpbGxMcccc0yeeeaZinvWWWednH322ZkyZUouuuii7LTTTs2ave++++Yvf/lLbr/99iatceONNzbp/4yVefLJJzNixIiK60888cQ888wzq3Xd77bhhhvmmGOOyaWXXprnnnsuY8eOzamnnrpav5dgbddQ7wAsV9tVnK//N+TmqST3qq4dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA95Keg5KjhyYpmtFcJsOHJBOHLf/0xGGLz6dsxtrF4lw9BzWjF6iWn/70p3n++ecrrj/ppJNqmIb3u29/+9uZM2dORbWtW7fOJz/5yapnmDJlSsW1m222WdXnN1VTMjTl2t4vTjzxxIwePTrbbLNNVdbr2LFj/vrXv6Z3794V91x22WVVmf1uZVnm1FNPzfz58yvu6dKlS0aPHp1vfvObadOmzWrN79WrV/7xj3/k+OOPb1LflVdemdGjR6/W7OWZOHFirrjiiorrN9tss9xxxx054ogjqjJ/q622ysiRI6u2XrVddNFFGTt2bMX1u+yyy//Pjp3HWV3X+wN/fYdhVVCENFcidy0ZtTS1NBfc0kLSVFIrtVKy3O7vppVWpt26XSsrqVzyuoRmWqS2uJSZmppLWKSCW2myKaCgsvP9/QHc0Fi+Z+acOSDP5+PxfczhnNf78359D8PMMLn//vvz1a9+NWuttVZdOrz73e/OAw88kEMOOaTyzOmnn57Jkyd3ePcVV1yRsqz2f5rzzz8/l19+efr27dvhvctSFEV22223/OAHP8j48eNz4YUXZuDAgQ3bByurlmYXYKleXs5rRZJtOqtInVXp/UrDWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALByaRuWDBmRpGjHcJmMGp6MHvnap0ePXPh8ynacWSzs0zasHbNAvUyaNCnnnXde5fzuu++eXXbZpYGNWJ2NGTMmF110UeX8sGHDsskmm9S9x6RJkypn3/zmN9d9f61q6TB58uQGNln1HH300bnsssvStWvXup7bs2fPXH311endu3el/F133ZUJEybUtUOS/OhHP8rdd99dOb/eeuvl97//fXbbbbe6dejVq1d+/OMf59hjj61p7oQTTsi8efPq1iNJTj/99CxYsKBStk+fPvntb3+bbbbZpq4devTokZ///OfZY4896npuRz366KP50pe+VDm/995755577smgQYPq3mXNNdfMT3/60xx11FGV8lOnTs25557b4b0333xzpdzHPvaxnHbaaR3eV4s111wzw4cPz+OPP56DDjqoU3dDs7U0uwBLNWMZzy/+7dCgoiiq/RS0cqny3XlZ9w4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAbWduwZMiIJEU7hstk1PBk9MiFfxw9cuGfU7bjrGJhj7Zh7ZgF6umEE07I9OnTK+fPOuusBrZhdTZv3rx87GMfy/z58yvlW1pa8rnPfa4hXaZOnVo5u9566zWkQy1q6TBlypQGNlm17LrrrrnkkkvS0tLSkPPf8pa35LOf/Wyl7IIFC/KLX/yirvvnzp2br3zlK5XzPXr0yA033JBtt922rj2Shf9eL7roouy///6VZ8aOHZsrr7yybh3uv//+/O53v6uc//GPf5xtttmmbvuX1K1bt1x//fUZMGBAQ85vj1NOOSWzZ8+ulH3ve9+bG2+8MWuttVbD+nTp0iWXXXZZ9t5770r5iy++OOPHj2/3vlmzZuXBBx9cYa5nz5751re+1e49HdWlS5f079+/afuhGVqbXYClmpBko7z2N0LFEn9uTXJAkms7uVe7FUVRJDkwK/4t14ROqAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALB8f7o4uf+SZrfofEeMTPpt2vg9U55Mrhm29Nd6vzmZMaEdh5bJqBOTX56ezH21/d16vzm5+4KFV7298/hkp4/X/9ylGXlEMu3pztlVL535/rDSu/zyyzNq1KjK+QMPPDD77LNP4wqxWjvvvPPywAMPVM6fcMIJ2XLLLRvSZcqUKZWza621VkM61KKWDrXc2xvZGmuskZEjR6Zbt24N3XPyySfnv//7vzN9+vQVZu+4446ccMIJddt9xRVX5B//+Efl/Pe+973stNNOddv/el26dMk111yT7bbbLs8880ylma9+9as55phj0qVLlw7v/8Y3vlE5+/GPfzwHHXRQh3cuT79+/XLJJZdk8ODBDd1TxR/+8IfccsstlbKbbrppRo0alZ49eza4VdLa2pqf/OQn2XbbbTNp0qTlZmfNmpVvfetbNf09L+mJJ57I/PnzV5gbOnToSvF1H1Ynrc0uwFI9muSdK8icmOTaTuhSLwcn2ShJmaRYTu7RzqkDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwHK+8kDz/WLNbdL75czpvT6Pe37mvdmx+xoSFVyO88kJjzl2aaU+vep/Dnfn+sFJ74okn8pnPfKZyvnv37rngggsa2IjV2R//+Mece+65lfP9+/evKV+rKVOmVM727t27YT0a0WHq1KkNbLLq+NKXvpQBAwY0fM+aa66ZI488Mj/84Q9XmL3zzjvruvv888+vnD3ggANy3HHH1XX/0qy11lq55JJLsu+++1bKP/HEE/nFL36RoUOHdmjv5MmT87Of/axStl+/fvnGN77RoX1V7bPPPjnqqKNy1VVXdcq+ZfnCF75QKdelS5dce+21WWuttRrc6F/69euX733veznssMNWmL3iiivy1a9+NV27dq15zzPPPFMpt8suu9R8NtAxLc0uwFL9bRnPF0nKRR93L4pit86r1GHL+m5YLvF4UlmW0zqjDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArn1dffTVDhw7N9OnTK8987nOfy2abbdbAVqyuJk2alMMOOyzz5s2rPHP++eenb9++Dev04osvVs726dOnYT0a0aGWe3ujWn/99fOpT32q0/Z98IMfrJR77rnn8vzzz9dl55/+9Kc8+uijlbKtra254IIL6rK3isGDB2fo0KGV8//7v//b4Z3XXntt5s+fXyl7xhlnZK211urwzqrOOeecdO3atdP2vd7DDz+cO++8s1L25JNPzg477NDgRv/u0EMPzU477bTC3OTJk3PjjTe2a8eMGTMq5TbaaKN2nQ+0X0uzC7BUt1fIFEm+UxRFa6PLdFRRFMcmeUeSMgt7/1tk0WtV7hsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAN6hPfvKT+etf/1o5v9NOO+Vzn/tcAxuxupo3b16OOOKIjB8/vvLMIYcckmOOOaaBrZLZs2dXzq6xxhoNbFL/DrXc2xvVCSeckJ49e3bavt133z3dunWrlH3sscfqsvPyyy+vnD322GOz+eab12VvVeedd15aWloqZX/9619n8uTJHdp39dVXV8r16dMnJ554Yod21WrgwIE5/PDDO3Xnki666KJKud69e+fzn/98g9ss22c/+9lKuZ///OftOn/OnDmVcq2tre06H2i/at8t6GwPJnlh0ePyda8VSzzXluQbndSpXYqi2DrJBfn3+1ia3zS4DgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArqa997Wu56qqrKud79eqVK6+8Mq2trQ1sxerqpJNOyu9///vK+fXWWy8XXXRR4wotMnfu3MrZleHfRi0d5syZ08AmK7+iKPLRj360U3d27949bW1tlbJjx46ty86f//znlbOnnHJKXXbWYquttsqBBx5YKTtv3rzccMMN7d41derU3HvvvZWyRx99dNZYY41272qvE088sdN3Jsns2bPz4x//uFL2k5/8ZNZZZ50GN1q297///Vl33XVXmLvllltSlmXN5/fo0aNS7tlnn635bKBjWppdgH9XLvxKe12SYhmRIkm56ONniqI4ubO61aIoio2T/CrJ4u/+r7+fJb+jzEzS/p9IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhlXXfddfnc5z5X08z3vve9bLHFFg1qxOrs/PPPzw9/+MPK+ZaWllx11VXp379/A1stNGfOnMrZ1tbWBjappmvXrpWztdzbG9GgQYOyySabdPrebbbZplJu/PjxHd41ZsyYTJgwoVJ2jz32yNZbb93hne1x4oknVs7eeuut7d5zxx13ZMGCBZWyH/7wh9u9pyN23XXXDBw4sNP33nHHHXnppZcqZY8//vgGt1m+1tbWHHjggSvMTZ48OaNHj675/KrfW371q1/VfDbQMS3NLsAyXbiC14sk5aKP3yyK4szGV6quKIotk/wuyYD8q+dSo4tev6Ysy2rfNQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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ZflwURSHJrkhC//OyiTL+uln8fPlUp7rmuQdSXZc1q6KP1S9PrS0XUtTLvHxF0lOqrIMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFXfjBkzsv/+++fPf/5z5ZlevXrlpptuys4779zAZqyOxo8fn7322iv/+Mc/Ks+86U1vym9/+9tsuummDWy2fGussUbl7IwZM9KvX78GtqnWoapevXo1sMnKrUePHs2u0HDjx4+vnH3rW9/awCbVbbrpphk9evQKc7Xc22ITJkyolFt//fVrPrsR3vzmN3farn/+85+VcqNHj05RFA1uU3/Tp0/PBhtsUPPc8OHDc/XVV+eee+5p9+4xY8ZkzJgx+fa3v52iKLLVVltl1113zS677JJddtklW2+99Sr5nkKztDS7ANWUZXlzkg8nmbv4qRWMFIuuxdnF15KvtfcqX3ct+doyb2GJ3bcmOaIsyxXdAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvAK+88koOPPDA3HfffZVnunfvnlGjRmX33XdvYDNWR5MmTcree++dJ554ovJM3759c+utt2brrbduYLMVW2eddSpnp0+f3sAm9e9Qy7290RRF0ewKDTdx4sTK2XXXXbeBTapbb731KuUmTpyYsixrOvuFF16olHvTm95U07mN0pl/J//85z87bVczzJw5s11zXbp0yU9+8pNsuOGGdelRlmUeffTRXHrppTn++OOz7bbbpl+/fjnooIPyta99LQ888EAWLFhQl13wRtXS7AJUV5bldUkOSLL4p9Mq37mLJa7FMx29lnbucqsvMXNFkoPKspxTYQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAVdzMmTNz0EEH5a677qo807Vr11x33XUZPHhwA5uxOnr++eez995757HHHqs806dPn9x8880ZNGhQA5tVs84661TOzpgxo4FN6t+hX79+DWxCs1X9XOjSpUtNn+eNtO6661bKzZs3L7Nnz67p7JkzZ1bKrb322jWd2yid2WPy5MmdtqsZqv7dL83GG2+c2267LRtvvHEdG/3LtGnT8stf/jJnnnlm3vnOd2bdddfNRz7ykdx44401f47D6qCl2QWoTVmWtyfZLcmjSYok5aKriqKOV6W6i64iyfwkZ5Rl+dGyLOdVnAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgFTZr1qy8//3vz+9///vKM62trbn66qtz0EEHNa4Yq6WpU6dm8ODB+dvf/lZ5Zo011sivfvWrvPOd72xgs+r69etXOTt16tQGNqlm2rRplbPrrLNOA5vQbLNmzaqU69mzZ4qiaHCbanr16lU5O3PmzJrOrvp+dO/evaZzG6Uze9T6Xq5q5s6d26H5rbbaKvfdd1/23HPPOjVatilTpuSKK67I+9///mywwQY5+eST8+ijjzZ8L6wqWptdgNqVZflIURQ7Jjk/yfAk5aIrSVaGn0DKJR4XSZ5I8uGyLO9vUh8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDarNE/edNWzW7R+bp067w9y3p/Z72UzJjQ/rO79krmvtr++d7rJz3Wav/88qzRvzHnLk3fgZ23q1468/2hU8yePTuHHHJIbrvttsozLS0tueKKK/LBD36wgc1YHU2bNi377LNPHn744cozPXv2zE033ZTddtutgc1q069fv8rZiRMnNrBJNRMmVP+eXsu9seqZNWtWpVz37t0b3KS6WrpUvb/F5syZUynXrVsn/Xy+Ap359zJz5sxO29UMZVl2+Iz1118/t912W37wgx/krLPOytSpU+vQbPmmTp2a73znO/nud7+bgw8+OOecc04GDRrU8L2wMmttdgHapyzL2UlOKori6iQXJNkhSbnoWqzo7Fqv2/1qkq8n+UZZlrX9lAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBMO3184UVj9Ns0+dR9//786JHJqOHtPLRIhoxI2oYtcU5Z+zEzJiZ7n73wnFXZsGua3YDV3Jw5c/LBD34wv/nNbyrPFEWRSy+9NEceeWQDm7E6eumll7Lvvvvmz3/+c+WZ7t27Z9SoUXnve9/buGLtsNFGG1XOTpgwoYFN6t+hlntj1TN//vxKuS5dujS4SXWtra2Vs/Pmzavp7Kr3WfV9a7Ra768jZs6c2Wm7VmUtLS0ZPnx4hg0blgsuuCDf+9738sILLzR8b1mWueGGG3LTTTflox/9aM4///ysvfbaDd8LK6OWZhegY8qyvLssy3ck+UiSR5IUi65k4W+UFl8NWb+UHUWSWUlGJNmyLMuvlGU5q0H7AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeKMYPTIZNTxJ2Y7hIhkyImkbtvCPbcMW/jlFO84qF/YYPbIds0CSzJ07N4cddlh++ctfVp4piiI/+MEP8tGPfrRxxVgtTZ8+Pfvtt18eeOCByjPdunXL9ddfn3333beBzdpn4MCBlbMTJkxoYJNqJk6cWDlby72x6unWrVul3OzZsxvcpLpauvTo0aOms7t37173Do3UmT26dOnSabveCNZee+188YtfzD//+c9cddVV2XfffdPa2trwvQsWLMiPfvSjvO1tb8s999zT8H2wMmppdgHqoyzLK8uyfHuSg5LclGReFv5GafFvlcplXJWOX85sscT1ZJKzk2xSluVJZVk+18HbAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHUwemQyaniSsh3DRTJkRNI27LVPtw1b+HyKdpxZLuwzemQ7ZmH1Nnfu3HzoQx/KDTfcUNPct7/97XziE59oUCtWVzNmzMj++++f++67r/JMa2trrr766rzvfe9rYLP2GzhwYOXsU0891cAm1Tz55JOVs7XcG6ueHj16VMrNmTOnwU2qmz17duVs1furNf/qq6/WdG6jdGaPXr16ddquN5Lu3bvnwx/+cG6++eZMnDgxV155ZY466qhstNFGDd373HPPZc8998zPf/7zhu6BlVFrswtQX2VZ/irJr4qi6Jvkg0nel2T3JH1fH33dxype/9upBUn+nOS2JD8ty/LB2hsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwWhs9Mhk1PEnZjuEiGTIiaRu29JcXP9+u88tFc1n2+cBrzJs3L0ceeWRGjRpV09w3vvGNfOYzn2lMKVZbL7/8cg444IDcc889lWe6dOmSq666KkOHDm1gs44ZOHBg5ewTTzzRwCb17/DWt761gU1otp49e1bKzZw5M7Nnz0737t0b3GjFpk2bVjlb9f4W69OnT6Xc888/X9O5jdKZPXr27JmXXnpphbnddtstd911Vyc0WvX069cvRx11VI466qgkyTPPPJO77747d955Z+6+++6MGTMmCxYsqNu+2bNn5/DDD8+vf/3r7L333nU7F1Z2rc0uQGOUZTktySVJLimKokjSluQdSd6eZNskb03y5iRVflopk0xJ8s8kjyYZk+QvSe4uy/LFencHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgNTF6ZDJqeJKyHcNFMmRE0jZs+bHFr7drT7loLiveA6u5+fPnZ9iwYbn++utrmjv33HPzH//xHw1qxerqlVdeyYEHHpi777678kxLS0t+9KMf5fDDD29gs45705velL59+2batGkrzP7jH//InDlz0q1bt05o9u9mz56dZ555plK2X79+6devX4Mb0UzrrLNO5ezkyZOz8cYbN7BNNZMmTaqU6927d1pbW2s6e/3116+Ue/7552s6t1EmT57cabvWWmutTJw4cYW5mTNndkKbN4ZNNtkkm2yySY488sgkyfTp03PPPffknnvuyR133JF77703s2bN6tCOuXPn5ogjjshf/vKXyp/fsKqr7Ss/q6SyLMskf150vUZRFH2T9E/SM0mPJN2SzE8yO8msJNOTTCzLcl6nFQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOCNb/TIZNTwJGU7hotkyIikbVi1+OJcu/aVi+ZSfR+sZubPn5+jjjoqP/3pT2uaO+uss/L5z3++Qa1YXb366qt53/velzvvvLPyTFEUueiii3LMMcc0sFn9bL/99vnd7363wtz8+fPzyCOPpK2trfGllmLMmDFZsGBBpez222/f4DY02wYbbFA5O2HChGy88cYNbFO9RxW13Nti66+/fqXcc889l3nz5qW1tbXmHfX09NNPd9qujTfeOGPHjl1h7uWXX+6ENm9Mffr0yX777Zf99tsvSTJ79uz84Q9/yG9+85uMGjUqTz31VLvOfeGFF/L//t//y1VXXVXPurDSaml2AZqrLMtpZVk+XpblX8qy/FNZlneVZXlPWZYPlWX5SFmW/yzLcl6zewIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAGMnpkMmp4krIdw0UyZETSNqy2sbZhC+dStGNnubDv6JHtmIU3tgULFuSYY47JNddcU9PcZz/72ZxzzjkNasXqaubMmTnooINyxx131DR34YUX5rjjjmtQq/rbYYcdKmcffPDBBjZZvgceeKBytpZ7YtW04YYbVs6OGzeugU2qe+yxxyrlarm3xTbaaKNKublz5+app56q+fx6Gzt2bKftGjBgQKXcc8891+Amq4/u3btn8ODBOf/88/Pk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8sk6Nq3uy1/+cm6//fZK2b322svPhawWVp+fNklRFN2KolirKIp1i6LYuCiKTVamq9nvDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWa8Jdk1PAkZTuGi2TIiKRtWL1b1VfbsIU9U7RjuFz4/kz4S71bQUNcfPHF+fSnP13TzHve857cdNNN6dWrV4Nasbr6whe+kG984xs1zXzoQx/KlVdemS5dujSo1cqpR48eueCCCyrnZ8+enQ984AO57rrrOrz7mmuuydChQzNnzpzKMxdccEG6d+/e4d2s2jbffPN87nOfq2nmrLPOyrHHHptXX321Lh1++ctfZrfddstzzz1XeebNb35zvva1r9Vl/5K6du2a7373uzXNXHnlldl1110zZsyYDu2ePn16TjjhhBx99NGZO3fuUjM9evTo0I6O6NWrV66++uqavm785je/yTbbbJMrr7wyCxYsaGC713r00UfzhS98IZtsskmOOOKI3HPPPXU7+6WXXso3v/nNbL755jnggANy7bXXZtasWXU7f1nmzZuXU045Jeecc07lmU984hMNbAQrj5ZmF6C+iqLoWRTFXkVRnF4UxcVFUfyhKIoniqKYnmRmkqlJJiT5e5KnV6LrqYa9KQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADTG+tsle3y2HYNFMmRE0jas7pUaom3Ywr4pap/d47ML3ydYBZx33nkpy7KmmTvvvDNrrrlmiqJYqa6PfvSjjXmT6DTnnXdezTPXXnttWltbm/759/rrS1/6Uv3foNc5+OCDc9hhh1XOz5w5M4cddlg+9alPZdq0aTXvmzJlSk444YQceeSRmTVrVuW5D33oQ3nf+95X8z7emM4444xsv/32Nc1cdtllaWtry4033tjuvZMmTcpxxx2Xgw8+OFOmTKk8VxRFfvCDH2SttdZq9+7l2XffffOZz3ymppmHHnoobW1t+eQnP5mxY8fWNPvSSy/l29/+djbffPP88Ic/XGaupaUlZ599dk1n11tbW1suuOCCmmZeeOGFHHPMMWlra8uPf/zjmr5WVVWWZR566KGce+652X777bPNNtvkvPPOy8SJE+u+a8mdv/nNb3L44YdnvfXWy0c+8pFcd911mT59et13/epXv8q73vWumt77bbbZJgcddFDdu8DKqLXZBei4oijekuSwJIck2TH//vfajt8EAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAV7nrnw4x1fqzhQJENGJG3DGlapIRb3HTU8SVltZo8z/vX+AECDXXLJJXnooYfy5JNPVp4ZMWJErr766nz605/O0Ucfnc0222y5+bFjx+aKK67IhRdemJdeeqmmfptvvnkuvvjimmZ4Y+vWrVuuv/76vOMd78jUqVMrzz3++ON5//vfnx122CEnnnhiDj744Ky33nrLnZk/f37uueeeXH755Rk5cmReffXVmvueccYZ+cAHPlDzXC3++7//O3fccUcefvjhyjPz58/PRRddlIsvvjg777xz9t9//+y0007Zaqut0q9fv6yxxhqZPXt2pk+fnieeeCIPP/xwbrvtttxyyy2V3oeTTz45u+yyS0duqy4++clP5rnnnstXvvKVmub++te/5qijjsqnP/3pDBkyJAcccED22GOPrLvuujV3mDZtWv72t7/lvvvuy7333ps777wzkyZNqvmcepk+fXquuOKKXHHFFenatWt23nnnvPvd785uu+2Wtra2bLTRRjWdV5ZlRo8enZtuuinXX399TZ+Hi11wwQVpaWmpeQ5WRa3NLkD7FUWxX5JTkwxe8umlRCv+BqhpltYZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAVcWeZy78eMfXVhAskiEjkrZhDa/UEIt7jxqepFx+do8z/vW+AEAn6NOnT376059m1113zaxZsyrPTZs2Leecc07OOeecbL755nnHO96RAQMGZO21105ZlnnxxRfz9NNP54EHHshTTz3Vrm49e/bMtddemz59+rRrnjeugQMH5pprrsn73ve+zJ07t6bZhx56KB//+MdTFEW23XbbbLvttnnrW9+a3r17p1u3bnn55Zfz/PPP57HHHsuDDz6YF198sd093/e+9+Xcc89t93xV3bt3z4033ph3vetdGT9+fE2zZVnm3nvvzb333lu3PjvssEPOO++83HfffXU7syPOOeecTJkyJSNGjKh5dtq0abnsssty2WWXJUk22GCDbL311tloo42ywQYbZI011kiPHj1SlmVmz56dWbNmZcqUKZk0aVImTpyYxx9/PM8//3y9b6lu5s6dm7vuuit33XXX/z3Xp0+fbLnlltlwww2zwQYbpF+/funRo0d69OiROXPm5JVXXsnLL7+ciRMnZuzYsRk3blxeeeWVdnc46aSTss8++9TjdmCV0NrsAtSuKIq2JBckeffip5Z4eXm/6SmW81qzrOA3UwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKwS9jxz4cc7vraMQJEMGZG0Deu0Sg2xuP+o4UnKpWf2OONf7wcAdKLtt98+P/vZzzJkyJDMmTOn5vnHH388jz/+eF07devWLT/72c/S1tZW13N54xg8eHCuueaaHH744Zk3b17N82VZZsyYMRkzZkwD2iX77LNPrrvuurS0tDTk/NfbeOON86tf/Sp77LFHXnrppU7ZuTQbbbRRbrzxxvTs2bNpHZbmwgsvTP/+/XPOOed06Jzx48dn/PjxdWq1cpo+fXruv//+3H///Q3ftccee+T8889v+B5YmXTOdwXqoljoi0nuT/LuJMWiq1ziyhLPv/4CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxtnzzGSPM5byQpEMGZG0Dev0Sg3RNmzh/aT499f2OGPh+wAATXLAAQfk2muvTWtra7OrpLW1NT/96U+z//77N7sKK7mhQ4fm6quvTo8ePZpd5TX222+/3HDDDZ3ea9CgQfn973+f9dZbr1P3Lrbuuuvml7/8ZTbYYIOm7F+RL3/5y7n00ktXus+X1dW73/3u3HTTTenWrVuzq0Cnaml2AaopiqJXkpuTnJ2kSxb+NqdcdBWvuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKA59jwz2eOMJZ4okiEjkrZhTavUEG3DFt5Xin89t8cZC+8fAJrsAx/4QG6++eb079+/aR369++fW265Je9///ub1oFVy6GHHpo//OEP2XDDDZtdJUly+umn55e//GV69uzZlP1tbW256667svXWW3fq3s033zz33HNPtttuu07dW6tjjz02999//0rf843uqKOOyq233po111yz2VWg07U0uwArVhRFnyS/TbJ3Fv4Gp1x0FXnNb3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgJbDnmckeZyQpkiEjkrZhzW7UGG3DFt5fioX3u+eZzW4EAP9nr732ygMPPJAddtih03fvuOOOeeCBB7Lnnnt2+m5Wbe985zvz4IMPZujQoU3r8OY3vznXX399/ud//iddunRpWo8k2WyzzfLAAw/k2GOP7ZR9Q4cOzT333JO3vvWtnbKvo972trflT3/6U770pS9ljTXWaHadpdpwww1zyimnNLtG3a299tq59NJLc+WVV6ZHjx7NrgNN0dLsAixfURQtSa5JsvOip8rFL7XzyHIluwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgj2vPM5JN/SNqGNbtJY7UNW3ife57Z7CYA8G8GDBiQ++67L9/85jfTp0+fhu/r06dPvvWtb+W+++7LgAEDGr6PN6b11lsv119/fUaNGpWBAwd22t7W1taccMIJefTRRzN06NBO27sivXr1yqWXXppbbrklb3/72xuyY4MNNshPf/rTXH/99enXr19DdjRK9+7d88UvfjGPP/54jj/++HTr1q3ZlbLGGmvk8MMPz4033ph//OMf+cIXvtDus773ve/llFNOyeabb17Hhu3X2tqa448/Po888kiOPfbYZteBpmppdgFW6Owk+ycpF/25WHStSLmMCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADrH+ts1u0HnWF3uE4BVUmtra0499dSMHTs2p512WtZaa62671hrrbVy2mmnZezYsTnllFPSpUuXuu9g9fOBD3wg48aNy+WXX55tt922YXt69uyZE088MU888US+//3vZ+21127Yro4YPHhwRo8enR//+MfZZZdd6nLm1ltvnUsuuSRPP/10Dj300Lqc2Szrr79+Lr744jz77LP5yle+ko022qhT96+77ro5+uijc+2112by5Mm55pprctBBB3X46+G73/3ufOtb38q4ceMybty4fPOb38zee++dnj171ql5NX379s3JJ5+cxx57LBdffHHWX3/9Tt0PK6OiLMtmd2AZiqLYNslDSVoXP7WCkdf/ZS4t/1KSWUlmLyXfVGVZDmx2B4CVXVEU05P0XtbrvXv3zvTp0zuxEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC81vz58zNu3LjK+S222CJdunRpYCMAAJb08ssv54orrsjPfvaz3HnnnZkzZ067zunWrVve85735IMf/GCOPvrorLnmmnVuCq91//335+qrr87Pf/7z/P3vf+/QWT179swee+yRI444IkOH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794F4jW5VKlSuu+++7Rs2TLt2LFDAwcOzPNZn3zyiQYNGqRq1ar5sWHeFS1aVI8//ri2bt2qHj16BLsOEFTBf7WBFY9ISjv3sXmRjHHuMUNSTUkLDcP4zDCM650uZxhGqGEY90naeq5ryAU9jRxGzvc0JS0wTdPndEcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQODVK10v2BUC4kq5TgAIpCpVquiBBx7QwoULdfz4cX3++efq16+fqlSpEpQ+RYsWVc+ePfWf//xHu3bt0mOPPaZixYoFpYtd4eHhevnll7V582YNGDBARYsW9fuOihUr6oUXXtD27dt19913+/18XHkMw9CAAQO0Z88evfXWW6pevbpju0qUKKGnnnpKe/fu1csvv6z/Z8fOw/Mq6/SB3ycNtHSzrLWsZV9H2VQ2lbLDqLSCGzoKigKKCj9BJSguSIZBcRQoo4AooIIbDYiyFMoOstgBkbUULFuhhZoudE/P7w9TJ2KTvknfpcXP57qeK+97zv083/u0adJkwIABNZu1Ij74wQ/msccey//8z//k3/7t36py5lvf+tb86le/yiOPPJK99967Kmc2ypZbbplf/epXmTx5ck4++eSss846dZ2/0UYb5VOf+lSuueaavPjii/nRj35UlT/TQw45JD/4wQ/yzDPP5IEHHsgZZ5yRPffcM6utttqKl+6FESNG5Ctf+UomT56cs846K294wxvqOh9WRkVZlo3uQAWKomhJ8q0kZZKih+jSv9Ci83WZ5IYkP05ydVmWC6rYafMkH0ny8SQbdunVtUNP/WYl2aksy6er1Qng9a4oillJhnR3f8iQIZk1a1YdGwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAP+ro6MgTTzxRcX6rrbZKv379atgIAHi9mTJlSu6+++7cfffdueuuu/Lggw9m0aJFVZ3R1NSUHXbYIW9/+9szatSoHHTQQRk0aFBVZzTKK6+8kosvvjhtbW2555570tHR0adzBg0alFGjRuUDH/hA3v/+92f11VevclP4P0uWLMltt92Wn//85/ntb3+bF198cYXOGzp0aPbbb7986EMfyrve9a4MGDCgSk3r55577sk111yT66+/Pg888EBFXwfXWWed7LjjjjnkkEPy7ne/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09qWBQBYCTU3ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsHJ75JFH8rvf/S7XXHNN7rrrrixevLjqM5YsWZL77rsv9913X84888xst912Ofroo/PJT34ygwcPrvq8VcXpp5+e008/veL8jBkzst9+++Xmm2/ODjvsUMNmr0/HH398fvnLX/Z63zvf+c4ceeSR1S9UZa+88kouuOCCnH/++Xnuuef6dMbzzz+f559/Ptdcc02SZNddd83nPve5fOADH8jqq69ezboAACutpkYXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWPg899FC++tWvZuutt87222+fL37xi7ntttuyePHiusx/5JFH8v/+3//LJptsktNPPz3z5s2ry9yVyZlnnpnTTjut1/tefvnl7LvvvnnkkUdq0Or168orr8wvf/nLRteoidmzZ+ekk07KhhtumJaWljz33HNVO/v+++/PRz/60Wy88ca58MILU5Zl1c4GAFhZNTW6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwcnjppZfy3e9+N29605vypje9Kd/61rfyxBNPNLTTjBkzctppp2X77bfP7373u4Z2qaezzz47p5xySp/3T5s2Lfvuu28ef/zxKrZ6/ZoxY0Y+/elPN7pGTfzyl7/MNttsk7PPPjvz58+v2ZyXXnopn/rUp7LbbrvlgQceqNkcAICVQVOjCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjTd+/PhsuOGG+cIXvpCHHnqo0XX+ydNPP513vetd+exnP5uFCxc2uk5Nff/7389JJ520wue8+OKL2WeffTJp0qQqtHp9+9znPpeXXnqp0TWqatGiRTn++OPzgQ98IC+88ELd5t57773Zfffdc8kll9RtJgBAvTU1ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw+jT/0UcbXaEu/lWek9e/mTNnZvHixY2usVznnXde3vGOd+SVV15pdJWaOP/883PCCSdU7bwXXngh++yzT5566qmqnfl689vf/jY/+9nPGl2jqtrb27Pvvvtm7NixDZk/f/78HHnkkTnhhBNSlmVDOgAA1FJTowsAAAAAAAAAAAAAAAAAAAAAAAAA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Z/Hixd1mX3311bz66quZPn16/vznPydJzj777DQ1NWWvvfbKEUcckY9+9KNZY401Kn6elcHMmTNz/fXX54477sgdd9yRhx9+OAsXLqxob1NTUzbffPPsueee2WuvvXLAAQdko402qnHj6ps3b16uuOKKXHjhhbnnnnuyZMmSbrMzZszIjBkzMmXKlEycOPHv1wcOHJj99tsvH/nIR/Le9743/fr1q0f1ups/f35uvfXW3HnnnbnzzjszceLEtLe3V7x/vfXWyx577JE999wzBx10UHbYYYfala2iSZMm5aabbspdd92VP/7xj3nyyScr/nfS1dChQ7PJJptk5MiR2WqrrfK2t70tu+222yr57wZqobnRBejWbhVkbqjyzKOTDExSJunuJ4ulP80WSe5K8oMk15Zl+UqSFEXRlGSLJB/rPG/dbs4rupy1ZpJPJjm7Kk8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAww0bMzpJMrWlJSnL3m0uy7/t63JOLbWPa+tbzyQpioxoba1LT/hXNmDAgKy55pqZMWNGRfk5c+ZkyJAhNW61bP/7v/+bAw44IDNnzqwov/XWW+e6667LyJEja1usU0tLSzbccMMcffTRWbRo0XLz48ePz3vf+96MGzcu/fv3r0PD6liwYEGOOuqodHR09Jg77bTTstVWW9WpVfWMHz++4uyhhx5awybL9p73vCe//e1vK8qOHz8+7373u2vcaNU2d+7c/Pd//3fOOeecTJs2bYXOWrJkSW677bbcdtttOe200/KlL30pn/vc59Lc3FylttW3ZMmStLW15bLLLsu1116bBQsW9PmcSZMmZdKkSfnJT36Soiiy11575Ygjjsh//Md/ZNCgQVVuXl0LFizIOeeckzPPPLPi74fdmTt3bq6++upcffXV2XzzzXPyySfnk5/8ZJqamqrUtnHKssy1116byy+/PFdddVVmz57d57OmTZuWtra2tLW15eSTT84OO+yQD3/4wznmmGOy5pprVrH1invppZdy0UUX5fLLL8/DDz9clTNnzZqVhx56KA899NA/XB8xYkR22223HHTQQRkzZkzWXXfdqsyDVc2q/xXz9ettFWRurPLMjyfp7rdKZecqkixJclxZlnuVZfnTsixf+XuoLJeUZflEWZanJvm3JBM69/R0bpHkmCo9AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACuJYWNGZ0Rra1IUvd9clpna0pL2cW1V79VV+7i2TG1pScqy95uLIiNaWzNszOiq9wL+2cCBAyvOln35N10Ff/rTn7L//vvnr3/9a0X53XffPXfeeWdGjhxZ22Kv8dGPfjS//e1vM3jw4Iry1157bQ4//PAsXLiwxs2q55vf/GYeeeSRHjNvfvObc/LJJ9epUfVMnTo1f/7znyvKbr755nX//EqS/fbbr+LsDTfcUMMmq74bbrghO+ywQ77yla9k2rRpVT172rRp+cIXvpBdd901f/rTn6p6djUsXrw4P/7xj7PtttvmsMMOS1tbWxYsWFC188uyzO23357jjjsuI0eOzBlnnJFZs2ZV7fxquummm7Lddtvli1/8YmbMmFHVsydPnpxjjz02e+yxRx5++OGqnl1PixYtyo9//ONst912+fd///f89Kc/zezZs6s6489//nNOOeWUbLLJJvnyl7+c9vb2qp7fF88//3w+9alPZaONNspXvvKVuvwdTp06NePGjcsxxxyTESNGZL/99ssPf/jDzJkzp+azYWXS1OgCdGvbZVzr+hPiS2VZPlOtYUVRvC3Jlkvfdhfr7HBUWZY/XN6ZZVlOS3Jgklu77H3teUttXhTF7r0qDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwEpv2JjRGdHamhRF7zeXZaa2tKR9XFvVeyVJ+7i2TG1pScqy95uLIiNaWzNszOiq9wKWbfbs2RVnBw8eXMMmy/bwww9nv/32yyuvvFJR/j3veU9uuummrL322jVutmwHHnhgbrnllgwfPryi/DXXXJMPfOADWbRoUY2brbiJEyfmrLPO6jHTr1+//OhHP0pzc3OdWlXPzTffXHF2v/32q2GT7o0cOTKbb755RdnHH388U6dOrXGjVU9HR0c+//nP58ADD8zTTz9d01kPPvhg9thjj4wbN66mc3rjvvvuy1ve8pZ8/OMfzxNPPFHzeS+//HK+8pWvZNttt81vfvObms+rVEdHR0499dQccMABeeqpp2o665577snOO++cSy65pKZzamH8+PHZfvvt8/GPfzyPPfZYzefNnj07//Vf/5VtttkmV1xxRc3nLUtZlvn+97+frbbaKhdeeGHDvj93dHTkpptuyrHHHpv777+/IR2gUZoaXYBujezmepGkTFLtr1aH93Cv7DL38rIsf1rpoWVZdiR5X5IXupzVnUMrPRcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBVx7AxozOitTUpit5vLstMbWlJ+7i2qnZqH9eWqS0tSVn2fnNRZERra4aNGV3VTkD3Fi1alFmzZlWU7devXwYPHlzjRv/o0Ucfzb777pvp06dXlD/mmGNy5ZVXZo011qhxs57tsssuueuuu7LllltWlG9ra8sRRxyRxYsX17hZ3y1atChHHXXUcjv+v//3/7LLLrvUqVV13X///RVnd9tttxo2qd7sP/7xjzVssuqZOXNm/v3f/z3nnHNO3Wa++uqrOfzww3PFFVfUbeayLFmyJKeeemp22223PPDAA3Wf/8ILL+Twww/PYYcdltmzZ9d9flfz5s3LmDFj0tramiVLltRl5sKFC3PkkUfmW9/6Vl3mraiZM2fmiCOOyAEHHJBJkybVff5LL72UD33oQzniiCMyd+7cus2dOXNmDj744Jxwwgl1nQv8o6ZGF6BbI5P09Nueh6s8b3Q387pe60hyam8PLsvy5SStSXr6jVqR5ODeng0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCqYdiY0RnR2poURe83l2WmtrSkfVxbVbq0j2vL1JaWpCx7v7koMqK1NcPGjK5KF6AyDz/8cMoK/82OHDkyTU1NNW70f5544onsu+++eemllyrKf/Ob38wPfvCD9OvXr8bNKrPZZpvlrrvuytve9raK8r/+9a/zkY98JB0dHTVu1jdnnHFG/vSnP/WY2XzzzfONb3yjTo2qb+LEiRVnd9lllxo26dmuu+5acbY3z/R6N3v27Oy///65/vrr6z57yZIl+ehHP5obb7yx7rOTZObMmXnXu96V1tbWLFmypCEdlrryyiuz2267ZdKkSQ2ZP2fOnBx00EH57W9/25D5X/3qV3PGGWc0ZHalHnroobzlLW/J5Zdf3ugqufzyy7PHHnvk2Wefrfms6dOnZ88992zI1wjgH9XvJw4qVhTF4CRrLn3bTeyJKs7bLMnmPcwrkpRJrirLckofx1yU5IXO16/9qXjp++2LohjSx/MBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYyQ0bMzojWluTouj95rLM1JaWtI9rW6EO7ePaMrWlJSnL3m8uioxobc2wMaNXqAPQe/fff3/F2a222qqGTf7R5MmTs88++2Tq1KnLzTY3N+fiiy/OV7/61To065111lknEyZMyLve9a6K8r/4xS/ysY99LEuWLKlxs97505/+lNbW1uXmLrjggqyxxhp1aFR9ZVnmgQceqCg7YMCAbLfddrUt1INdd9214uzEiRNr2GTVMX/+/LznPe/Jfffd17AOixYtyoc//OG8+OKLdZ07Y8aMvPOd78y1115b17k9eeSRR7LHHnvkoYcequvcxYsX533ve19uu+22us59ra9+9au54oorGtqhO9ddd1122223TJo0qdFV/u7BBx/M3nvvnWeffbZmM+bMmZODDjooDz/8cM1mAJVrbnQBlmlkBZmnqzhv/wpzP+rrgLIsFxZF8askn0/S9bdZRZf3RZK3Jbmxr3MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYuQ0bMzpJMrWlJSnL3m0uy7/t63JOb7SPa+vb3CQpioxobe3TXGDFXX311RVn3/rWt9awyf95+umnM2rUqDz//PPLzQ4aNCi/+tWvcvDBB9ehWd8MHDgwbW1tOfbYY3PRRRctN/+zn/0szc3Nufjii9PU1FSHhj1bvHhxjjrqqCxatKjH3Cc+8Ynss88+dWpVfVOmTMnMmTMrym655Zbp169fjRt1b5tttqk4++CDD9awyarj6KOPzi233FJRdujQodl5552z+eabZ/3118+gQYPSr1+/vPrqq3n++efz+OOP57777su8efN63WPatGk59thj09bW1uu9fdHe3p79999/pfw8ePnll7Pvvvvm5ptvzvbbb1+XmZ/+9Kdz3XXX9Xn/G9/4xuy0007Zeuuts9Zaa2XgwIGZO3du2tvb88QTT+SBBx7Ic889t9xzyrLMUUcdlTe96U197lILV199dd73vvdl4cKFja7yT5566qnsvffeueuuuzJ8+PCqn3/88cdn4sSJVT8X6JvmRhdgmdauIDOtivPe3s31rr95mpHkhhWcc02Szy8ns0OSG1dwDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACuxYWNGJ0mmtrQkZdm7zWX5t31dzqlE+7i2vs1LkqLIiNbWXs0DqmfmzJm54YYbKs7vvffetSvTacqUKRk1alSeffbZ5WbXW2+9XHPNNXnLW95S814rql+/frnwwguzwQYb5Bvf+MZy85dcckmam5tz4YUXpiiKOjTs3llnnZWJEyf2mBkxYkS+853v1KlRbTz11FMVZ7fYYosaNlm+ddZZJ8OGDUt7e/tys88++2wWL16c5ubm2hdbSV100UX52c9+1mNmxIgR+Y//+I+8//3vz0477ZSmpqYe8wsXLsy1116bsWPHZvz48b3qc9VVV+Wmm27Kvvvu26t9vdXR0ZHDDjtsuf9+uzN8+PAcdNBBGTVqVLbbbruMHDkyQ4YMSb9+/TJ79uy8+OKLefTRR3PnnXfm97//fR5//PFez5g+fXoOPvjg/PGPf8y6667bp56Vuuyyy3LhhRf2et9aa62Vj3/84/nIRz6SN7/5zcvNP/zww7n88stz0UUX5aWXXuo2N3/+/Bx11FH51Kc+1etOtXDDDTfk8MMPz6JFi/q0f8cdd8w73/nO7Lrrrtliiy2y8cYbZ+jQoVljjTWyaNGizJ49O1OmTMljjz2WO+64I9dcc02ef/75Xs146qmncvjhh2fChAlZbbXV+tRzWa677rpccsklfdq79dZbZ999980222yTzTffPJtttlmGDBmSQYMGZdCgQSmKIgsWLMjcuXPz8ssvZ/r06Xn66aczadKkPPLII7nvvvvy3HPPVe1Z4PXiX/d/LSu3gRVkpldx3p5JuvtNU9F577dlWS5ZwTm3JVmcpF/nmcv66WurFZwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAKmDYmNFJkqktLUlZ9m5zWf5tX5dzetI+rq1vc5KkKDKitbWiOUBtXHDBBVmwYEFF2WHDhmX33XevaZ/nnnsu++yzT6ZMmbLc7Oabb57rr78+m2++eU07VdvXv/71bLjhhjn22GPT0dHRY/ZHP/pRmpub8z//8z8piqJODf/RI488km9+85vLzZ177rkZNmxY7QvV0NNPP11xdsstt6xhk8psscUWuf/++5eb6+joyDPPPJPNNtusDq1WPn/5y1/yuc99rtv7a6+9dk4//fR8/OMfT//+/Ss+d/XVV8+hhx6aQw89NDfccEOOPvroPPvssxXvb2lpyT333FNxvi9aWloyYcKEXu/baaedcsopp2TMmDFpbm5eZmattdbKWmutle222y6HHXZYvvvd7+aOO+7It7/97Vx99dW9mvfss8/mgx/8YG644Yb069ev130r8dRTT+Uzn/lMr/asttpqOfHEE/OVr3wlQ4YMqXjf9ttvn29961v5yle+krPOOitnnnlm5s2bt8zsvffeW/H34Vp6/PHH84EPfCCLFi3q1b71118/xxxzTI466qhstNFG3eb69euXAQMGZN11182uu+6aj3zkIynLMjfddFP+8z//s1efp3fccUdOPPHEnHfeeb3q2p2yLPOlL32pV3vWXXfdfP7zn89HPvKRbLLJJsvNNzc3Z9CgQVl33XWz7bbb5h3veMc/3J86dWpuuumm3Hjjjbnmmmvyyiuv9KoPvB41NboAyzSwgsyr1RhUFMX6SZZ+he3pJ6FrV3RWWZaLkkxeTmzkis4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABg1TBszOiMaG1NiqL3m8syU1ta0j6urcdY+7i2TG1pScqy9zOKIiNaWzNszOje7wWqYuHChTnnnHMqzr/vfe9L//79a9go2XDDDTN58uSUZbnc9eSTT2bzzTevaZ9aOfroo7N48eKKnvMHP/hBir58La+Cjo6OHHXUUVmwYEGPuTFjxuSwww6rU6vaefrppyvObrzxxjVsUv0OvXm215spU6Zk3rx5y7x36KGH5rHHHstxxx23Ql/fDjjggNx3333ZeeedK95z77335q677urzzOUZP358zjrrrF7tGThwYH7wgx/k/vvvz/ve9740Nzf3av9ee+2Vq666KuPHj8+GG27Yq70TJkxIa2trr/b0xrHHHpvZs2dXnN94441z++2357/+678yZMiQPs0cMGBATjvttNx7773Zeuutu809+OCDfTq/WmbPnp13v/vdaW9vr3jP4MGD8+1vfzuTJ0/Oaaedlo022qjXc4uiyH777ZebbropbW1tWX/99SveO3bs2Nx88829nrksEyZMyJ/+9KeK81/84hczZcqUnHrqqdlkk02q0mHEiBH5yEc+kp/85Cd58cUXc8MNN+SII46o+f+7YGXW1OgCLNPACjI9/+RQuT26ud71N1BLktxQpXmPJ+nup64iyfAqzQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAVMGzM6IxobU2KovebyzJTW1rSPq5tmbfbx7VlaktLUpa9P7soMqK1NcPGjO79XqBqvve97+W5556rOH/UUUfVsA0ro+9+97u59957e8wMGzYsY8eOrVOj2nr66acrzr7xjW+sYZPqd+jNs/2rOOWUUzJu3Liss846VTlv+PDhuf7667P55ptXvOeHP/xhVWa/1rx583Lcccf1as9mm22W+++/P8ccc0yamppWaP5+++2XBx54IKNGjerVvjPOOCNPPPHECs1elquvvjrjx4+vOL/NNtvk7rvvztve9raqzN9hhx1y9913Z9ddd63KedV28sknZ9KkSRXn99hjjzz00EM56aSTMmDAgKp0OPTQQzNx4sTsueeeFe/51Kc+lfnz56/w7EsuuaSiXFNTU371q1/lv/7rv7LGGmus8NzuNDc3Z//998/PfvazPP/882ltbc16661Xs3mwslqx70TUysAKMn34LdEy7d7DvaW/5fpTWZYzqzRvSjfXlz7PulWaAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCpi2JjRGdHamhRF7zeXZaa2tKR9XNs/XG4f15apLS1JWfb+zKLIiNbWDBszuvd7gap56aWXcsYZZ1Scf8c73pHdd9+9ho1Y2Tz++OM57bTTlpv79re/nREjRtShUe299NJLFWff+MY31rBJ9TtMmzathk1WPaeeempaW1tT9OX/Rz1YZ5118vOf/zz9+vWrKH/VVVdl4cKFVe2QJK2trZk8eXLF+a233jq33357tt1226p1WHvttfP73/8+Bx10UMV7FixYkOOOO65qHZKko6MjJ510UsX5DTfcMDfffHPWX3/9qvZYc801c+ONN1b1z7gaJkyYkAsuuKDi/BFHHJEJEyZk5MiRVe8yfPjwjB8/Pvvuu29F+SeffDLnn3/+Cs+94YYbKsp97Wtfy+GHH77C83pj7bXXzimnnJIpU6Zkp512qutsaLSmRhdgmVarIDOoSrOW99NnmeSWKs1KkjnLuT+kirMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYRQwbMzojWluTouj95rLM1JaWtI9rS5K0j2vL1JaWpCx7f1ZRZERra4aNGd37vUBVHXvssZk1a1bF+a9+9as1bMPKZsmSJfn4xz+e+fPn95jbe++984lPfKJOrWpvxowZFWeHDx9ewybV7/DKK6/UsMmq5X3ve1++9a1v1ez8t771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WltbK+Uefvjhmveuh4ceeqjPZr32ta/N/fffv8rc3Llz+6DN2mn06NE59NBDc+ihhyb522t57bXX5te//nUuu+yyPPnkkz3a9957701HR0dOP/303qwL/VZTowvQO8qynFuW5TVlWX67LMuTy7I8rizLY8qynFSW5allWV5YluWfy7Ls7qM+ZZJdk6xX4fifvugEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA/zB78pR0trcnZVn74qJIa0dHWtom1LSspW1CWjs6kqKofWZZprO9PbMnT6l9Lazluru7c9RRR+UnP/lJTetOPvnkfOELX6hTK1i77bTTTpWzt99+ex2brNy0adMqZ2u5J9ZMG220UeXsvffeW8cm1SxatCgPPvhgpWwt97bUxhtvXCn36KOPZsGCBTXv39vuueeePpu1ySabVMo98cQTdW7y6rHuuuvm0EMPzTnnnJPHH388U6dOzb//+79n8ODBNe/1rW99K88++2wdWkL/09ToAqy9yrJ8vuLRg/+sAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsCaaPXlKOtvbk7KsfXFRpLWjIy1tE3o0u6VtQlo7OpKiqH1xWaazvT2zJ0/p0WxYG3V3d+f9739/fvSjH9W07uMf/3i+8pWv1KkVrP123nnnytlp06bVscnK3XbbbZWzO+20Ux2b0B9ssskmlbN33313HZtUc//992fx4sWVsrXc21LbbLNNpVx3d3emT59e8/69aebMmZk1a1afzdtss80q5R599NE6N3l1Kooie+21Vy644II88sgjmTRpUpqamiqvf/HFF3P++efXsSH0H9W/MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWw+zJU9LZ3p6UZe2LiyKtHR1paZuwWh1a2iaktaMjKYraF5dlOtvbM3vylNXqAGuD7u7u/Md//EcuvvjimtZNmjQp3/jGN+rUCl4d3vKWt1TOXn/99XVssmKLFi3KH/7wh0rZIUOGZPz48XVuRKNtv/32lbN//OMf69ik9zvUcm9LbbnllhkyZEil7E033VTz/r2p6vdyb9lxxx0r5ebMmZOHHnqozm1e3TbccMOcffbZufLKKzNs2LDK6y699NI6toL+o6nRBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC13+zJU9LZ3p6UZe2LiyKtHR1paZvQK11a2iaktaMjKYraF5dlOtvbM3vylF7pAmuisiwzceLEXHDBBTWt++AHP5j//M//rE8peBXZbbfdMmzYsErZqVOnZtGiRXVu9M/+8Ic/ZO7cuZWye+65Z4YMGVLnRjTa+uuvn7Fjx1bK3njjjXVu07sdxo8fX/P+TU1N2XbbbStlf//739e8f2/q6/lvfvObK2dvvfXWOjZhqf333z+XXnpp5fy0adPy4osv1rER9A9NjS4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArN1mT56Szvb2pCxrX1wUae3oSEvbhF7t1NI2Ia0dHUlR1L64LNPZ3p7Zk6f0aidYE5RlmQ9/+MM577zzalr3gQ98IOecc06KnnzPAS8zaNCg7L333pWyL774Ym688cY6N/pnv/nNbypn999//zo2oT/ZcccdK+WmT5+exx9/vM5tVu7KK6+slBs5cmQ222yzHs3Yc889K+WuuuqqLFq0qEczesNll13Wp/PGjx+foUOHVspeffXVdW7DUgcddFCOOOKIStmurq7ccccd9S0E/UBTowsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa6/Zk6eks709KcvaFxdFWjs60tI2odd7JUlL24S0dnQkRVH74rJMZ3t7Zk+e0uu9oD+bNGlSvve979W05t/+7d9y7rnnpujJ9xqvKlOmTElZlv3meOihhyp333vvvWvae8KECav1Wu2///6Vs5dccslqzeqJWmYecMABdWxCf7LvvvtWzk6ZMqV+RVZh2rRpeeyxxypl99lnnx7/fKv6ejz//PO55pprejRjdf3lL3/Jfffd16czBw4cmP32269S9pe//GW6u7vr3IilPvzhD1fOPvjgg3VsAv1DU6MLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGun2ZOnpLO9PSnL2hcXRVo7OtLSNqHXey2rpW1CWjs6kqKofXFZprO9PbMnT+n1XtAffexjH8t3vvOdmtYcccQR+eEPf5impqY6tYJXp7a2thQVf3b97Gc/y+LFi+vc6B9uvfXW3HfffZWyW2yxRcaPH1/nRvQX+++/f+XsxRdfXMcmK3fBBRdUztZyT6+09957Z+DAgZWy5557bo/nrI7vf//7DZnb1tZWKffUU0/liiuuqHMbltptt90yYsSIStlZs2bVuQ00nr9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgF43e/KUdLa3J2VZ++KiSGtHR1raJvR6r+VpaZuQ1o6OpChqX1yW6Wxvz+zJU3q9F/Qnn/jEJ/Kf//mfNa1597vfnYsvvjgDBgyoUyt49dp0002zxx57VMo+/fTTmTx5cp0b/cO5555bOXvkkUfWsQn9zfbbb5+NNtqoUvaPf/xjpk2bVudG/2zu3Lm5+OKLK+cPPPDAHs8aMWJEDjjggErZyy67LI888kiPZ/XE7Nmza3otetOhhx6a5ubmStmzzjqrzm1YasCAAdl4440rZefNm1fnNtB4TY0uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKxdZk+eks729qQsa19cFGnt6EhL24Re77UyLW0T0trRkRRF7YvLMp3t7Zk9eUqv94L+4FOf+lS+8Y1v1LSmra0tP/rRjzJgwIA6tQLe9773Vc6eeeaZdWzyDzNnzszFF19cOV/LPbB2eO9731s5+6UvfamOTZbvrLPOygsvvFApu+uuu2aLLbZYrXlHHHFEpdzixYvzhS98YbVm1eqMM86o/Fr0ttGjR+ewww6rlL3mmmty9dVX17kRS40YMaJSbtCgQXVuAo3X1OgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwNpj9uQp6WxvT8qy9sVFkdaOjrS0Tej1XlW0tE1Ia0dHUhS1Ly7LdLa3Z/bkKb3eCxrps5/9bL761a/WtOad73xnfvrTn6a5ublOrYAkec973pN11123UvaWW27Jb37zmzo3Sr7+9a9nwYIFlbJ77LFHXv/619e5Ef3Nv//7v1fOTpkyJX/4wx/q2Oblnn766Xzta1+rnK/lXlbkX/7lXzJixIhK2QsvvDC33377as+s4qGHHspZZ53VJ7NW5KMf/WhN2fnz59exDUt1dnZWyg0fPrzOTaDxmhpdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFg7zJ48JZ3t7UlZ1r64KNLa0ZGWtgm93qsWLW0T0trRkRRF7YvLMp3t7Zk9eUqv94JG+MIXvpDTTz+9pjUHH3xwLr300gwcOLBOrYClWlpacuyxx1bOn3jiiVm8eHHd+tx///0566yzKuf/v//v/6tbF/qvbbfdNrvuumvl/MSJE/PSSy/VsdE/HH/88Xn++ecrZUeMGJHDDz98tWeuu+66+eAHP1gp29XVlaOPPrrur0dZlvmP//iPzJs3r65zVmW33Xar/LVy991352Mf+1idGzF37tw88cQTlbKbbLJJndtA4zU1ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACw5ps9eUo629uTsqx9cVGktaMjLW0Ter1XT7S0TUhrR0dSFLUvLst0trdn9uQpvd4L+tJXv/rVfP7zn69pzQEHHJCf//znGTRoUJ1aAa904oknZuDAgZWyd911V7761a/WpUd3d3c++MEP5qWXXqqU32677XLIIYfUpQv93ymnnFI5e+edd+bkk0+uY5u/ueiii3LJJZdUzk+aNCkjR47sldkf+9jHKn8f/+Uvf8nxxx/fK3NX5DOf+Uyuu+66us6o6swzz6ycPffcc3PGGWfUsU1jLF68uNEV/u7HP/5x5T7bbrttndtA4zU1ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwZps9eUo629uTsqx9cVGktaMjLW0Ter3X6mhpm5DWjo6kKGpfXJbpbG/P7MlTer0X9IVvfvOb+dSnPlXTmv322y9TpkzJ4MGD69QKWJ6NN94473//+yvnP//5z+f666/v9R5f/OIXc+2111bOt7e3p+jJz1jWCu94xzuy0047Vc5/61vfyvnnn1+3PjfddFMmTpxYOb/OOuvk4x//eK/N32ijjfLhD3+4cv4HP/hBvvSlL/Xa/GV973vfS0dHR1327oldd901hx9+eOX8ySefnK985St1bFSbsizzi1/8oqbP7yvttNNOOfvss7NgwYJebFa7efPm5Rvf+Eal7KabbppNNtmkzo2g8ZoaXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYc82ePCWd7e1JWda+uCjS2tGRlrYJvd6rN7S0TUhrR0dSFLUvLst0trdn9uQpvd4L6unb3/52TjzxxJrWvPWtb81ll12WoUOH1qkVsDKnn356Ro4cWSnb1dWVtra2/PnPf+61+eedd15OO+20yvk99tgjRxxxRK/NZ830jW98o6b8xIkTc+GFF/Z6jxtvvDEHHXRQFi5cWHnNZz/72YwePbpXe5x66qlZf/31K+c/85nP5FOf+lS6u7t7rcMZZ5yRD33oQ722X2/51re+lQ022KBy/tOf/nTe//73Z+7cuXVstXLz5s3LD37wg+ywww6ZMGFCbr311h7v9eijj+ajH/1oNt1005x66qnp7OzsxabVHXfccbn77rsrZd/xjnfUuQ30D02NLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsmRb87/+ms709KcvaFxdFWjs60tI2odd79aaWtglp7ehIiqL2xWWZzvb2LPjf/+39YlAH5557bj7ykY/UtGbPPffM5ZdfnmHDhtWpFbAqG2ywQb74xS9Wzj/77LN529veluuvv361Z3/zm9/MxIkTU1b8XWDAgAH5r//6r9Wey5pv7733ztFHH10539XVlaOPPjrt7e3p6urqlQ4//OEPs//+++eFF16ovGb77bfPJz7xiV6Zv6z11lsvX/7yl2ta89WvfjUHHnhgHn300dWaPWPGjLS1teXkk09eYWbIkCGrNWN1bLjhhrngggtS1PD7+IUXXpjtt98+v/rVr+rY7J9NmzYtJ5xwQjbaaKMce+yxufPOO3tt76eeeiqnnXZaNtlkk7znPe/JFVdckcWLF/fa/ivy4osv5vDDD8+FF15Yec3EiRPr2Aj6j6ZGFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWTEO22Sajjzuu9oVFkdaOjrS0Tej1TvXQ0jYhrR0dSVHUvHb0ccdlyDbb1KEV9L4vfelLKcuypjW///3vs+6666Yoin51vP/976/PiwT91HHHHZddd921cv7pp5/Ovvvum1NPPTXz58+ved5jjz2W//t//29OPPHEdHd3V173iU98IuPHj695Hmunr3/963nta19bOV+WZb785S9nl112yQ033NDjuQ888EAmTJiQD3zgAzV9/Q8aNCjnn39+mpubezx7ZY499tgceuihNa357W9/m6233jonn3xyHnvssZrWPvXUUznttNMybty4TJkyZYW5ddZZJyeddFJNe/e2gw46KJ/61KdqWvPwww/nHe94R/bcc89cdtll6erq6vVeXV1dufHGG3PKKadk3Lhx+T//5//krLPOyuzZs3t91lKLFi3Kz372sxxyyCEZO3ZsjjvuuPzqV7/q0Xv5ynR3d+dHP/pRdtxxx/z0pz+tvO7AAw/MDjvs0KtdoL+qz08DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4FVhzEcmJUme/va3qy0oirR2dKSlbUL9StXB0r6d7e1JWVZaM/r44//++gBAPQ0YMCA/+clPsuOOO+bZZ5+ttKarqyunnXZafvCDH+SEE07Ie9/73owdO3ala26//fZccMEFOffcc7NgwYKaOu6+++750pe+VNMa1m6jRo3KpZdemr322isLFy6svO62227Lnnvumb333jsf/OAHc9BBB6WlpWWlaxYuXJipU6fmvPPOy+TJk7No0aKa+5599tl505veVPO6Wpx33nnZcccd8/jjj1deM3/+/Jxxxhk588wzs/fee+eAAw7IzjvvnHHjxmXUqFEZNmxY5s+fn+eeey733Xdf/vSnP+U3v/lNrr322kqvQ0dHR0aMGLE6t9UrvvSlL+WJJ57IRRddVNO6G264ITfccENaW1vT1taWgw8+OLvttlvWW2+9mjvMnDkzd955Z26++ebcfPPN+f3vf5/Zs2fXvE9vmTVrVs4555ycc845GTp0aHbbbbfsscce2X333bPDDjtkww03rGm/rq6u3HLLLfnlL3+ZSy+9NPfff39N6wcOHJhvfvObNa2BNVlzowsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa7YxH5mUJHn6299eebAo0trRkZa2CfUvVQdLe3e2tydludLs6OOP//vrAgB94XWve10uvvjivPOd70x3d3fldU888UROOumknHzyydlmm23ypje9KRtttFFaWlqyaNGizJ49O/fdd1+mTZuWxx9/vEfdxowZk5/85Cdpbm7u0XrWXm9+85tzzjnn5AMf+EDNa6dOnZqpU6dmwIABGT9+fN7whjdkk002yfDhwzNgwIDMnTs3nZ2dufvuuzNt2rTMmzevxz0/9KEPZeLEiT1eX9Xo0aNz+eWXZ88998ycOXNqWtvV1ZVrr7021157ba/1OfjggzNp0qRcdNFFvbZnTxVFkfPOOy/PP/98fvGLX9S8vrOzM9/5znfyne98J0my6aabZquttsrGG2+c17zmNRk2bFiGDBmSrq6uLFy4MPPnz88zzzyTGTNmpLOzM/fee29mz57dy3fV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77nnniq2aZ577rkne+21V6ZNm1bxmu9+97v5y1/+ko4dOzZr5rrrrpuHH344q6++esVrHnvsseyyyy6ZOHFis2YCAMAXReWfUGhNkyvILFv1FtWxUpJyHueL2effat06AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVMOoEe/lvuteqnWNVnHftS9m1Ij3al0DPrdWXnnlbL/99hXnH3vssSq2aboHHngge+65Z6ZOnVpRviiKnHnmmTn//PNTV1e3ULOXX375DB8+PFtssUXFax5++OHstttumTRp0kLNBgCAz7OFe6dOtVTy15kVqt6ihRVF0SHJqguIvdEaXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKiece9NybArn0/KWjdpJWUy7MrnM+69KbVuAp9b++yzT8XZUaNGVbFJ0zz00EPZbbfdMnny5Iry7du3z1VXXZUTTjihxTosueSSufvuu/PlL3+54jXDhw/PHnvskSlT/FwDAIB5qa91AebptQoyGyS5sdpFWtgG+ddrrkxSzCfzequ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoMU1NpYZeuXzmTWzsdZVWtWsmY0ZdtXz+fIPN0hdXVHrOvC5s9VWW1Wcff3119PY2Ji6uroqNlqwRx55JLvuumsmTZpUUb5bt27529/+lkGDBrV4l44dO+Zvf/tbvvvd7+bCCy+saM19992XPffcM7fccks6derU4p2AhfPxxx9nyJAhefLJJ/Pss89m1KhRGTduXCZMmJCpU6emY8eO6dy5c3r37p0VVlghAwcOzOabb54tt9wyvXr1qnX9FtPY2Ji33347r732WsaOHZvJkydnypQpaWhoSJcuXdK5c+f06NEjK6ywQvr375/27dvXunKL+vDDDzNkyJA89thjef755zNq1KiMHz8+EydOTENDQ7p165Zu3bplqaWWymqrrZY111wz66+/frbddtsv7M/2cePG5dVXX83bb7+dSZMmZcqUKZk6dWoWW2yxdOnSJV27ds3yyy+fFVdcMYsvvnit67aIhoaGvPHGGxkzZkzGjh2bcePGZfr06Zk+fXrq6+vTuXPnTxw9evRI//7906NHj1pXhzatvtYF+L/Ksny3KIqpSTomKZPM6y80m7duqxaxSwWZp6reAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKp5atibeffV8bWuURNjXhmfp4a9mfV2XL7WVeBzZ5VVVklRFCnLcoHZhoaGTJ48Od26dWuFZvM2YsSI7LzzzpkwYUJF+WWWWSa33XZb1l9//ap1qqurywUXXJBll102J510UkVrhg0blr333js33XRTOnbsWLVu8Hl17733Zrvttltgbptttsm99967wNy0adNy1VVX5brrrssDDzyQWbNmzTc7efLkTJ48OWPHjs0zzzyTJDnnnHNSV1eXLbfcMgceeGAOOuigdOrUqeL7aQvGjx+fO++8M8OHD8/w4cPz7LPPZsaMGRWtraury0orrZQtttgiW265ZXbaaacst9xyVW7c8qZOnZrrrrsuF198cR555JE0NjbON/vRRx/lo48+yujRozNy5Mj/Pd+5c+fsuOOO+frXv57/+I//SLt27VqjequbNm1a7rvvvjz44IN58MEHM3LkyIwbN67i9b169crmm2+eLbbYIrvsskvWWmut6pVtQaNGjcrQoUPz0EMP5fHHH8/LL79c8f+TuXXv3j39+/fPgAEDMnDgwGyyySbZdNNNF8n/N1AN9bUuwHw9l2TDJJ/+9FgmKZJsVRRF17IsJ7V6s+b7cgWZx6pdAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgOoY996U/OPGV2tdo6b+ceOrGbB2zyzRu3Otq8DnSseOHdOjR4989NFHFeUnTZqUbt26VbnVvP3zn//MTjvtlPHjx1eUX3XVVXPHHXdkwIAB1S0224knnph+/frlsMMOy8yZMxeYHzJkSP7jP/4jf//739OhQ4dWaAh82pQpU/Lb3/42559/ft5///2F2quxsTH3339/7r///vy///f/csIJJ+TYY49NfX19C7VteY2NjRk8eHCuvvrq3H777Zk+fXqz9xk1alRGjRqVK664IkVRZMstt8yBBx6Yb3zjG+nSpUsLN29Z06dPz/nnn58zzzyz4t+H8zNlypTcdNNNuemmm7LSSivl+OOPz+GHH566uroWals7ZVnm9ttvz7XXXpsbb7wxEydObPZe77//fgYPHpzBgwfn+OOPz1prrZWvfe1rOfLII9OjR48WbL3w3nvvvVxyySW59tpr8+yzz7bInhMmTMjTTz+dp59++hPn+/Tpk0033TS77LJL9tlnnyy99NItMg8WNYv+T8zPrwfnca6Y63H7JPu3UpeFVhTFRknWTlLmk/dRzvX4vbIs32rVYgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALSIxsYyQ698Pg0zG2tdpaYaZjZm2FXPp7GxrHUV+Nzp3LlzxdmyrM3/waeeeiqDBg3Kxx9/XFF+s802y4MPPpgBAwZUt9inHHTQQbn55pvTtWvXivK333579ttvv8yYMaPKzYBPu+uuu7LWWmvl5JNPzvvvv9+ie7///vv54Q9/mI022ihPPfVUi+7dEmbNmpXLL788q6++evbdd98MHjw406dPb7H9y7LMAw88kKOPPjoDBgzIaaedlgkTJrTY/i1p6NChWWONNfLjH/84H330UYvu/corr+Soo47K5ptvnmeffbZF925NM2fOzOWXX5411lgju+++e/70pz9l4sSJLTrjmWeeyU9/+tP0798/P/nJTzJu3LgW3b853n777RxxxBFZbrnlcvLJJ7fKv+GYMWPy97//PUceeWT69OmTHXfcMX/4wx8yadKkqs+GtqSu1gWYrwcXcL1I8p3WKNJCjv2Ma0WSMsnQVuoCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAC3v6nrfy7qvja12jTRjzyvg8fc9bta4BnzsTJ06sONu1a9cqNpm3Z599NjvuuGM+/PDDivJ77bVXhg4dmqWWWqrKzeZt5513zr333pvevXtXlL/lllvyn//5n5k5c2aVmwFJ0tDQkO9973vZeeed89prr1V11pNPPpnNN988f//736s6pykee+yxfOlLX8qhhx6al156qerzPvjgg5x88slZffXV87e//a3q8yrV0NCQk046KTvttFNeffXVqs565JFHssEGG+TKK6+s6pxqGDJkSNZcc80ceuiheeGFF6o+b+LEiTnrrLOy2mqr5brrrqv6vHkpyzLnnXdeBg4cmIsvvrhmv58bGhoydOjQHHXUURkxYkRNOkCt1NW6APM1LMms2Y/Luc4Xc32/flEUe7dqq2YoimL1JAfmk/cxLze2Qh0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABa2PQpM/PoLa/Vukab8ugtr2X6lJm1rgGfGzNnzsyECRMqyrZr1y5du3atcqNPev7557PDDjtk7NixFeWPPPLI3HDDDenUqVOVm322DTfcMA899FBWWWWVivKDBw/OgQcemFmzZlW5GXyxjR8/PrvvvnvOP//8Vps5efLk7Lfffrnuuutabea8NDY25qSTTsqmm26aJ554otXnv/POO9lvv/2y7777ZuLEia0+f25Tp07NPvvsk9NPPz2NjY2tMnPGjBn55je/mV/+8petMm9hjR8/PgceeGB22mmnjBo1qtXnv/feeznggANy4IEHZsqUKa02d/z48dl1113z/e9/v1XnAp9UV+sCzFtZlh8mGZakmF9k9rVfF0VR209kC3ZB/v1am/t+yrkeT09ye6s1AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoMW88PC7mTF1Vq1rtCkzps7KCw+/W+sa8Lnx7LPPpizLirIDBgxIXV1dlRv920svvZQddtgh7733XkX5X/ziF/n973+fdu3aVblZZVZcccU89NBD2WSTTSrKX3/99fn617+ehoaGKjeDL6aJEydm0KBBufPOO1t9dmNjYw466KDcfffdrT47ScaPH5899tgjp59+ehobG2vSYY4bbrghm266aUaNGlWT+ZMmTcouu+ySm2++uSbzTznllJx22mk1mV2pp59+Ol/60pdy7bXX1rpKrr322my++eZ58803qz5r7Nix2WKLLWryMwL4pNb7xEFz/GU+54u5Hq+Y5Det0KVZiqI4Nsm2Scp8svf/RmZf+1tZlpNbsRoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtoGws8/R9b9W6Rpv0zP1vpyzLWteAz4URI0ZUnB04cGAVm3zSK6+8ku233z5jxoxZYLa+vj6XXXZZTjnllFZo1jQ9e/bMsGHDsscee1SU//Of/5yDDz44jY2NVW4GXyzTpk3LXnvtlccee6xmHWbOnJmvfe1reffdd1t17kcffZRtttkmt99+e6vO/SzPPfdcNt988zz99NOtOnfWrFnZf//9c//997fq3E875ZRTct1119W0w/zccccd2XTTTTNq1KhaV/lfTz75ZLbddtu8+eabVZsxadKk7LLLLnn22WerNgOoXH2tC/CZrktyVpIlk5RJirmuFXOdO6IoimfKsryg9SvOX1EUOyT5df7Vc0H+u8p1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqIK3Xvw449+fWusabdK496bkrRc/znKrLVnrKrDIu+mmmyrObrzxxlVs8m+vvfZatttuu7z99tsLzHbp0iV//etfs+uuu7ZCs+bp3LlzBg8enKOOOiqXXHLJAvP/8z//k/r6+lx22WWpq6trhYbw+XfYYYfl3nvvrSjbvXv3bLDBBllppZXSt2/fdOnSJe3atcvkyZPz9ttv58UXX8xjjz2WqVOb/j7t/fffz1FHHZXBgwc3eW1zjBs3LoMGDcqTTz7ZKvOa4oMPPsgOO+yQe+65J2uuuWarzPz2t7+dO+64o9nrl1lmmay//vpZddVVs+SSS6Zz586ZMmVKxo0bl5deeilPPPFE3nrrrQXuU5ZlDjnkkKyzzjrN7lINN910U/bff//MmDGj1lX+j1dffTXbbrttHnroofTu3bvF9z/mmGMycuTIFt8XaJ76Whdg/sqynFIUxX8n+VmScn6xJEWS84qimFGW5cWtVvAzFEWxdZIb8q/X2JyOc5tzrkzyaFmWj7RuQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFrCM/e9XesKbdoz972d5VZbstY1YJE2fvz43HXXXRXnt9122+qVmW306NHZbrvt8uabby4w26tXr9xyyy350pe+VPVeC6tdu3a5+OKLs+yyy+bUU09dYP7KK69MfX19Lr744hRF0QoNWVjTp0/PyJEj89hjj+WJJ57Ia6+9ltdffz3jx4/P5MmT09jYmE6dOqVTp07p1q1bll122fTr1y8DBgzIuuuumw033DArrriif+8quOSSS/I///M/n5np06dPvvGNb+QrX/lK1l9//dTV1X1mfsaMGbn99ttzwQUXZMiQIU3qc+ONN2bo0KHZYYcdmrSuqRoaGrLvvvtm5MiRzVrfu3fv7LLLLtluu+2yxhprZMCAAenWrVvatWuXiRMn5t13383zzz+fBx98MLfddltefPHFJs8YO3Zsdt111zz++ONZeumlm9WzUldffXUuvvjiJq9bcsklc+ihh+brX/961l133QXmn3322Vx77bW55JJL8t577803N23atBxyyCE54ogjmtypGu66667st99+mTlzZrPWr7feetlmm22y0UYbZeWVV87yyy+f7t27p1OnTpk5c2YmTpyY0aNH54UXXsjw4cNzyy235O23m/Z559VXX81+++2XYcOGpX379s3qOS933HFHrrzyymatXXXVVbPDDjtktdVWy0orrZQVV1wx3bp1S5cuXdKlS5cURZHp06dnypQp+eCDDzJ27Ni89tprGTVqVJ577rk89thjeeutt1rsXuDzor7WBVig85N8P0n3JGWSud/BznlcJqlL8vuiKFZO8tOyLBtbs+TciqL4apJLknTO/+08LydWvRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtbtLH0/Lak2NrXaNNe+3JDzLp42np2qNjravAIuuPf/xjpk+fXlF2iSWWyGabbVbVPm+99Va23377jB49eoHZlVZaKXfeeWdWWmmlqnZqaT//+c/Tr1+/HHXUUWloaPjM7KWXXpr6+vpcdNFFKYqilRrSVA888ED22muvDBs2LJMnT/7M7MSJEzNx4sS8//77eeWVV/7P9aWWWio777xzdt999+y2225ZYoklqtT6i+P111/PscceO9/rSy21VP7rv/4rhx56aDp06FDxvosttlj23nvv7L333rnrrrty2GGH5c0336x4/YknnphHHnmk4nxznHjiiRk2bFiT162//vr56U9/mn322Sf19fXzzCy55JJZcskls8Yaa2TffffNb37zmwwfPjy/+tWvctNNNzVp3ptvvpmvfvWrueuuu9KuXbsm963Eq6++mu985ztNWtO+ffscd9xxOfnkk9OtW7eK16255pr55S9/mZNPPjlnn312zjzzzEydOnWe2UcffbTi38PV9OKLL+Y///M/M3PmzCat69u3b4488sgccsghWW655eaba9euXTp27Jill146G220Ub7+9a+nLMsMHTo0Z5xxRpNep8OHD89xxx2X//7v/25S1/kpyzInnHBCk9YsvfTS+d73vpevf/3r6d+//wLz9fX16dKlS5Zeeumsvvrq2XrrrT9xfcyYMRk6dGjuvvvu3HLLLfnwww+b1Ac+j+pqXYDPVpblx0lOTvJZn1KKJOXsrz9K8mBRFOu0Qr1PliiKpYqiuCzJ/yTpPLvTvMzpWia5rSzLe1qpIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC3o2eHvpCxr3aJtKxvLPDf8nVrXgEXWjBkzcv7551ec33///dOhQ4cqNkr69euXV155JWVZLvB4+eWX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Jk6cmHfffTcjR47MjTfemP/6r//KPvvskx49eix0h4suuiinnHJKC9zN59txxx2Xoihabd6gQYMqyk2aNClvvfVWi8y88sorK87++Mc/bpHXX6WKosgZZ5xRcf7aa6/NzJkzmz2vLMv8+c9/rii78sorZ9999232rObYcssts+WWW7bqzLn98Y9/rCg3YMCAHH300VVuM28dOnTI97///Yqyf//735s1Y8aMGRXl6uvrm7U/0Hx1tS5A85VleV2SLZI8k2TOu69y9lFLczrM6XRWkh3Lshxfu0oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0lI/HTK51hUXStEkzal0B2rQzzzwzf/rTnyrOd+7cOVdffXXq6+ur2AoWPXV1ddliiy1yxhln5B//+EcmTpyYxx9/PFdddVVOOOGE7LHHHvnSl76UVVddNcsss0w6d+6cdu3apWvXrundu3fWX3/97LXXXjn55JNzww03ZOzYsXnggQdy6KGHpkuXLs3uddppp+WWW25pwTv9fOnWrVv222+/Vp05YMCA9OrVq6Lsiy++uNDzJk2alCFDhlSU7dSpU4488siFntlUgwYNylprrVVR9oMPPsh9993X7FlPPvlk3nrrrYqyRx55ZIqiaPas5jr66KNbfWaSvPPOO7njjjsqyv7oRz+q6XuBgw8+OO3bt19grtL7+bSOHTtWlHvzzTebtT/QfHW1LsDCKcvyiSQbJvllkplJ5vymLWcfrVpnrplFkteTDCrL8qdlWc5q5S4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUybRJM2tdYZE0a0ZjrStAm3X99dfnxBNPbNKa//7v/87AgQOr1AgWPRtuuGF+97vfZcyYMRk+fHh+8pOfZJNNNkm7du0Wat927dplyy23zKWXXprRo0fnhBNOSKdOnZq8T1mWOeigg/L2228vVJ/Pqx122CGdO3du9blrrLFGRbl33nlnoWfde++9mTmzsveRX/nKV7Lkkksu9MzmOProoyvODhkypNlz7rnnnopyRVHkwAMPbPachbHPPvvU5HV5yy23pLFxwe+dO3bsmK997Wut0Gj+llpqqWyxxRYLzI0cOTIffvhhk/fv2bNnRbnbbrutyXsDC6eu1gVYeGVZzirL8v8lGZjkyiSNSYo5l+c6qjL+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1my11Va55ZZb0rlz5yq1AuZnxowZueqqq7Lhhhtmo402yrnnnpt33323qjM//vjjnHzyyVl77bVz7733Nnl9p06dcsEFF7R8MRY522yzTQ455JCK8w0NDTnkkENy4oknpqGhoUU6XH755Rk0aFAmTJhQ8Zq11147P/zhD1tk/tx69OiRM844o0lrzjrrrOy888554403Fmr2u+++m3322ScnnHDCfDMdO3ZcqBkLo3fv3rniiitSFJV/mLjyyiuz9tpr57bbbqtis/9rxIgR+f73v59ll102hx9+eJ555pkW2/u9997Lqaeemv79++crX/lKbr311syaNavF9p+fyZMn56tf/WquvPLKitccccQRVWwEbUddrQswb0VRbJJk4yRl5v+nqDnXiiSnlGX5lbIsP2qlivNVluV1STZL8vqcUxUsO7ZqhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKi5tbbpl52+tWbq29fVuspCqW9fl52+tWbW2nrZWleBFnfaaaelLMsmrXnggQfStWvXFEXRpo5vfvOb1XmSqKkrrriiRV4fp556asUzDznkkBaZee+991bviUny+OOP57jjjsuyyy6bTTbZJKeeemqGDx+eqVOnLvTejY2NefDBB3PEEUekf//+Oe200zJlypRm7fXHP/4xK6200kJ34vPh17/+dZZbbrmK82VZ5owzzsgmm2yS4cOHN3vuK6+8ki9/+cs59NBDm/R/ZLHFFstll12W+vr6Zs/+LIcffnj22muvJq25++67s9pqq+WEE07Im2++2aS17733Xk499dQMHDgwgwcPnm+uS5cuOf7445u0d0vbdddd85Of/KRJa15//fXsvvvu2WqrrXLTTTeloaGhxXs1NDTkwQcfzEknnZSBAwfmS1/6Us4777yMGzeuxWfNMXPmzPz1r3/NHnvskb59++bb3/52brvtthb5eT+3xsbGXHPNNVl//fXz5z//ueJ1O++8c9ZZZ50W7QJtVXV+G9ASjl7A9TJJMfvrj8qy/G31K1WuLMvniqLYLsl9SZbPv/v+n+js8/sURdGrLMv3W7EmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArWiVjXpn6eW6ZeiVz+fdV8fXuk6T9Vlp8Wx/0OpZonfnWlcBgHlqbGzMo48+mkcffTQ///nPU19fn3XWWSdrrbVWVl111ayyyipZZpll0rt37yy11FLp2LFjOnTokKIoMm3atEyePDnvvPNO3nzzzTz99NMZOXJk7rnnnnz00UcL3e3YY4/N17/+9Ra4Sz4vllxyyVx//fXZeuutM3369IrXPf7449lqq62yzTbb5Mgjj8yuu+6aJZZY4jPXTJ8+Pffdd18uvfTS/P3vf8/MmTOb3Pd3v/tdNtpooyava4pLL70066+/ft56662K10ydOjVnn312zjnnnGyzzTbZaaedsuGGG2bgwIFZcskl07lz50ydOjUff/xxRo0alX/+85+56667MmzYsIqeh9NPPz3du3dfmNtqEaeddlrefvvtXHXVVU1aN3z48AwfPjx9+vTJPvvsk9122y2bb755evTo0eQO77//fp555pn84x//yD/+8Y888MADGTduXJP3aSljx47NRRddlIsuuiidOnXK5ptvni233DJbbLFF1llnnfTu3btJ+zU0NOSRRx7JzTffnOuvvz4vv/xyk9a3b98+v/3tb5u0BhZl9bUuwP9VFEW7JHsnKecTKZMUs7/+rizLNvlTqyzLN4qi2D3JI0k659+955hzD0nSPv+654tbtSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtaonenbPPjzbIU8PezD9ufDUNMxtrXWmB2rWvy6Z7r5h1tl8udXVFresAQMVmzZqVkSNHZuTIkTXtcdBBB+W3v/1tTTvQNm288ca56KKLcuihhzZ57X333Zf77rsv7dq1y7rrrps11lgj/fv3T7du3dKuXbtMmjQpY8aMyQsvvJARI0ZkypQpze551FFH5Ygjjmj2+kr17Nkzt9xyS7baaqtMnDixSWsbGhoybNiwDBs2rMX67LbbbjnmmGNy1VVXtdiezVUURS699NKMHz8+N954Y5PXjxkzJhdeeGEuvPDCJMmAAQOy6qqrpl+/fllmmWXSuXPndOzYMQ0NDZk+fXqmTp2aDz/8MO+++27GjBmTl156KePGjWvhu2o5U6dOzdChQzN06ND/Pbfkkktm1VVXTd++fdO3b9/06NEjHTt2TIcOHTJ9+vRMmjQpkydPzltvvZUXX3wxo0aNyvTp05vd4Ywzzsjqq6/eErcDi4T6WhdgnjZNsniSMsmn/4Iz51yZ5MkkP2rdak1TluVzRVF8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oKkoK3UBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICmoqzUBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmoqyUhcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgqykpdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgqSgrdQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKairNQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACairJSFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaCrKSl0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCpKCt1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACApqKs1AUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJqKslIXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoKspKXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoKkoK3UBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICmoqzUBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmoqyUhcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgqykpdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgqSgrdQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKairNQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACairJSFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaCrKSl0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCpKCt1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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/uuxTltuHdvvvV/s2n9wtOvUeX3rQpP38ccfR01NTalrrNOVV14Z48aNi4ceeig6depU6jpFd9VVV8U555xTtP2mT58e/fr1izFjxsS2225btH3zNn/+/EjTtNQ11qq2tjZ+9rOfxXPPPRd33nlntGrVqtSV/mXFihVx0kknxd13312S+XV1dXH++efHiy++GLfddls0b968JD0AAPJSUeoCrNWRq3yerPJ5usrH64s5MEmS5hFx5RrmFmVE/Lt/54gYGhGHF3kGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATVRaVxdTXnslXn50WLw7/p+RpnW5zZo3dUrMmzolnr/v79G9996x26Avxta77BpJWVluM4HieP755+MLX/hCPProo7HFFluUuk7RXHvttXHmmWcWfd+pU6fGQQcdFGPGjIltttmm6Ptv6IYNGxaDBw+OYcOGRWVlZanrRHV1dRx77LHx4IMPlrpK3H333VFdXR133313VFRUlLoOAEDR+M9B47bvah5LV/m8NiLuKfLM70bENivnJOvIpus41iRZZf9DkyQ5ev0qAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0NQtX7I4XnjogbjxB2fE3Rf+LN4Z91ykaV2DzE7r6uKdcWPj7gt/Fjf+4Ix44aEHYvmSxQ0yG6i/N954IwYPHhwff/xxqasUxQ033BBDhgyJNE1z2X/KlClx0EEHxZQpU3LZf0P31FNPxRFHHBHV1dUl7VFXVxcnnXRSPPjggyXtsaoHHnggTjrppNye2wAApVBR6gKsXpIkbSJi54hY3d1nsvLxMWmazi/izGYR8cM1zPy0TzLJemTSled+myTJvak7bQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA1OXV1tvDR8WIy9+/aoWrqk1HViwYxpMfrm62Ls3bfHPsecGLsfcliUlZWXuhY0ekmSRPfu3WPPPfeMPfbYI7bddtvYZpttYvPNN482bdpEmzZtoqamJpYsWRLTp0+Pd999N1588cUYOXJkPPfcc1FbW1uvua+//nocffTRMWLEiCgvb7q/qzfffHN861vfijRNC1q3ySabxOzZszPn33///ejXr1+MGTMmtthii0JrNhllZWWxww47xJ577hm77757dOvWLbbZZpvo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D1dEx823KHUV+Mzp1KlTzJ8/P1N2+vTpsdlmm+XcaPVeeuml6N+/fyxYsCBTvmfPnvHII4/ENttsk2+xVdx8881x2mmnRXV1dab8IYccEvfdd1+0aNEi52ZNw6JFi6KysjJTtnnz5lFVVVX0DocffngMGzYsU3bUqFFx4IEHFr3D2jz++OMxcODATNnDDz88HnzwwZwblcb7778f3bp1W2eua9eu8f7776/xfE1NTQwdOjT++Mc/rjVXqMrKyjjrrLPi/PPPj9atWxdt3zw89thjcdNNN8UDDzwQixcvLtq+u+++e5xwwgnxzW9+Mzp27Fi0ffNQV1cXN954Y/ziF7+IadOmFW3fTTfdNM4555w455xz1vg6P3r06DjooIPWuVffvn1j9OjRRetWX0899VTcdtttcc8998TcuXOLtu+2224bJ5xwQnznO9+JzTffvGj7FsPHH38cN910U9x6660xfvz4SNM0t1mdOnWKvffeOwYOHBhHH310bLXVVrnNakgbwv8zKisrY9GiRWuLLErTNNtNDlFW6gKsVpZ3OG3Wd0iSJElE9ImIdb3aPrO+s1axZB3nvVsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABogurqamPE1ZdGTfWKUlcpqZrqFTHimsuirq621FXgM6d169aZs2ma5thkzV555ZUYOHBgLFiwIFN+n332iWeeeSa22WabfIt9yqmnnhr/+Mc/om3btpnyw4cPj2OOOSZWrNiwX+M/UernYnV1dYwePTpTtnXr1rHvvvsWvcO67L///tGyZctM2dGjR0d1dXXOjZqu8ePHx+c///k488wz4/333y/q3gsXLowLL7wwdtlll8zPqYZ27733Ru/evWPQoEFx2223xeLFi4u6/0svvRQ//vGPo2vXrvE///M/MWvWrKLuXywvvfRS7LHHHnHaaafFtGnTirr3zJkz4yc/+Unstttu8cwzzxR174ZUV1cX9957b+y1117xhS98IYYOHRpz584t6oz33nsvLrzwwth2221jyJAhRf9Z1MeCBQvi3HPPjS222CLOPvvsGDduXO73QfPmzYuHH344vv/970fXrl1j3333jT/96U9F/35DY1dW6gKsVlWGTPa7+TXbJSIqV36erCVXzL+sS9ZxvkURZwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBAXho+LKZPmljqGo3C9LfeiJeGDyt1DfjMWbRoUeZs27Ztc2yyeq+//noMGDAg5s2blyn/pS99KUaOHBmdOnXKudnqDR48OEaPHh1dunTJlB82bFgcd9xxUV1dnXOzxq/Uz8Vx48bF4sWLM2UPOOCAaN68edE7rEvLli1jv/32y5RdtGhRjB8/PudGTdPvf//76NOnT7z88su5zpk8eXIMHDgwrrrqqlznFOLtt9+Ofv36xdFHHx0vvvhi7vMWL14cf/zjH6Nnz54xdOjQSNM095lZXX755bHPPvvEhAkTcp3z5ptvxgEHHBAXXXRRrnPy8MILL8Tee+8dRx99dIwbNy73eVVVVTF06NDYaaed4sorr4y6urrcZ67O7bffHtttt1384Q9/iCVLlpSkQ5qmMXbs2PjBD34Qw4Z5D8SGpazUBVitpRkyWxRhzoFreHzVO4j5aZq+VYRZn1jXc662iLMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoAMuXLI6xd99e6hqNyti7b4/lSxaXugZ8ZlRXV8fChQszZcvLy6Nt27Y5N/pPEydOjP79+8ecOXMy5U8//fS49957o1WrVjk3W7vevXvHs88+G9tvv32m/P333x8nnnhi1NTU5NyscZs3b17m7EYbbVT0+ePHj8+c7dOnT9Hn5zH7hRdeyLFJ07NixYr42te+Fj/5yU+itra2QWbW1NTEd7/73fjDH/7QIPPW5sorr4zPfe5zMWrUqAaf/fHHH8eQIUOib9++MXPmzAafv6q6uroYMmRInH322VFVVdUgM9M0jZ/+9KcxZMiQBnvurY8VK1bEOeecE3vttVdBr43FsnDhwjjrrLNi4MCBBf1tWF8rVqyIr371q3HSSSfF/PnzG2wu8J/KSl2A1cryjmy7Iszpt5ZzSUSkEfFsEeasal3vHv0XCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoIl5ffTIqFq6pNQ1GpWqpUvijTEjS10DPjNef/31SNM0U3abbbaJsrKynBv926RJk6J///4xa9asTPlf//rXcc0110R5eXnOzbLZdttt49lnn4299947U/7uu++Ok08+OWpra3Nu1ni9+uqrmbPbbrtt0ee/+OKLmbO9e/cu+vys9txzz8zZQq7ps66mpiaOPvrouOmmm0oy/9xzz42//vWvJZldVVUV3/jGN+Kss86KqqqqknT4xFNPPRV77rln/POf/yzJ/Jqamjj++ONj6NChJZk/dOjQGDJkSElmZzVlypTYf//947LLLou6urqSdnniiSdizz33LOjvQ30tXbo0Bg8eHDfffHPus4C1a7h3HBRidoZM9/UZkCRJRUT0i4h1vUN9Zn3mrEabdZxfXOR5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5Citq4sJjz1U6hqN0suPPhxpmpa6BnwmjB8/PnO2R48eOTb5T++++27069cvZsyYsc5sRUVF3HDDDXHBBRc0QLPCdO7cOZ544ok47LDDMuX//ve/x1e/+tWoq6vLuVnjVOrn44svvpg5u8ceexR9flZ77rln5mwh1/RZlqZpfPWrX41hw4aVtMd3vvOdeP311xt05vLly+Pwww+PG2+8sUHnrs20adPiwAMPjCeeeKLBZ59xxhlx1113NfjcVV1//fXx+9//vqQd1uTFF1+M3r17x7hx40pd5V/ef//9OOigg+KVV17JbUZtbW0cc8wxMXr06NxmANlVlLoAqzU5Q2bf9ZxxYES0i4g0IpK15J5ezzmfttkaHv+kw6IizwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBHU157JRbMmF7qGo3SghnTYsprE6Lr53YrdRVo8h588MHM2b322ivHJv82efLkOOigg2LatGnrzLZp0ybuuuuuOOSQQxqgWf20bt067r///hgyZEhcf/3168zfdtttUVFRETfccEOUlZU1QMPGo5TPx5qampg4cWKmbLt27WKLLbYo6vxCbLnlltG2bdtYvHjxOrNvvPFG1NTUREVFRQM0a7wuuOCCuP322zNlW7VqFXvssUd07949ttpqq2jTpk00b948li5dGjNnzoy33347nn/++Vi4cGHBPZYtWxannnpqjBs3rkF+v6uqquLII4+Mxx57LPdZhVq2bFkcfvjh8fDDD0ffvn0bZOZFF12U6XV4TTp27Bh77LFH7LDDDtG5c+do27ZtLF++PD7++ON455134pVXXol33303017nnXde9O7du1H9bj7//PNx8MEHx0cffVTqKv9l3rx50a9fv3jqqadixx13LPr+v/nNb2L48OFF3xeon8bzysi/pGm6NEmSaRGxeUSkEZGsenrl1/snSdIqTdNl9RxzzJrGr/L5iogYV8/912TztZxLI2JRkecBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQo5cffajUFRq1CY8+HF0/t1upa0CT9vHHH8ejjz6aOX/ggQfmV2alDz74IA466KD48MMP15ndZJNNYtiwYfH5z38+917rq7y8PK677rrYYost4le/+tU68zfddFNUVFTEddddF0mSNEDD0nvrrbfi1VdfzZwv9vNxypQpUVNTkym73XbbFXV2fXTv3j0mTJiwzlx1dXV8+OGH0a1btwZo1Tg99thjcdFFF601s9FGG8XJJ58cX/nKV6JPnz7RrFmzteZra2tj1KhRMXTo0LjnnnsiTdPMfV588cW44YYb4rTTTsu8pr5OP/30eOSRR+q1dqONNopBgwZF//79Y5dddoltt902Kisro3nz5rFo0aKYM2dOvPnmm/H888/H8OHD46WXXip4xtKlS+NLX/pSjBs3Lnr06FGvnlmNGTMmLrjggoLXtWnTJk466aT42te+FnvvvXeUlZWtNf/ee+/F3XffHddcc01Mnjx5jbk0TeNb3/pWXHHFFQV3ysMrr7wSAwcOjEWLFtVrfY8ePaJ///6x5557Ro8ePWLrrbeODh06RKtWraK2tjYWL14cH374YUyaNCmeeeaZGD58eLz99tsFzZg3b14cccQR8c9//jPat29fr56r89prr8Vvf/vbeq3t2rVrDBgwIHbaaafYbrvtonv37tG+ffto06ZNtG7dOioqKqKqqiqWLVsWc+fOjTlz5sSUKVPi7bffjokTJ8b48ePj3XffLdq1wGdFUsgfVhpOkiQPR8TBEZFGxKrvUj75Oo2Io9M0vb8eezePiBkRsdEnD61h/2fTND2g0P3XMfudiPjkbvmTuavOfDBN0yOLORPgsyRJkoUR0W5N59u1axcLFy5swEYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8J9qa2tj0qRJmfM9evSI8vLyHBuRp0Xz5sZ13/1GpGldqas0WklZWXzryhuiXafOpa4CTdbFF18cP/7xjzNlN9poo5g5c2a0aNEitz5Tp06Nvn37xnvvvbfObPfu3WPEiBHRvXv33Prk5frrr48hQ4ZEbW3tOrOnn356XH311ZEkSQM0K63vfve7cdVVV2XK7rDDDjFx4sSizh85cmQMGDAgU/YrX/lK/P3vfy/q/EIde+yxcffdd2fKjhw5Mvr165dzo4b1/vvvR7du3daZ69ixY1RUVMTs2bNXe75NmzZx/vnnx1lnnRXt2rWrV5fx48fH17/+9Xjttdcyr9liiy1i8uTJ0axZs3rNzOLqq6+O73znOwWv6969e5x//vlxwgknRKtWrTKve+WVV+L//u//4pZbbom6usLuYXfeeed47rnnom3btoXWzWTBggXRq1ev+PDDDzOvSZIkvvnNb8ZFF10UG2+8ccEza2tr45prrokLLrggFixYsMZcr169YsKECevcr2/fvjF69OiCe2Qxe/bs2GuvveKDDz4oaF2HDh3im9/8Zpx22mnRs2fPguc+//zz8Yc//CHuu+++SNM087ovfvGLMWzYsILnrcmXvvSl+Mc//pE5365duzj99NPrfd2fNn/+/Bg1alQ8/vjj8Y9//COmTZv2X5kbb7wxvva1r633rFLZEP6fUVlZGYsWLVpbZFGappUN1aepKyt1AdZobIbMj+q59wkR0WHl52t79/NYPfdfrSRJWkbENuuIvVPMmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOTnlZEjIk3rSl2jUUvr6uLVJ0aUugY0WStWrIjLL788c/7YY4+NFi1a5NgoYsstt4x333030jRd5/HOO+9E9+7dc+2Tl9NOOy1qamoyXec111wTSZKUunLu5s6dG3/9618z50855ZSid5g8eXLm7NZbb130+YUqpEMh1/ZZM3/+/Jg9e/Zqz+27777x+uuvx/nnnx/t2rWr94w999wzxo4dGwcffHDmNdOmTYu77rqr3jPX5fXXX49zzjmnoDUVFRXxm9/8Jt544434xje+Ea1atSpo/a677hp//etf45///GfsvPPOBa19/fXX4+yzzy5oTSHOPffc+PDDDzPnO3bsGMOGDYvrrrsuNt5443rNLC8vj+9+97sxYcKE2GeffdaYmzBhQr32L5ba2to4+uij44MPPsi8plmzZnHeeefF5MmT4+KLL46ePXvWa/bee+8d99xzTzz55JMF7fHQQw8V9Ddjbd55550YNmxY5vypp54aH3zwwXpd96d17Ngxjj766Lj66qvjww8/jKeffjpOP/309XpdgqaurNQFWKOn1vB4EhHpyo/7JEkyqJBNkyQpj4jzVu6xLg8XsncGO8a/n3Nreuf1bpFnAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJO3n3+m1BWahEnP+T5BfV166aUxderUzPmvf/3rObZhQ/fzn/88li5dmilbUVERJ598ctE7TJ48OXN20003Lfr8QhXSoZBr21CceuqpMXr06OjatWtR9mvbtm3ce++90adPn8xrhg4dWpTZn5amaZx++umxYsWKzGs6d+4co0ePjp/97GfRvHnz9Zrfu3fv+Oc//xnHH398QetuuOGGGD169HrNXp2XX345/vKXv2TOb7rppvHUU0/FoYceWpT5W221VTzxxBNF26/YLr744nj66acz53fccccYN25cXHTRRdG+ffuidNh///1j/PjxceSRR2Ze88Mf/jBmz5693rNvvvnmSNM0U/aSSy6Jm266KTp06LDec9ckSZLYb7/94pprronp06fHn//85+jWrVtu86CxKit1AdboqYhYsPLz1b16phGRRMRNSZIUcsd8XkT0WPl5spo9P/FhmqbjC9g3iyx3b+8WeSYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5qFq6JOZNnVLqGk3CvKlTomrpklLXgCZn1qxZceGFF2bOf+ELX4h99tknx0ZsyF577bW49tprM+dPPPHE2HrrrYveY9asWZmzm266adHnF6qQDrNnz86xSdNzyimnxI033hjNmjUr6r6tWrWKO+64I9q1a5cp//TTT8eMGTOK2iEi4oYbbohnnnkmc75Lly4xevTo2G+//YrWoXXr1nHbbbfFN77xjYLWDRkyJGpqaorWIyLihz/8YdTV1WXKVlZWxsiRI2OnnXYqaoeWLVvGfffdF3379i3qvutr4sSJ8ctf/jJzvn///jF27Njo1atX0bu0bds27rrrrjj55JMz5efPnx+//e1v13vuiBEjMuW+/vWvxw9+8IP1nleItm3bxne+8514++2347DDDmvQ2VBqZaUuwOqlaVobEQ9GRLKa0588lkZEl4h4LEmSHuvaM0mSb0TEr1auW2Ns5fk7CyqcTZY7oHdzmAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECRzXrv3VJXaFJmT/b9gkINGTIkFi5cmDl/wQUX5NiGDVlNTU18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0r9//27PwYrhbW97Ww466KCa63/3u9/la1/7Wt3yjBs3LoccckgWLlxYU31VVfnqV7/abfP79euXr3zlKzXX33jjjTn++ONTSum2DK2uvfbafPKTn+z2vl21/vrr5+STT665/qc//WlOOOGEmv8se8Ktt96aww47rMvnR44cmW9961uZOnVqN6bqvEWLFuU73/lOTbX9+vXLO97xjjongsZranQAlqyqqg8k2T1JSdLevwxKm71FSU5J8v9KKTf0WMgalFKmJPlz2n+GtNzfqccCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0CO2O+j92enwoxodoy52OvyobHfQ+xsdA7rVOeeck8985jOdOvPud787V199dfr161enVLxRfeELX8jZZ5/dqTOHH354zj///DQ1NdUp1fLnM5/5TDbYYIOa6z/60Y/m5ptv7rb5119/fT72sY/VXL/RRht1+vsMrz/f/e5306dPn5rrTz/99HzrW9/q9hyPP/54dt1110yaNKnmMx//+MczYsSIbs1xwgknZNiwYTXXn3vuuTnqqKMyd+7cbstw0UUX5eCDD878+fO7rWd3OPXUU7PpppvWXH/OOefkPe95TyZOnFjHVEs2f/78/O///m923HHH7LrrrvnDH/7Q5V4vv/xyTj311AwdOjSf/exn8+STT3Zj0tp94xvfyC233FJT7W677eZ9IW8Ib5x3myuuU5ewV1o+VkmmJBlZSvl2KWVh3VN1zd0d3G99jrdVVVX1VBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6xnYHvT+7H/MfSVU1Okr3qKrscex/ZLuD3t/oJNCtzj333Jx44omdOrPzzjvn2muvTf/+/euUijeqU045Jd/73vc6deYDH/hALrzwwvTq1atOqZZPffv2zVlnnVVz/dy5c3PggQfm8ssvX+bZl156aQ4++ODMmzev5jNnnXVW+vTps8yzWbFtsskm+cpXvtKpM6eeemo++tGPZtasWd2S4brrrss73/nOjB8/vuYza6yxRs4888xumd/WSiutlB//+MedOnPhhRdmxx13zCOPPLJMs6dNm5ZPfOITOeKIIzJ//vx2a/r27btMM5ZF//79c8kll3Tq+8YNN9yQESNG5MILL8yiRYvqmO61/va3v+WUU07Jeuutl8MOOyx33313t/WeOnVqfvCDH2STTTbJPvvsk8suuyxz5szptv4dWbBgQU466aR885vfrPnMxz72sTomguVHU6MD0LGqqg5IsnmSkmTx30aV1rIkU5PsXUr5Yw/G64p72rnX9rn6JhneQ1kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoQVvttW/e8+kvpLl3n0ZHWSbNvfvkPZ/+Qrbcc99GR4Fud8YZZ6SU0qkzd9xxRwYOHJiqqpar9ZGPfKQ+nyR6zBlnnNHpM5dddlmam5sb/vW3+Pr617/e/Z+gxey///55//vfX3P97Nmz8/73vz+f/OQnM3ny5E7Pe+WVV/KJT3wihx9+eObMmVPzuQ984APZb7/9Oj2P16cvfelL2XrrrTt15vzzz89WW22Va665pstzX3rppRxzzDHZf//988orr9R8rqqq/OxnP8ub3vSmLs9ekr322iuf+tSnOnXmwQcfzFZbbZWPf/zjefzxxzt1durUqfnRj36UTTbZJD//+c87rGtqasppp53Wqd7dbauttspZZ53VqTMvv/xyjjzyyGy11Vb5n//5n059r6pVKSUPPvhgvvWtb2XrrbfOiBEjcsYZZ+TFF1/s9lltZ95www059NBDs/rqq+eoo47K5ZdfnmnTpnX7rN///vfZfvvtO/W5HzFiRN7znvd0exZYHjU3OgBLdEwH91v/xVslWZjk8FLK/T0TaZk8WEPN25L8vd5BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6HnDd9g5bxm6YW787x/l+bF/a3ScTltr+IiMPP7TWXnNtRsdBQD+zXnnnZcHH3wwTz75ZM1nfvrTn+aSSy7JiSeemCOOOCIbb7zxEusff/zxjBo1Kuecc06mTp3aqXybbLJJzj333E6d4fWtd+/eueKKK/L2t789kyZNqvncuHHjcsABB2SbbbbJ8ccfn/333z+rr776Es8sXLgwd999d37961/n4osvzqxZszqd90tf+lIOPPDATp/rjP/8z//MbbfdloceeqjmMwsXLswvfvGLnHvuudluu+0ycuTIvOMd78imm26aVVddNQMGDMjcuXMzbdq0PPHEE3nooYfyhz/8ITfddFNNn4dPf/rT2WGHHZblsbrFxz/+8YwfPz6nn356p849/PDD+fCHP5wTTzwxBx10UPbZZ5/ssssuWW211TqdYfLkyXn00Udz77335p577skdd9yRl156qdN9usu0adMyatSojBo1KiuttFK222677LTTTnnnO9+ZrbbaKuuss06n+pVSMmbMmFx77bW54oorOvV12Oqss85KU1NTp8/Biqi50QFoX1VVb06yd5LSUUnL3g9LKTf0VK5l9HSS+Xn1667k1WdY3EY9mggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAetcpaa+fQb5yZv1x/TUZfMioL5s9rdKSlal6pd3Y6/Mhsvc/+aWrq1eg4ANCuwYMH5ze/+U123HHHzJkzp+ZzkydPzje/+c1885vfzCabbJK3v/3tGTp0aN785jenlJIpU6bk6aefzp///Oc89dRTXcrWr1+/XHbZZRk8eHCXzvP6tcEGG+TSSy/Nfvvtl/nz53fq7IMPPpjjjjsuVVVl8803z+abb54NN9wwgwYNSu/evTNjxoxMnDgxf//73/PAAw9kypQpXc6533775Vvf+laXz9eqT58+ueaaa7L99tvn+eef79TZUkruueee3HPPPd2WZ5tttskZZ5yRe++9t9t6LotvfvObeeWVV/LTn/6002cnT56c888/P+eff36SZK211spmm22WddZZJ2uttVYGDBiQvn37ppSSuXPnZs6cOXnllVfy0ksv5cUXX8y4ceMyceLE7n6kbjN//vyMHj06o0eP/te9wYMHZ/jw4Vl77bWz1lprZdVVV03fvn3Tt2/fzJs3LzNnzsyMGTPy4osv5vHHH8/YsWMzc+bMLmc44YQTsscee3TH48AKobnRAejQfkl6JylJqjb3S5vr8Um+1pOhlkUpZWFVVU8k2XQJZRv0VB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAao6mpV7bd76BssPX/y43//aM8P/ZvjY7UobWGj8jI4z+dlddcu9FRAGCptt566/z2t7/NQQcdlHnz5nX6/Lhx4zJu3LhuzdS7d+/89re/zVZbbdWtfXn92HPPPXPppZfm0EMPzYIFCzp9vpSSRx55JI888kgd0iV77LFHLr/88jQ1NdWl/+LWXXfd/P73v88uu+ySqVOn9sjM9qyzzjq55ppr0q9fv4ZlaM8555yTIUOG5Jvf/OYy9Xn++efz/PPPd1Oq5dO0adNy//335/7776/7rF122SXf//736z4Hlic981OBrth5CXtVkpLke6WU2T2Up7v8I6/m78i6PRUEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxlplrbVz6DfOzLuPPC59+g9odJzX6NN/QN595HE59Ovfycprrt3oOABQs3322SeXXXZZmpubGx0lzc3N+c1vfpORI0c2OgrLuYMPPjiXXHJJ+vbt2+gor7H33nvn6quv7vFcW265ZW699dasvvrqPTq31WqrrZbrrrsua621VkPmL803vvGN/PKXv1zuvl7eqHbaaadce+216d27d6OjQI9qanQAOrRTkrLYvbav5ya5oMfSdJ8Xl7BXJXlLTwUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg8ZqaemXb/Q7MsT/5ZXY96risvObaDc2z8pprZ9ejjsuxP/lltt3vwDQ19WpoHgDoigMPPDA33nhjhgwZ0rAMQ4YMyU033ZQDDjigYRlYsRxyyCG5/fbbs/bajX0/2Oqzn/1srrvuuvTr168h87faaquMHj06m222WY/O3WSTTXL33Xdniy226NG5nfXRj340999//3Kf8/Xuwx/+cG6++eYMHDiw0VGgxzU1OgD/rqqq5iTDO9pOUpLcVEqZ3nOpus2EDu6Xlo+Ne+cPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAw/QdMDDb7Htgjv7hz3LIKd/Kxv9vh1RVU4/Mrpqassk7dswhp3wrR//wZ9lm3wPTd8DAHpkNAPWy22675c9//nO22WabHp+97bbb5s9//nN23XXXHp/Niu3//b//lwceeCAHH3xwwzKsscYaueKKK/Jf//Vf6dWrV8NyJMnGG2+cP//5z/noRz/aI/MOPvjg3H333dlwww17ZN6yeutb35r77rsvX//61zNgwIBGx2nX2muvnZNOOqnRMbrdm9/85vzyl7/MhRdemL59+zY6DjREz/zGgs4amqT1p3fVQc2tPROl281Yyv7gHkkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAcqmqqgx921Y58HNfzXHn/Co7HHJ4Vl1nvbrMWnWd9bLDIYfnuJ/8Kgd89isZ+ratUlVVXWYBQCMMHTo09957b37wgx9k8ODBdZ83ePDg/PCHP8y9996boUOH1n0er0+rr756rrjiilx55ZXZYIMNemxuc3NzPvGJT+Rvf/tbDj744B6buzT9+/fPL3/5y9x0001529veVpcZa621Vn7zm9/kiiuuyKqrrlqXGfXSp0+ffO1rX8u4ceNy7LHHpnfv3o2OlAEDBuTQQw/NNddck2effTannHJKl3v95Cc/yUknnZRNNtmkGxN2XXNzc4499tg89thj+ehHP9roONBQzY0OQLtqeefwYN1T1Mfcpez36ZEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALPcGrTokO77/Q9nx/R/K3FkzM+HpJ/PSU0/kxaeeyISnn8jkF56vudfKa66V1TbYOGtsuHFW33DjrLbBRunTf0Ad0wPA8qG5uTknn3xyDj/88Hzve9/LL3/5y0ydOrVbZ7zpTW/KMccck89//vNZY401urU3b1wHHnhg9ttvv1x88cX5z//8zzz66KN1mdOvX7985CMfyRe/+MUMHTq0LjO6w5577pkxY8bk0ksvzU9+8pPcfffdy9xzs802y2c/+9kcccQR6d27dzekbJw111wz5557bs4444z84he/yM9//vP885//7LH5q622Wvbee+/sv//+2W+//dK/f/9u6bvTTjtlp512yg9/+MOMGzcu1157ba677rrcddddmT17drfMqMXKK6+cI488MieeeGI22mijHpsLy7OqlNLoDCymqqoPJLk0SUlStdlqfV2SDC2lLPNPiKqqFi1pTiml17LOWGzeSUl+sNjM1i/CKsnCUspK3TkT4PWkqqppSQZ1tD9o0KBMmzatBxMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwGstXLgwY8eOrbl+2LBh6dWrVx0T8Xo2d9bMvPLPf2TOjOlZMH9eFs6blwUL5qe5eaX06t07zSv1Tt+Bg7LqOuumT/8BjY4LAMuFGTNmZNSoUfntb3+bO+64I/PmzetSn969e2fnnXfO+973vhxxxBEZOHBgNyeF17r//vtzySWX5He/+12eeeaZZerVr1+/7LLLLjnssMNy8MEHZ9CgQd0Tsgc98sgjufrqq3PjjTfmvvvuy5w5c5Z6ZvDgwdliiy0ycuTI7L///tliiy16IGljlFJy77335qqrrsp1112XRx99NIsWLeq2/muvvXa222677LzzznnXu96V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5szJlClT8vzzz2fMmDGv2W9qasq2226b3XffPYcccki23XbbOj3Biue0007L6aefXlPtKquskj/96U/Zcsst65yqsebOnZu//vWvGTNmTMaMGZOHHnoof/3rXzN9+vSaeyxcuDDz58/P9OnTM3HixDz++OP/VjNkyJDstNNOec973pP3vve9WWWVVbrzMRqmlJIHHngg119/fW6++eY8/PDDmTJlSk1n11577Wy99dYZOXJk9t1332ywwQb1DQsAsBxqbnQA2vXYEvZKkirJ3lVVbVlKeaiHMnVJVVVbJhmZV3MvyZKeeWk2Xsr+M8vQGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAN77HHHst1112Xa6+9NnfddVcWLFjQ7TMWLVqU+++/P/fff3/OPPPMjBgxIscee2yOO+64DBw4sNvnrShOP/30nH766TXXT5o0KXvssUduueWWvPWtb61jsp41a9as3HXXXbn99ttz22235d57783cuXPrPvfll1/OlVdemSuvvDLHH3989t1333zqU5/KbrvtVvfZ9fDKK6/kF7/4RX7605/mn//8Z5d6jB8/PuPHj8+1116bJHn729+eT33qUzn00EPTu3fv7owLALDcamp0ANp1awf3qzbXTUl+WP8oy+wH+b/c1RLqbu1K86qqmpJskqQsoeyZrvQGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABg+bZozoLMfW5aZv/tlcx6eGJm/mVCZt7/Ymb+ZUJmPTwxs//2SuY+Ny2L5ixodFRYIT388MM59dRTM3z48Gy++eb5whe+kNtvvz0LFvTM36nHHnssn/nMZzJ06NCcfvrpmT17do/MXZ6ceeaZOe200zp97uWXX87uu++exx57rA6petZzzz2XHXfcMW9+85uz55575vTTT8/tt9+euXPn9niW+fPn56qrrsruu++ebbbZJn/84x97PENXTZ8+PZ/73Oeyzjrr5Ctf+Ur++c9/dlvvP//5zznyyCOz3nrr5dxzz00ppdt6AwAsr5obHYB2/TnJlCRvSlKSVG32qjb3dqmq6nOllP/q8YQ1qKrqM0l2zb8/Q1rutZqa5L4ujtksSZ8OZrR6uou9AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWE4smrMg88bPyPzx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2WTBokbHWbrmprxp7/Uz8J1rpWqqGp0G6ubyyy/P+9///prrhwwZkn322Sd777139tprr7zlLW/p0tyXXnopv/rVr/KjH/0oEyZM6FKPM888M1/84he7dLbRLr744hxxxBFZtKj274dVVeX73/9+jj766Bx00EG57bbbOjVzk002yW233ZY111yzs3F73JgxY7L11lt3uL/55ptn1113zfbbb5/tttsuG2+88TLPnDFjRi6//PKMGjUqt956a0opne6x4YYb5tFHH03fvn2XOU+tRo0alaOOOqpTZwYOHJjPfe5zOfnkkzN48OCazjzxxBM57bTTcumll3bqczNgwIDcf//92WyzzTqVEWi8Cy64IEcfffRS64466qhccMEF9Q8EdfBG+H3G4MGDM3369CWVTC+l1PaGgFRdeZNIz6qqau8k1yZpar21hPLSTk3rvflJxiR5NMnjSZ5LMjHJy0nmJJnXUtunZQ1JslqSdZIMT7J5kq2T9F7CjI6ytd1fmGT/UsoNS3iOJaqq6pNJftzSd/Ecra8fKKX8v67OAFgeVVU1LcmgjvYHDRqUadOm9WAiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHithQsXZuzYsTXXDxs2LL169apjIpY38yfOyuTLx2Xes9MaHaXTeg8dnJUP2SQrvaV/o6NAXVx++eV5//vfv8SagQMH5uCDD85hhx2WPffcM83Nzd02f+bMmTnjjDPyve99LwsWLOjU2T59+mTMmDHZdNNNuy1PT7jsssvywQ9+MAsXLqz5TO/evTNq1KgceuihSZK5c+fmyCOPzGWXXdap2ZtuumluvfXWrL766p0619PGjBmTrbfe+l+vV1111YwcOTL77bdfdt9996y22mp1nX/nnXfm+OOPz8MPP9zps9/5znfypS99qQ6p/t2zzz6bESNGZNasWTWf2WGHHXLZZZdlnXXW6dLMW265JYcffnheeumlms9sueWWeeCBB7z/gxXMBRdckKOPPnqpdUcddVQuuOCC+geCOngj/D5j8ODBmT59+pJKppdSBvdUnhVdU6MDsHSllBuTfDJJ1XprCeVVyyptVuu93knekeQjSb6T5H+S3JTkwSSPJXkiyZMt139JcnNLzXeTfDTJdkn6LGXGkrSeOaGUckMNj95+k6qqkpyY//s8tM2RNveu6OoMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAut+shyZmwtl/ybxnpzU6SpfMe3ZaJpz9l8x6aGKjo0CP23zzzfPjH/8448ePz69//evss88+aW5u7tYZAwYMyLe//e3ccccdWXPNNTt1du7cufnqV7/arXnq7be//W0+9KEPZeHChTWfedOb3pQbb7wxhx566L/u9enTJ5deemlOOumkTs3/+9//nt122y0TJy7/39PWXXfdfPrTn84dd9yRCRMm5KKLLsrhhx+e1VZbre6z3/nOd+bBBx/MN7/5zVRV1amzZ555ZmbMmFGnZK910kknZdasWTXXH3bYYbntttuyzjrrdHnmrrvumgcffDDDhw+v+cxDDz2Uc845p8szAQCWF02NDkBtSim/SPKVJK3v5stSjlSL1bautntdWR31WmL8NtenlVJ+vpT6pflAkmE11F2xjHMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoJjPufj6TLv17yvxFjY6yTMr8RZl06d8z457nGx0FesS73/3u3HjjjXnkkUdywgknZPDgwXWfuf322+eee+7Jhhtu2Klzv/3tbzNmzJj6hOpmV111VQ477LAsWLCg5jNrr7127rjjjrz73e/+t72qqvLDH/4w3/ve91JVVc09H3vssey+++55+eWXaz7T0972trflueeey49+9KPstNNOaWpq6vEMzc3NOfXUU3PBBRd06vM7derUXHzxxXVM9qobbrghV155Zc31Bx10UC688MKstNJKyzx7rbXWyp/+9KdssMEGNZ857bTTMmHChGWeDQDQSD3/rpQuK6WcmeRjSVp/K1VqOFa1Wa1nlmW117PDyC2rasn8iVLKGTVkXpr3J3k8ydgO1uNJbi6ljOuGWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACyjabf8I1OuejIpjU7STUoy5conM+3WfzQ6CdTNyJEjc/fdd+eWW27JXnvt1ePz11tvvfzhD3/IkCFDOnXu5z//eZ0SdZ/rrrsuH/jABzJ//vyaz4wYMSJ333133va2ty2x7nOf+1wuuuii9O7du+beDz/8cPbcc89MmjSp5jM9qVevXo2O8C9HHnlkvv71r3fqzKhRo+oTpo0vfOELNdcOGzYsF154YZqbm7tt/lprrZXf/OY3NX/dTZ06NWeccUa3zQcAaISmRgegc0op5yXZL8nEJFVe/TVVrb+qqrpp1RS1zcyXk+xfSvlFjWeX3LiUQ0opmy1ljeyOWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACybabf+I9NufKbRMepi2g3PZNqt/2h0DOhW22+/fW699dZcf/312X777RuaZYMNNshFF13UqTOXXnpp5s6dW6dEy+7GG2/M+973vsybN6/mMzvvvHNGjx6dddddt6b6D37wg7n++uszePDgmmeMGTMme+65Z6ZMmVLzmTeqr371q9lmm21qrr/nnnsyderUuuX5/e9/n4cffrim2qamplxyySUZOHBgt+fYdttt861vfavm+vPOOy+vvPJKt+cAAOgpTY0OQOeVUm5KsmWSm5NUrbdbVqO1zVEl+VOSLUspNzQuEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI0w457nM+2GZxodo66m3fBMZtzzQqNjQLfYZ599cvfdd2eXXXZpdJR/2XvvvfPBD36w5vopU6bkrrvuqmOirvvDH/6Qgw46KHPnzq35zPve977cdNNNWXnllTs1a7fddsvtt9+etdZaq+YzDz74YPbaa69MmzatU7PeaHr16pVvf/vbNdcvXLgwo0ePrlueM888s+ba4447Lttss03dspx00kkZPnx4TbWzZs3K2WefXbcsAAD11tToAHRNKeWlUsreST6UZHySqnWrzeqxOIvNrJK8mOTIUsoepRS/cQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHiDmfXQxEy56slGx+gRU656IrP+OrHRMWCZDRgwoNER2vWNb3wjTU1NNdffcsstdUzTNbfccksOOOCAzJkzp+YzJ554Yi677LL07du3SzO33HLL3H333dlss81qPnP//fdn5MiRmT59epdmvlHstddeWX/99Wuu/9vf/laXHGPGjMkdd9xRU22/fv1y+umn1yVHq5VWWilnnnlmzfX//d//nQULFtQxEQBA/dT+LxSWS6WUS5JsmuTLSV5MUrWsJCltVrePXqx369wJSb6SZFgp5aI6zAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGA5N3/irEy+fGxSGp2kh5Rk8m/GZv7EWY1OAq9LG2+8cXbbbbea6++///46pum8O+64I/vvv39mz55dU31VVTnzzDNz9tlnp6mpaZlmr7feehk9enTe+c531nzm7rvvzr777psZM2Ys0+zXs6qqsu+++9ZcP3bs2LrkGDVqVM21H/nIR/KWt7ylLjnaOvDAAzNs2LCaaidOnJgbbrihzokAAOpj2d6ps1wopcwqpXw3yfpJPprk9patqmUlr/56q6PVYeulnGnb/84kxyYZWko5s5Qyc5kfDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBVOWVQy+fJxKfMXNTpKjyrzF7363ItKo6PA69J73/vemmvHjRtXxySdc9ddd2XffffNzJkza6pfaaWVMmrUqHzxi1/stgyrrLJK/vCHP+Sggw6q+czo0aPznve8J7Nmzeq2HK83O+ywQ821kyZN6vb5CxcuzKWXXlpz/UknndTtGdpTVVU+/elP11x/0UUX1TENAED9NDc6AN2nlDI/yQVJLqiqap0k70uyZ5Kdkwxq78hiHztStXNvRpLRSW5OckUp5bmuZAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOD1Zcad4zPv2WmNjtEQ856dlhl3Pp9BO6/d6CjwurPzzjvXXPvMM89k0aJFaWpqqmOipbv33nuzzz77ZMaMGTXVDxo0KFdccUX23HPPbs/St2/fXHHFFTnxxBPz05/+tKYzt912W/bff/9ce+216devX7dnWtFttNFGNddOnz692+ffcssteeGFF2qq3W677TJs2LBuz9CRww47LCeddFLmz5+/1Nqrr746M2bMyMCBA3sg2evL5MmTc/PNN+ehhx7Ko48+mnHjxmXKlCmZNm1aZs+enb59+6Z///5ZffXVs8EGG2TYsGHZcccds9NOO2W11VZrdPxus2jRoowfPz5PP/10Jk6cmJkzZ2bWrFlZuHBhBgwYkP79+2fllVfOBhtskKFDh2allVZqdORu9corr+Tmm2/O/fffn7/97W8ZN25cpk6dmunTp2fhwoUZNGhQBg0alFVXXTWbbrppNt9882y99dZ597vf/Yb93j5lypQ89dRTGT9+fGbMmJFZs2Zl9uzZ6d27dwYMGJCBAwdmvfXWy4Ybbpg3velNjY7bLRYuXJjnnnsuL7zwQiZOnJgpU6Zk7ty5mTt3bpqbm9O/f//XrJVXXjlDhw7Nyiuv3OjosFxrbnQA6qOU8s8kZyU5q6qqXkm2TLJFkrcm2TTJ2knWTDIkSUf/6ixJXk7yQpLnk/w9ycNJ/prkoVLKgno+AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACuW+RNnZeqNzzY6RkNNvfGZ9N105az0lv6NjgKvK5tsskmqqkopZam1CxcuzMyZMzNo0KAeSNa+P//5z9l7770zbdq0murXWGON/P73v8/WW29dt0xNTU0555xzsvbaa+erX/1qTWf+9Kc/5cADD8zVV1+dvn371i3bimjllVeuubZXr17dPv/3v/99zbWHH354t89fklVWWSUjR47MNddcs9Ta2bNn55Zbbsn+++/fA8l63q233ppdd911qXW77LJLbr311qXWzZkzJ6NGjcqll16aO+64IwsWLOiwdubMmZk5c2YmTpyYRx55JEny/e9/P01NTdlpp53ywQ9+MEceeWT69etX8/MsD6ZOnZobb7wxo0ePzujRo/Poo49m3rx5NZ1tamrKRhttlHe+853Zaaedstdee2Xdddetc+LuN3v27Fx66aU599xzc++992bRokUd1k6aNCmTJk3Ks88+mwcffPBf9/v375899tgjH/7wh3PwwQfX5fvU8mDOnDm57bbbcuedd+bOO+/Mgw8+mClTptR8frXVVsuOO+6Yd77znRk5cmTe+ta31i9sNxo3blz++Mc/5q677soDDzyQJ554oua/J20NHjw4Q4cOzfrrr59hw4Zlu+22y/bbb79C/r2BemhudADqr5SyMMmDLes1qqpqStIvSd+WlSRzk8xJMquU0vFPaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhRFpVMvnxcsmBRo6M01oJFmXz5uLzl41ukaqoanQZeN/r27ZuVV145kyZNqql+xowZGTRoUJ1Tte8vf/lL9tprr0ydOrWm+uHDh+eGG27I+uuvX99gLb7yla9knXXWybHHHpv58+cvtf7mm2/OwQcfnN/97nfp06dPDyRcMTQ3N9dcO2TIkG6ff/PNN9dce+CBB3b7/KU54IADcs0119RUe/PNN2f//fevc6IV26xZs/LDH/4wZ599diZMmLBMvRYtWpTbb789t99+e0477bR88YtfzKc+9alOfU33tEWLFuXKK6/MhRdemOuvvz5z587tcp9x48Zl3LhxueCCC1JVVXbaaad88IMfzBFHHJEBAwZ0c/LuNXfu3Jx99tk588wza/552JFZs2bl6quvztVXX52NNtoon//853Pcccelqampm9I2Tikl119/fS655JJcddVVmT59epd7TZgwIVdeeWWuvPLKfP7zn89b3/rWfOhDH8rHP/7xrLzyyt2Yetm99NJLOe+883LJJZfk0Ucf7Zae06ZNy8MPP5yHH374NffXXHPNbL/99hk5cmTe+9735i1veUu3zIMVzYr/HZNlUkpZVEqZWUp5pZQyvmW9XEqZUUp5g/92DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFrNuOv5zHt2WqNjLBfmPTstM+56vtEx4HWnf//+NdeWUuqYpGN//etfs+eee2by5Mk11e+www658847s/7669c32GKOPPLIXHPNNRk4cGBN9ddff30OOeSQzJs3r87JVhwzZsyouXbVVVft1tkvvPBCHnnkkZpqN9poox7/+kqSPfbYo+bam266qY5JVnw33XRT3vrWt+aUU07JhAkTurX3hAkT8tnPfjZvf/vb89e//rVbe3eHBQsW5Pzzz89mm22W973vfbnyyiszd+7cbutfSskdd9yR448/Puuvv37OOOOMTJu2fL6f/eMf/5gRI0bkC1/4QiZNmtStvZ988sl84hOfyI477phHH320W3v3pPnz5+f888/PiBEjst9+++Wiiy7K9OnTu3XGI488ki9/+csZOnRovvSlL2XKlCnd2r8rxo8fn4997GNZd911c8opp/TIn+ELL7yQ3/3ud/n4xz+eNddcM3vssUd+/vOfd+pnI7weNDU6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBiWzR7Qab94dn/z46dh1lZ1/0D/9xnBhgGGET2RUFF3FJEzR2VFFxSe3zUSvNxSwXTLC21NCtNzSV7tEUrcSFLW/wZmpmKoCZqKpG4pSwqAiIoyj7ALPfvj+CJDOQ+M2eZwdfruu6Lw7nf3+/nfZ85c86ZU+4aLcriR2ZGY219uWvARmXJkiWZsx07dixik3V7+eWX46CDDooFCxZkyh955JExfvz46Nq1a5GbrdvBBx8cjz32WPTs2TNT/v7774/Pfe5zUVdXV+RmrcPMmdnf9wYMGFDQ2Y8++mjm7EEHHVTQ2VkNGDAgttpqq0zZ1157LebOnVvkRq1PQ0NDfOUrX4mDDz443njjjaLOmjJlSuy9997xhz/8oahz8vHcc8/FJz/5yTj11FNj6tSpRZ/33nvvxbe+9a3Ybrvt4v/9v/9X9HlZNTQ0xMUXXxwjRoyI119/vaiznnnmmdhll11izJgxRZ1TDOPGjYsddtghTj311Hj11VeLPm/JkiVx9dVXx7bbbhu/+c1vij5vXdI0jRtuuCEGDRoUN998c9nenxsaGmL8+PExatSomDRpUlk6QLnkyl0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaN2W/W1epCsayl2jRUlXNMSyv80rdw3YaNTV1cXixYszZSsqKqJjx45FbvTv/vGPf8SBBx4Y7777bqb8yJEj45577on27dsXudlH23XXXeOpp56KrbfeOlN+7Nixcfzxx0d9fX2Rm7V8U6ZMyZwdOnRoQWdPmjQpc3bPPfcs6Ox85DP7b3/7WxGbtD6LFi2KT3/60/GjH/2oZDOXLVsWxxxzTPzmN78p2cx1aWxsjIsvvjj23HPPeP7550s+/+23345jjjkmjj766FiyZEnJ56+ttrY2jjrqqLjyyiujsbGxJDNXrVoVJ598clx++eUlmddcixYtiuOPPz5GjBgR06ZNK/n8efPmxXHHHRfHH398LF++vGRzFy1aFIceemh89atfLelc4N/lyl0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaL3SxjSW/XVuuWu0SMv+OjfSNC13DdgovPzyy5l/nwYMGBC5XK7Ijf5l6tSpceCBB8a8efMy5S+77LL42c9+FhUVFUVuls2WW24ZTz31VOyxxx6Z8nfffXeccMIJ0dDQUORmLdu4ceMy5WpqamLnnXcu6OzJkydnzu66664FnZ2P3XbbLXM2n2va2C1ZsiSGDx8eDz30UMlnNzY2xoknnhiPPPJIyWdHRCxatCgOP/zwuPLKK6OxsbEsHda45557Ys8994xp06aVZf7SpUvjkEMOiT/+8Y9lmX/JJZfEFVdcUZbZWb344ovxyU9+Mu66665yV4m77ror9t5775g1a1bRZ7377ruxzz77lOU1Avh3pfuLAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANjorJyxMOrfqy13jRap/r3aWDljYblrwEZh0qRJmbODBg0qYpN/N2PGjPjUpz4Vc+fO3WC2srIybr311rjkkktK0Cw/3bp1iwkTJsThhx+eKf/b3/42TjrppGhsbCxys5Zp+vTp8eSTT2bKHn744ZHL5Qo2O03TeP755zNlq6qqYvvtty/Y7HzttttumbOTJ08uYpPWY8WKFXHkkUfGc889V7YOdXV18YUvfCHeeeedks59//33Y//9948///nPJZ37UV555ZXYe++948UXXyzp3Pr6+jj22GPjL3/5S0nnftgll1wSv/nNb8raYX0efPDB2HPPPWPatGnlrvJ/pkyZEgcccEDMmjWraDOWLl0ahxxySLz88stFmwFkV1nuAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDrtfSvc8tdoUVb9vTcqBrYpdw1oNW77777Mmd33333Ijb5lzfeeCOGDRsWc+bM2WC2Q4cO8fvf/z4OPfTQEjRrmurq6hg7dmyMGjUqRo8evcH8r3/966isrIxbb701crlcCRq2HJdddlmkaZope+655xZ09syZM2PRokWZsltvvXVUVFQUdH4+tt1228zZKVOmFLFJ63HaaafFY489lilbU1MTu+yyS2y11VbRp0+f6NChQ1RUVMSyZctizpw58dprr8Vzzz0XtbW1efeYP39+jBo1KsaOHZv32qZYuHBhDB8+vEU+D95777048MAD49FHH40ddtihJDO/9KUvxYMPPtjk9b169YohQ4bENttsE5tuumlUV1fH8uXLY+HChTF16tR4/vnnY/bs2RvcJ03TOOWUU2KnnXZqcpdiuO++++LYY4+NVatWlbvKf3j99dfjgAMOiKeeeip69uxZ8P3PPvvsmDx5csH3BZqmstwFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgNapftHKWPHKgnLXaNFq/7Eg6hetjMrO7cpdBVqtRYsWxcMPP5w5f8ABBxSvzGozZ86MYcOGxaxZszaY7dGjR9x///3xyU9+sui9mquioiJuvvnm6Nu3b1x66aUbzI8ZMyYqKyvj5ptvjiRJStCw/B566KH41a9+lSk7dOjQ2G233Qo6//XXX8+cHThwYEFn56tbt26xySabxMKFCzeYnTVrVtTX10dlZWXxi7VQo0ePjl//+tcfmendu3f8z//8T3z2s5+NIUOGRC6X+8j8qlWr4s9//nP89Kc/jXHjxuXV5957743x48fHgQcemNe6fDU0NMTRRx8dkydPbtL6nj17xiGHHBLDhg2L7bffPgYMGBCdOnWKioqKWLJkSbzzzjvxj3/8I5588sl44IEH4rXXXst7xrvvvhuHHnpo/O1vf4vu3bs3qWdWd9xxR9x88815r9t0003j1FNPjRNOOCEGDx68wfzLL78cd911V4wePTrmzZu33tyKFSvilFNOiTPOOCPvTsXw8MMPxzHHHBN1dXVNWr/zzjvH/vvvH7vttlsMHDgwNt9886ipqYn27dtHXV1dLFmyJGbOnBmvvvpqTJw4Me6///6YM2dOXjNef/31OOaYY2LChAnRpk2bJvVclwcffDDGjBnTpLXbbLNNHHjggbHtttvGVlttFVtuuWV06tQpOnToEB06dIgkSWLlypWxfPnyeO+99+Ldd9+NN954I6ZNmxavvPJKPPfcczF79uyCXQtsLJI0TcvdAQDIKEmSxRHRaX3nO3XqFIsXLy5hIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4dw0NDTF16tTM+UGDBkVFRUURG1FMi8bNjCXj3yp3jRav04GbR+fh/ctdA1qta6+9Ni644IJM2U022STeeeedaNeuXdH6zJ49O/bff/94/fXXN5jdaqut4qGHHoqtttqqaH2KZfTo0TFq1KhoaGjYYHbkyJFx0003RZIkJWhWPi+99FLst99+8cEHH2ww26ZNm3jmmWdiyJAhBe1wyy23xGmnnZYpe8EFF8TVV19d0Pn5+uQnPxmTJk3KlJ0xY0ZsueWWRW5UWo899lgMGzZsg7n+/fvH/Pnzo7a2dp3nu3btGt/73vfi1FNPbfLr28MPPxynnXZazJo1K/Oa3XffPZ555pkmzcvqwgsvjGuuuSbvdUOGDIlvfvObcdRRR0VlZWXmdRMnToxrr7027rvvvrxnfupTn4qHH364aH+/vP7667HzzjvHkiVLMq9p06ZNnHvuufGtb30rOnXqlPfMFStWxDXXXBNXXXXVep9/ERGDBw+OKVOmbHC/k046KW6//fa8e2Tx2muvxZ577hkLFy7Ma12fPn1i5MiRccopp8Rmm22W19o0TWP8+PHx/e9/PyZMmJDX2rPOOit+8pOf5LXmo3rsvPPO8cILL2Re07179/jKV74SJ5xwQvTv3/y/RebOnRvjx4+PRx55JO6///5YsGDBf2QeffTROOCAA5o9q1w+Dt9n1NTUbOg1ZkmapjWl6tPa5cpdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGidal96r9wVWgWPEzTdqlWr4kc/+lHm/LHHHhvt2rUrYqOIfv36xYwZMyJN0w0e06dPj6222qqofYrltNNOi/r6+kzX+bOf/SySJCl35aIaP3587L///vHBBx9kyn/nO9+JIUOGFLzHG2+8kTm7+eabF3x+vvLpkM+1bWxmzpwZtbW16zz3mc98Jl599dU488wzm/X6NmLEiHjuuedil112ybzm2WefjaeeeqrJMzdk3Lhxcc011+S1prq6On72s5/FpEmT4thjj43Kysq81u+7775x7733xrhx46Jfv355rZ0wYUJceeWVea3Jx6hRo2LJkiWZ85tvvnk88cQTcfXVV0enTp2aNLOqqiq+/e1vx7PPPhvbbLPNenNTpkxp0v6FsmTJkjjiiCNi4cKFmdd07Ngxrr322pgxY0Z8+9vfjs022yzvuUmSxEEHHRTjx4+PsWPHRp8+fTKv/elPfxqPPvpo3jPXZcKECfHCCy9kzl9wwQUxc+bMuPjii6N///4F6dC7d+844YQT4vbbb4933nknHn744Tj++OOL/rkLWrJcuQsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArU/jivqon7e83DVahfp5y6NxRX25a0CrdP3118fs2bMz50855ZQituHjaP78+XHiiSfGQQcdFO+//36mNYccckh84xvfKEqfN954I3O2V69eRemQj3w65HNtHxff/OY34w9/+EN069atIPv17NkzHnroodhqq60yr/n5z39ekNkfVltbG2eeeWZea7bccsuYNGlSjBw5MnK5XLPmH3TQQfH888/HsGHD8lp3xRVXxNSpU5s1e13uu+++GDduXOb8tttuG08//XTsscceBZn/iU98Ip5++unYbbfdCrJfoZ1//vkxbdq0zPm99947Xnzxxfj6178eVVVVBenwmc98JiZPnhz77LNP5jVnnHFGrFixotmzx4wZkymXy+Xi97//fVx99dXRvn37Zs9dn8rKyhg+fHj8+te/jjlz5sSVV14ZPXr0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duyYKfvMM8/Eww8/XPAOH/aDH/wgVqxYkSm77777xtZbb13kRrQ0J510Uubs2LFj4+mnny5im3/33nvvxbXXXps5n8+1rM9nPvOZqKmpyZQdM2ZMTJ48udkzs3jjjTfihhtuKMms9TnnnHPyytbW1haxDWvMnTs3U65Tp05FbgLllyt3AdapYQPntylJi8IblCGzoWsHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgFage3D02+cxW5a5REpt8ZmBU79S93DWg4C677LK4/PLL81pz2GGHxd133x1t2rQpUisov0cffTSuvfbazPmuXbvG4YcfXvAem2yySZx++umZ8+edd17U19cXvMca06dPjxtuuCFz/oILLihaF1quHXbYIfbaa6/M+TPOOCNWrVpVxEb/ctZZZ8WiRYsyZWtqauLzn/98s2d27NgxRo4cmSnb0NAQp5xyStEfjzRN44tf/GIsX768qHM2ZO+99878XHn11VfjK1/5SpEbsXTp0pgzZ06mbP/+/YvcBsovV+4CrNOS9dyfRkQSEUNK2KWQds2QWVr0FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJRExz37RM0hA8pdo6hqDhkQHffsXe4aUHBXX311fOc738lrzYgRI+Kee+6Jtm3bFqkVHyevvPJKNDY2lrvGf5gyZUocddRReXU78cQTi/Z7cd5550WbNm0yZV9++eW4+uqri9KjsbExRo4cGatWrcqU/8QnPhGHH354UbrQ8l188cWZsy+99FJceOGFRWzzT7/85S/jd7/7Xeb82WefHZ07dy7I7K985SuZf49feOGFOOusswoyd32+9a1vxaOPPlrUGVldd911mbM333xzXHPNNUVsUx719fXlrvB/7rrrrsx9dthhhyK3gfLLlbsA67RoHfcla93ulSTJjqUqU0AjMmQWFrsEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApVNzwGZRc8iActcoippDBkTNAZuVuwYU3P/+7//GN77xjbzWHHjggTF27Nho165dkVrxcXPNNdfEkCFD4s9//nO5q/yfRx55JPbff/9YtGhR5jXV1dVxwQUXFK1Tv3794uSTT86c/853vhN/+ctfCt7je9/7XkyYMCFz/qKLLookSQreg9bh05/+dOyyyy6Z89dff33ceuutRevz1FNPxRlnnJE536FDhzj33HMLNr9v375x5plnZs6PHj06rrjiioLNX9vPf/7zuPLKK4uyd1Pstdde8fnPfz5z/sILL4yrrrqqiI3yk6Zp3HvvvXn9fD9sl112iR//+MexYsWKAjbL3/Lly+OHP/xhpuyAAQOif//+RW4E5ZcrdwHWaVpEbOhT5hdKUaRQkiTpFxH7R0S6gej0EtQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACghGoO2Cw2+a+tIpJyNymQJGKT/xoYNQdsVu4mUHA//elP47zzzstrzQEHHBD33XdftG/fvkit+Lh64YUX4rDDDoudd9457rjjjli1alVZeqxYsSIuuOCCOPjgg2PRokV5rf3yl78cvXr1KlKzf7r88sujc+fOmbINDQ1x1FFHxZQpUwo2/5ZbbolLL700c37fffeN4447rmDzaZ1++MMf5pU/44wzYsyYMQXv8eSTT8ahhx4aK1euzLzmkksuiW7duhW0x3e/+93o2rVr5vy3vvWt+MY3vhGNjY0F63DNNdfEqFGjCrZfoVx//fXRo0ePzPlvfvObcfLJJ8fSpUuL2OqjLV++PEaPHh077bRT/Nd//Vc899xzTd7rrbfeinPOOScGDBgQ3/3ud2Pu3LkFbJrdl770pXj11VczZT/96U8XuQ20DLlyF2Cd/vER59L451dTX0ySpEOJ+hTC2RFRsfr22l+tpWvdrouI6SVrBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMl03LNPbHrctpG0yZW7SrMkbXKx6XHbRsc9e5e7ChTczTffHF/+8pfzWjN06NC4//77o7q6ukitIGLKlClx4oknRp8+feLss8+OZ555JtI0Lfrc2tra+PnPfx4DBw6Ma6+9NhobG/Nav/XWW8e3v/3tIrX7lx49esT3vve9zPn3338/DjrooPjLX/7S7Nn/+7//G2eccUbmn0dFRUX85Cc/afZcWr/9998/TjnllMz5hoaGOOWUU+Kiiy6KhoaGgnS47bbbYvjw4bF48eLMa3bcccf42te+VpD5a+vSpUt8//vfz2vN1VdfHQcffHC89dZbzZr9zjvvxFFHHRUXXnjhejNVVVXNmtEcPXv2jNtvvz2SJMm8ZsyYMbHjjjvGAw88UMRm/2nSpEnx1a9+Nfr27Runn356vPTSSwXbe968eXHppZdG//7947Of/Wz86U9/ivr6+oLtvz7Lli2Lz3/+8zFmzJjMa84444wiNoKWo3V/u7Hxem4996/9LrJpRFxcgi7NliTJZhHx5YhY36ftNdf1fJqm+f21AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQKtRvVP36HHOkGjbv6bcVZqkbf+a6PGVXaJ6p+7lrgJFccUVV0SapnmteeKJJ6Jjx46RJEmLOk4++eTiPEiU1YIFC+KnP/1p7LnnntGnT5849dRT4ze/+U289dZbBZtRV1cX48ePjy9/+cvRt2/fGDVqVMyZMyfvfSorK2PMmDFRXV1dsG4f5Utf+lLstddemfPvvfdefOpTn4rvfve7UVtbm/e8WbNmxX//93/HeeedF42NjZnXfe1rX4vBgwfnPY+N0w9+8IPYbLPNMufTNI3vf//7sccee8TEiRObPHfGjBnxX//1X3Hqqafm9fxv27Zt3HrrrVFZWdnk2R/l9NNPjyOPPDKvNY888khsu+22ceGFF8asWbPyWjtv3ry49NJLY9CgQTF27Nj15jp06BDnn39+XnsX2qGHHhrf+MY38lrz5ptvxqc//ekYOnRo3HfffdHQ0FDwXg0NDfHkk0/GxRdfHIMGDYpPfvKTccMNN8TChQsLPmuNurq6+P3vfx+HH3549OnTJ770pS/FAw880KTX8o/S2NgYd955ZwwZMiR++9vfZl538MEHx0477VTQLtBSFefdgOYaFxGNEZFERLr637Wtue+8JEnuSdN0Uon7ZZYkSRIRt0RE+1j3tayRRsRDpeoFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAebTpXh3dR+4US598OxY99GZEfWO5K21YZS46HzwgOu7TJ5JcUu42AETEO++8E7fddlvcdtttERHRu3fvGDJkSGy77baxzTbbxGabbRY9e/aMHj16RMeOHaOqqiratm0bDQ0NsWrVqli2bFnMnz8/5s2bFzNmzIipU6fGpEmT4rnnnovly5c3u99NN90Ue+21V7P3yaqioiJ+85vfxJAhQ+L999/PtKahoSEuvfTSGD16dHz1q1+N448/Pvr06fORayZPnhy333573HzzzbFixYq8Ou6zzz5xxRVX5LWGjdumm24ad999d+y3336xcuXKzOv+9re/xdChQ2P//fePkSNHxqGHHhqbbLLJR65ZuXJlPP7443HLLbfEH/7wh6irq8u7749//OPYbbfd8l6Xj1tuuSWGDBkSs2fPzrymtrY2rrnmmrjuuuti//33jxEjRsSuu+4agwYNik033TSqq6ujtrY2Pvjgg5g2bVr8/e9/j4cffjgmTJiQ6XG48soro6ampjmXVRBXXHFFzJkzJ375y1/mtW7ixIkxceLE6N27dxx11FFx2GGHxd577x1dunTJu8P8+fPjpZdeir/+9a/x17/+NZ544olYuHBh3vsUyrvvvhs33XRT3HTTTdG+ffvYe++9Y99994199tkndtppp+jZs2de+zU0NMQzzzwTf/zjH+Puu++O6dOn57W+TZs28b//+795rYHWrLLcBfhPaZq+nyTJMxGxV0SkHzqdrL4vjYi2EfG7JEn2StN0XolrZnVlRBwU/+y7oW+j7i9+HQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMotySXRaWjfqNq2S3xw97RYNXNxuSutV9v+NdHl2EHRplv7clcB4CPMnTs35s6dGw888EC5q8Sll14ap512Wsnnbr755nHHHXfEEUccEY2NjZnXzZkzJ84///y48MILY7vttovddtst+vbtG5tssknU1dXFwoULY9q0aTFp0qSYPXt2k7p17949fvOb30RlZWWT1rPx2n333eOmm26KU089Ne+1jz/+eDz++ONRUVERgwcPju233z769+8fnTp1ioqKili6dGnMnTs3Xn311Zg0aVIsX768yT1HjRoVZ5xxRpPXZ9WtW7e4//77Y+jQobFkyZK81jY0NMSECRNiwoQJBetz2GGHxdlnnx2//OUvC7ZnUyVJErfcckssWrQo7r333rzXz507N2688ca48cYbIyJiwIABsc0220S/fv2iV69eUV1dHVVVVdHQ0BArV66M2traWLBgQbzzzjsxd+7cmDp1aixcuLDAV1U4tbW1MX78+Bg/fvz/3bfpppvGNttsE3369Ik+ffpEly5doqqqKtq1axcrV66MpUuXxrJly2L27Nnx2muvxbRp02LlypVN7vD9738/tttuu0JcDrQKPtW0XKMjYq/1nEsiIl19DIiI8UmSDEvT9N0SdcskSZKLIuLC+GfPdUnjn9cSEfFimqbPlaQY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AAAAAAAAAAAAAAAAAAAAAKDuqqysjKlTp8Z7770X77//fnz44Ycxc+bM+PLLL2PBggVRXl4ey5cvjwYNGkRZWVk0btw41ltvvejYsWN07tw5ttxyy9h6661jm222iZYtWxb7ceB768svv4wPPvggvv7661i8eHEsXrw46tWrF82aNYtmzZrFeuutF5tvvnk0b9682FMBAIqutNgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC6Y/HixTFu3Lh45ZVX4rXXXou///3vsWzZsjWeW758eSxfvjwWLlwYs2bNirfeeuvfXi8pKYntttsu+vTpE4cffnhst912BXqCuufSSy+NK664IlO2devWMXr06OjZs2eBV62b5s6dG7fddlvO57p27RrHH398/gcVSJqm8eabb8bzzz8fI0eOjHfffTcWLlyY6WynTp1i2223jf79+8f+++8f3bp1K+xYAIBaqLTYAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA2m3q1Knx7LPPxjPPPBPjx4+PioqKvHdUVVXFxIkTY+LEiXHNNdfEFltsESeddFKcfPLJ0bRp07z31RVXXHFFXHHFFZnzCxYsiH322Sdefvnl2GqrrQq4bN00ZMiQeOyxx3I+t8cee8Txxx+f/0F5Nn/+/Ljrrrvi9ttvjy+++KJad8ycOTNmzpwZzzzzTEREbL/99nH66afHj3/842jQoEE+5wIA1FolxR4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANQ+7777blxyySWx6aabxpZbbhm/+MUv4tVXX42Kiooa6Z86dWqcffbZ0aVLl7jiiiuivLy8Rnprk2uuuSYuvfTSnM/Nmzcv+vTpE1OnTi3AqnXXE088EY899lixZxTE4sWL49xzz43OnTvHRRddFF988UXe7p40aVIcd9xxseGGG8bQoUMjTdO83Q0AUFuVFnsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQHUsX7485s6dG8uWLYuKioqoqKiIysrKqFevXpSWlkZpaWk0btw42rVrF2VlZcWeC3XCnDlz4k9/+lPcf//98e677xZ7TkRELFiwIC699NK477774tZbb40DDjig2JNqxA033BAXXnhhtc9/9dVX0adP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y5fHmDFj4rXXXovXXnstJk+eHAsXLsx8fr311otddtkldt111+jfv39stdVWhRubR9OmTYtRo0bF+PHj480334yPPvoo8++Tf9W8efPo0qVLdO3aNXr06BE77bRT7LzzznXy9w0UQmmxBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADrhnnz5sXo0aOLPaOoRo0aFZtsskm0bdu22FNgnVJWVhatWrWKBQsWZMovWbIkmjVrVuBV3+7vf/979OvXLxYtWpQpv+mmm8YLL7wQXbt2Leyw/++iiy6Kzp07x0knnRSrVq1aY37kyJHxox/9KJ588slo2LBhDSzMjxUrVsSgQYOisrJytblLL700evToUUOr8mfkyJGZs4ccckgBl3y7gw8+OJ5++ulM2ZEjR8ZBBx1U4EV127Jly+J3v/td3HLLLfHVV1+t1V1VVVXx6quvxquvvhqXXnppnH/++XH66adHaWlpntbmX1VVVQwbNiweeuiheP7552PFihXVvmfatGkxbdq0uP/++yNJkthtt91i4MCB8ZOf/CSaNGmS5+X5tWLFirjlllvimmuuyfzn4XdZtmxZPPXUU/HUU09F9+7d47zzzouTTz45SkpK8rS2eNI0jeeffz4eeeSRGD58eCxevLjad3311VcxbNiwGDZsWJx33nmx1VZbxTHHHBOnnnpqtGrVKo+r196cOXPi7rvvjkceeSSmTJmSlzu/+eabePfdd+Pdd9/9t5/v0KFD7LzzztG/f/847LDDol27dnnpg7qm7n/HBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIquqqoqhg8fHhUVFcWeUlQVFRUxfPjwqKqqKvYUWOc0btw4czZN0wIu+W7vvPNO9O3bN77++utM+d69e8drr70WXbt2Leyw/3DcccfF008/HU2bNs2Uf/755+Pwww+PlStXFnhZ/lx++eUxderU1WZ69uwZ5513Xg0typ/Zs2fHe++9lynbvXv3Gv/6iojYZ599MmdffPHFAi6p+1588cXYaqut4pe//GV89dVXeb37q6++inPOOSe23377eOedd/J6dz5UVFTEfffdF5tvvnkMGDAghg0bFitWrMjb/WmaxtixY+O0006Lrl27xpVXXhnffPNN3u7Pp1GjRsUWW2wRv/jFL2LBggV5vfvjjz+OwYMHxy677BJTpkzJ6901adWqVXHffffFFltsEQcccED88Y9/jMWLF+e147333osLL7wwunTpEhdccEEsXLgwr/dXx8yZM+OUU06JDTbYIH75y1/WyK/h7Nmz48knn4xTTz01OnToEPvss0/84Q9/iCVLlhS8G2qTkmIPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOq+CRMmxIwZM4o9o1aYMWNGTJgwodgzYJ2zePHizNmmTZsWcMm3mzJlSuyzzz4xf/78TPmDDz44Ro0aFW3atCnwsm+37777xiuvvBLt27fPlH/mmWfixz/+caxatarAy9be5MmT47rrrlttpl69enHPPfdEaWlpDa3Kn5dffjlzdp999ingku/WtWvX6N69e6bsBx98ELNnzy7worqnsrIyzjjjjNh3331j+vTpBe16++23Y5dddoknn3yyoD25mDhxYuywww5xwgknxIcffljwvnnz5sUvf/nL2HzzzeOvf/1rwfuyqqysjIsvvjj69esXn3zySUG7JkyYEL169YoHHnigoD2FMHLkyNhyyy3jhBNOiPfff7/gfYsXL45rr702Nttss3j00UcL3vdt0jSNm2++OXr06BFDhw4t2p/PlZWVMWrUqBg8eHBMmjSpKBugWEqKPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACo28rLy+OVV14p9oxa5ZVXXony8vJiz4B1xqpVq+Kbb77JlK1Xr140bdq0wIv+3T/+8Y/o06dPzJ07N1P+1FNPjSeeeCIaNWpU4GWrt91228X48eNjk002yZQfNmxYDBw4MCoqKgq8rPpWrVoVgwYNWuPGs88+O7bbbrsaWpVfkyZNypzdeeedC7gkf91vvvlmAZfUPYsWLYoDDjggbrnllhrrXLp0aRx++OHx6KOP1ljnt6mqqoqLL744dt5553jrrbdqvH/WrFlx+OGHx4ABA2Lx4sU13v+vysvL47DDDourrroqqqqqaqRz5cqVcfzxx8dvfvObGulbW4sWLYqBAwdGv379Ytq0aTXeP2fOnDj66KNj4MCBsWzZshrrXbRoUey3335x5pln1mgv8O9Kij0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqNveeuutWLFiRbFn1CorVqyIt99+u9gz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HhtttFENrKp9Pv300zj99NO/8/U2bdrEFVdcESeccEI0bNgw870NGjSIQw45JA455JB48cUX46STTooZM2ZkPn/RRRfFhAkTMuer46KLLorRo0fnfG7bbbeNCy+8MA477LAoLS391kzr1q2jdevWscUWW8SAAQPixhtvjHHjxsX1118fTz31VE59M2bMiKOOOipefPHFqFevXs57s/jkk0/i5z//eU5n6tevH2eddVb88pe/jGbNmmU+t+WWW8ZvfvOb+OUvfxnXXXddXHPNNVFeXv6t2TfeeCPzn8OF9MEHH8SPf/zjWLVqVU7nOnbsGKeeemoMGjQoNthgg+/M1atXL8rKyqJdu3ax/fbbx7HHHhtpmsaoUaPi6quvzunrdNy4cXHWWWfF73//+5y2fpc0TeP888/P6Uy7du3ijDPOiGOPPTa6dOmyxnxpaWk0adIk2rVrF5tvvnn88Ic//LfXZ8+eHaNGjYqXXnopnnnmmZg/f35Oe2BdVFLsAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDdNHny5EjTtNgzarU0TWPy5MnFngF11sqVK+OWW27JnD/iiCOiYcOGBVwU0blz5/j4448jTdM1/vjoo4+ie/fuBd1TKCeddFJUVFRkes4777wzkiQpys7KysoYNGhQrFixYrW5ww47LAYMGFBDqwpn+vTpmbMbbrhhAZfkf0Muz7au+eyzz6K8vPxbXzvkkEPi/fffj9NOO22tvr/169cvJk6cGL169cp85o033ojx48dXu3NNRo4cGdddd11OZxo3bhx33nlnTJo0KY444ogoLS3N6fxuu+0Ww4cPj5EjR0bnzp1zOjt69Oi46qqrcjqTi8GDB8fixYsz5zfccMMYO3ZsXHvttdGsWbNqdZaVlcWll14ab7zxRmy66abfmXv77berdX++LF68OA466KBYuHBh5jNNmzaN66+/Pj7++OO49NJLY4MNNsi5N0mS2GeffWLUqFExbNiw6NixY+azt912W7z88ss5d36b0aNHxzvvvJM5/4tf/CI+++yzuPjii6NLly552dChQ4c49thj4/77748vv/wyXnzxxRg4cGDBP3dBbVZS7AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA3TR16tRiT6gTvE9QfTfddFN88cUXmfODBg0q4BpqoxtvvDHeeOON1WZatmwZt912Ww0tKqzp06dnzq6//voFXJL/Dbk82/fFhRdeGE8++WS0bds2L/e1b98+RowYEd27d8985g9/+ENeuv9TeXl5nHbaaTmd2WijjWLSpElx6qmnRklJyVr177PPPvHWW2/FXnvtldO5K6+8Mj788MO16v42Tz31VIwcOTJzfrPNNovXX389dtppp7z0b7XVVvH666/H9ttvn5f78u28886LadOmZc7vsssu8e6778a5554bZWVledlwyCGHxOTJk2PXXXfNfOaUU06J5cuXr3X3Aw88kClXUlISf/nLX+Laa6+NRo0arXXvdyktLY2+ffvGn/70p5g5c2ZcddVVsd566xWsD2qrtfuTCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPheWr58ecydO7fYM+qEuXPnxvLly4s9A+qcOXPmxJVXXpk5/8Mf/jB69+5dwEXUNh988EFceumla8xdf/310aFDhxpYVHhz5szJnF1//fULuCT/G7766qsCLql7Lr744rjqqqsiSZK83tu2bdt4+OGHo169epnyw4cPj5UrV+Z1Q0TEVVddFR9//HHm/Kabbhpjx46NzTffPG8b2rRpE88991z0798/85kVK1bEaaedlrcNERGVlZVx7rnnZs537tw5Xn755ejYsWNed7Rq1SpeeumlvL7H+TB69Oi46667MucHDhwYo0ePjq5du+Z9S/v27WPkyJHRp0+fTPmPPvoobr/99rXuffHFFzPlfvWrX8Xhhx++1n25aNOmTVx44YXx2Wefxbbbbluj3VBsJcUeAEDdkCTJZkmSDEmSZGiSJK8mSfJZkiQLkiRZlSTJ8iRJ5iVJMj1JkrFJktyfJMkvkyTZL0mS1sXeDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA/s2ePbvYE+oU7xfkbvDgwfHNN99kzl9yySUFXENtU1VVFSeccEIsX758tbk999wzTjzxxBpaVXgLFizInG3fvn0Bl+R/w/z58wu4pG454ogj4je/+U3B7t9xxx1j0KBBmbKLFi2K0aNH57V//vz5cdNNN2XOt23bNp5//vno2LFjXndERJSVlcXjjz8e22yzTeYzo0ePjpdffjlvG5544omYNm1apmyDBg1i2LBhsf766+et/1+1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OPKTPFVPz5CZm6euXO9dv0C9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUArvvvnv06dOn2DMKok+fPrH77rsXewbk1W233RZnn312Tmf23HPPeOqpp6JRo0YFWgWszm9+85to0aJFpmxlZWUcdthh8fbbb+et/5577onLLrssc3633XaLo48+Om/91E033nhjTvlTTjklHnjggbzveO2112K//faLFStWZD5zySWXRNu2bfO649e//nW0adMmc/6Xv/xlXHDBBVFVVZW3Ddddd10MHjw4b/fly0033RTrrbde5vyFF14Yxx9/fCxZsqSAq1Zv2bJlcffdd8fWW28dhx56aEycOLHad33++edx+umnR9euXePXv/51zJ49O49Ls/vZz34W77//fqbsAQccUOA1UDuUFHsAQAH9OCLqZ8w+nqbpzEKO+Rd/johZGbPbJUmyWR46P4uINX3qXpiHnurc27hAvQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1BK77757HHDAAcWekVcHHHBA7L777sWeAXk1dOjQ+K//+q+czuy+++7xzDPPROPGjQu0CliT9dZbL6644orM+QULFsQ+++wTr7766lp3/+53v4tTTjkl0jTNlK9Xr178/ve/X+te6r499tgjBg0alDlfWVkZgwYNiosuuigqKyvzsuG+++6Lvn37xjfffJP5zA9+8IM455xz8tL/r1q1ahVXX311Tmeuvfba2HfffePzzz9fq+4vv/wyDjvssDj//PO/M1NWVrZWHWujffv2cf/990eSJJnPPPDAA/GDH/wgnnvuuQIu+78mTZoUZ555ZnTq1ClOPvnkeO+99/J295w5c+Kyyy6LLl26xJFHHhnPPvtsVFRU5O3+77J06dI46qij4oEHHsh85pRTTingIqg9Soo9AKCABuaQfbBgK/5DmqYVEfFoDkeOyUPnqoj4dA2xJWvb8x0Wr+H1hgXqBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgFtlhhx3i8MMPj9LS0mJPWSulpaVx+OGHxw477FDsKZB3V155ZaRpmtOZsWPHRtOmTSNJklr14/jjjy/MmwS11M9+9rPo3bt35vy8efNi7733jl//+tdRXl6ec9+MGTPiRz/6UZx99tlRVVWV+dw555wTPXv2zLmPddNvf/vb2GCDDTLn0zSNq6++OnbaaacYN25ctXs//vjjOPTQQ+OEE07I6eu/QYMGce+99xbs8+zJJ58cBx98cE5nXnrppdhss83i/PPPjxkzZuR0ds6cOXHZZZdFjx49YtiwYd+Za9KkSZx33nk53Z1v++23X1xwwQU5nfn000/jgAMOiN133z2eeuqpqKyszPuuysrKeO211+Liiy+OHj16xA477BA333xzLFy4MO9d/7Rq1ar4y1/+EgceeGB07Ngxfvazn8Vzzz1Xre/lq1NVVRUPP/xwbLvttvHnP/8587l99903tt5667xugdqqbv/rBsB3SJKkVURk/dvlvIh4qYBzvs2fIuLsjNn9I+KSPHROjoiNVvN60zx0fJtma3h9RYF6AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoZbbaaqtYf/31Y/jw4TFjxoxiz8nZBhtsEIceemi0adOm2FMA4N/Uq1cvHn300dh2221jwYIFmc5UVlbGZZddFnfffXeceeaZMXDgwOjYseNqz0yePDnuv//+GDp0aCxfvjynjbvuumtceeWVOZ1h3da6det4/PHH44c//GGsWLEi87k333wzdt9999hjjz3i1FNPjf322y9atmy52jMrVqyIMWPGxD333BNPPvlkrFq1Kue9t956a2y//fY5n8vFPffcE9tuu2188cUXmc+Ul5fHddddFzfccEPsscce0a9fv9huu+2iR48e0bp162jcuHGUl5fH119/HdOmTYu///3v8eKLL8bo0aMzvQ9XXXVVNG/efG0eKy+uvPLKmDlzZjz44IM5nRs3blyMGzcuOnToEIcddljsv//+scsuu0SrVq1y3vDVV1/Fe++9F3/729/ib3/7W4wdOzYWLlyY8z35Mnfu3LjjjjvijjvuiEaNGsUuu+wSu+22W+y6666x9dZbR/v27XO6r7KyMiZMmBBPP/10PP744/HRRx/ldL5+/frxu9/9LqczUJeVFnsAQIHsHRElGbPPpmlaUcgx/ylN08lJksyMiE4Z4tsmSdI2TdN5a1k7KSIOX83rLdfy/ureu7RAvQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1EJt27aNQYMGxYQJE2LUqFFRUVFR7ElrVFpaGn369ImddtopSkpKij0HAL7VhhtuGA899FAcdNBBUVVVlfnczJkz47zzzovzzz8/Nt9889h+++2jU6dO0bJly1i1alUsXLgwpk2bFpMmTYovvviiWtvatWsXjz76aJSWllbrPOuuHXfcMe6444444YQTcj47ZsyYGDNmTNSrVy969uwZW2yxRXTp0iWaNWsW9erViyVLlsTs2bPj/fffj0mTJsWyZcuqvXPw4MFxyimnVPt8Vm3bto1nnnkmdt9991i8eHFOZysrK2P06NExevTovO3Zf//9Y8iQIfHggw/m7c7qSpIk7rnnnli0aFEMHz485/OzZ8+O22+/PW6//faIiOjatWtsuumm0blz51h//fWjcePGUVZWFpWVlbFixYooLy+P+fPnx5dffhmzZ8+ODz/8MBYuXJjnp8qf8vLyGDVqVIwaNep/fq5169ax6aabRseOHaNjx47RqlWrKCsri4YNG8aKFStiyZIlsXTp0vjiiy/igw8+iGnTpsWKFSuqveHqq6+OzTffPB+PA3WCTzXAuqpfDtmXCrZizb0/zZBLImKfiHh0LfvGr+H1dmt5/3dZbw2vzypQLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtVRJSUn07t07Ntlkkxg+fHjMmDGj2JO+0wYbbBCHHnpotGnTpthTAGCN9t9///jDH/4Qp5xySqRpmtPZqqqqmDJlSkyZMiWvm1q2bBkjRoyIzp075/Ve1h2DBg2KxYsXxxlnnFGt85WVlTF58uSYPHlynpf9t+OOOy5uu+22gtz9bXr27BmPP/54HHTQQbFy5coa6/22HX/+85+jpKSkaBv+U2lpaTz++OMxePDguOeee9bqrk8//TQ+/fTT/AyrpRYsWBCvv/56jXQNHDgwzjnnnBrpgtqi9nx3BMivvXLIvlSwFfnrzeV5vsvfImLxal7fLg8d1bn3swL1AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQy7Vt2zYGDRoU++67bzRs2LDYc/5Nw4YNY999941BgwZFmzZtij0HADI76aST4tZbby32jIiIaNasWbzwwgux7bbbFnsKtdzpp58eN998c5SUlBR7yr8ZNGhQ3HfffTW+q1+/fvHMM89E06ZNa7T3nzbeeOOi9q9OaWlp3H333XH55ZfXuq+X76sBAwbEAw88UOwZUON8BwLWOUmStIiIjTPGP0vT9MtC7lmNv+WQ3W5ty9I0XRURo1cT2TpJkrK17fkWO67mtVURMaUAnQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1BElJSXRu3fvOPPMM6N///7Rpk2bou5p06ZN9O/fP84888zo3bt3lJSUFHUPAFTHz3/+83jkkUeicePGRdvQrVu3GDduXOy0005F20Ddcvrpp8czzzwTLVq0KPaUqFevXtxwww1x7733Fu3zYN++fWPUqFHRqVOnGu3daaedYvz48dG5c+ca7c3VJZdcEq+88kp06dKl2FO+184777x47LHHorS0tNhToMb51wJgXbRtRCQZs28WcsjqpGn6UUQszBjfKkmS+nmofWw1r9WPiL556PgfSZJsGRGr+6T7dpqmK/LZCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA3dSoUaPYeeedY8iQIXHcccfFZpttFkmS1Eh3kiSx+eabx3HHHRdDhgyJnXfeORo1alQj3QBQKEcddVT8P3bsPUazu77v+Od35rK7s8zsxV7vrsP6BjY2UWxCGqAoxjXlZgdCkiIMTYIsoNwSIUNFGkSlJBVSQioUoaY0FSmmIUAqkgbCJbWS2CkNiItxwS5Oshhs1wYcL77N7I3Zmfn1DxwnNHj3Od7nzG+f3ddLOto/nu/5fd9n9OjR6nzmM5/Jeeedt+67n/e85+XGG2/MxRdfvO67mWxXXHFFvvjFL+ayyy5r1nD++efn+uuvz5vf/OZmDX/naU97Wr70pS/lhS984eC7Sil57Wtfm+uvvz47duwYfN84XHrppfnyl7+cN77xjZmZmWmd832df/75ec1rXtM6Y+zOPPPM/PEf/3F+4zd+I13Xtc6BJnzzgZPRU3vM3jRYxWi+OOLchiQ/OIZ9f5Rk6Sifv24MO/6h1x/j80+OeR8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOulJLzzjsvL3vZy3LNNdfksssuy44dOwbZtWPHjlx22WW55pprctVVV+W8885LKWWQXQDQwiWXXJJbbrklb3vb27Jhw4bB9+3atSu/+7u/m+uuuy7bt28ffB8npyc84Qm54YYb8p73vCc7d+5ct72bNm3K2972ttx888151rOetW57j+X000/Pxz72sXzoQx/KOeecM8iOJz3pSbn++uvz27/925mbmxtkx1C2bNmSd73rXfnKV76Sl7zkJem6rnVStm3blle+8pW54YYbsnfv3rzmNa95zGd98IMfzGtf+9rs2bNnjIWP3aZNm/KWt7wlt956a170ohe1zoGmplsHAAzg4h6zfzVYxWj+Osk/H3H2kiRfOp5ltdZDpZT3J3nDo4y8oJTyg7XWrxzPniQppZyR5OeOMfaHx7sHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICT15YtW3L55Zfn8ssvz+HDh/Otb30r3/rWt/LNb34z3/zmN3P//fePfNb27dtz5pln5swzz8zu3buze/fubNy4ccB6ADgxzM3N5e1vf3uuvvrqvOMd78gHPvCBHDp0aKw7du3alde97nV505velIWFhbGezamplJJXv/rV+Zmf+Zn8zu/8Tt75znfmzjvvHGTXli1b8vrXvz5vfvObs2PHjkF2jMPLXvay/NRP/VSuvfbavPvd784tt9xy3Gc+7WlPy1ve8pb89E//dLquG0NlO+eff34+/OEP54477si73/3uXHvttfn2t7+9bvv37NmTK664Ij/xEz+R5z73uZmdnR3LuVdeeWWuvPLKJMmXv/zlfOITn8gnP/nJfP7zn8+RI0fGsmMUu3fvzqte9aq84Q1vyO7du9dtL5zISq21dQNwAiqlXJ3k2hHHf7XW+ivD1fRTSvlUkktHHL+k1nrzkD1HU0q5Jslvjjj+72qtvzyGnecm2Ztk+lFGPp/kmbXW1ePc8wdJ/sVRRj5da/2x49lxKiqlLCaZf7TP5+fns7i4uI5FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC9VldXs3fv3pHnL7jggkxNTQ1YxMns8OHD2bdvXw4dOpSVlZVHrunp6UeuTZs2ZceOHdm4cWPrXAA4Idx3331573vfm4985CP53Oc+l9XV1cd0zubNm3P55Zfnqquuyktf+tLMzs6OuRT+3traWj71qU/lgx/8YD72sY/lnnvuOa7zFhYW8pznPCcvf/nL88IXvnAi/6/4uc99Lh//+Mdz3XXX5Utf+lKOHDlyzHtOP/30POUpT8mVV16ZF73oRXniE5+4DqVtrKys5FOf+lQ++tGP5k/+5E/y1a9+dWxnl1Jy7rnn5hnPeEYuvfTSPOtZz8qTn/zksZ0/isOHD+fGG2/MZz/72Ueub3zjG2Pd8cQnPjHPf/7z8+IXvziXX355pqenx3r+ieZUeJ+xsLCQpaWlo40s1VoX1qtn0pVaa+sG4ARUSrk6ybUjjv9qrfVXhqvpp5RyV5LHjzi+udZ6cMieoyml/HiSj484/v5a6yvGtPe/JHnlUUZ+vdb61uM4/3VJ/tMxxl5Uax312XlYKWUxyfyjfT4/P5/FxcV1LAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA77W6upq9e/eOPH/BBRdkampqwCIAAB7NAw88kOuvvz633HJLbr311uzduzf3339/lpaWsn///kxNTWV+fj6Pe9zjsnPnzlx00UW56KKL8tSnPjWXXnppNmzY0PoROEV97Wtfy6c//encfPPN+frXv57bb7899957bw4ePJgDBw5kbW0tc3NzmZuby7Zt23LuuefmvPPOy0UXXZRnPvOZueSSS9J1XevHGJuVlZXcdtttue222/Lggw9m//79WV1dzfz8fObn53PaaaflwgsvzBlnnNE6tZkHHnggX/jCF3LTTTfl9ttvz5133pm77rorDz74YA4ePJhDhw5leXk5MzMz2bBhQzZv3pzt27fn9NNPz5lnnvnId+jCCy/MxRdfnIWFhdaP9I/ce++9ue222/K1r33tkevOO+/MQw89lP3792f//v1ZWlrK4cOHv+c5d+zYkZ07d+ass87Kk570pFx00UV5+tOffsp9X06F9xkLCwtZWlo62shSrfXE+3KfoEqttXUDcAIqpVyd5NoRx3+11vorw9WMrpQym+RQklH+l/ztWuuOgZOOqpTyQ0luHnH8L2utl45p7xlJ/ibJ1qOMvaPW+kuP4eyfT/IfkpSjjN1Qa31237NJSimLSeYf7fP5+fksLi6uYxEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfK/V1dXs3bt35PkLLrggU1NTAxYBAAAAHN2p8D5jYWEhS0tLRxtZqrUurFfPpOtaBwCM2dkZ/bftniFDRtSn4dxxLa213pvkXx9j7N+UUv68lPLkUc4spZxVSvmDJL+VpBxldH+SfzVaKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJxYplsHAIzZzh6z9wxWMbpvJ1nJaL/HZ4xzca31vaWUy5K84ihjz07y5VLKnyX5SJLP5Lt/t/uSbM13/97/JMlPJrkiyaZjrU3ymlrr146nHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFqZbh0AMGbbe8z+7WAVI6q11lLKviS7RxifKaXM11qXxpjwuiTnJHnWUWamk7zg4et4vbXW+qExnAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABNdK0DAMbstB6zDw1W0U+fjj7Pd0y11kNJrkzyP8d57vdbleTNtdZ3DLwHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtW1DgAYs9N6zC4NVtFPn47t415eaz2Q5LlJ/uO4z37Yt5P8eK31Nwc6HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANbNdOsAgDHb2mN2caiInvp0bB0ioNZ6JMkvlFI+luRdSZ40hmPXkvzXJL9Ua713DOc1U0p5a5K3tu542HzrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFPZdOsAgDHb0GP2wGAV/fTp6PN8vdVaryul/FCSq5L8QpKnP4Zj7kvy+0neVWv96jj7GtqQZL51BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO1Ntw4AGLOZHrMrg1X006djdrCKh9VajyT5vSS/V0o5K8nzkzwjyUVJzk4yn2RzkuUkB5J8I8nXk9yU5C+T/K9a64nytwUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICxmm4dADBmsz1mVwar6OdIj9k+z3fcaq3/N8l7Hr4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADglNe1DgAYs9kesyuDVfTTp6PP8wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABj1rUOABizPr9rq4NV9NOnw+82AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANNS1DgAYs5Ues9ODVfQz02P2yGAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwDF1rQMAxmy5x+zMYBX9TPeYPTJYBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBM060DAMZsucfsifIbONNjts/zMT7fSbLUOuJh860DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATmXTrQMAxuxIj9nZwSr66dOxPFgFj6rW+mtJfq11R5KUUhaTzLfuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOFV1rQMAxuxAj9n5wSr66dNxcLAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4Ji61gEAY3Z/j9mFwSr66dPR5/kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAMetaBwCM2f09ZucHq+inT8d9g1UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx9S1DgAYs/t6zG4frKKfbT1m7x+sAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADimrnUAwJjd12N212AVIyqlbEiybcTx/bXW5SF7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKPrWgcAjNndPWZ3D1Yxuj4NfZ4NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGEDXOgBgnGqt9yQ5NOL4riFbRtSn4fbBKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICRdK0DAAZwx4hzm0opu4cMGcETeszePlgFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJKudQDAAG7vMfvEwSrGv//rg1UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI+laBwAM4G96zJ4/WMX49+8drAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYSdc6AGAA/7vH7MWDVYzmkh6zNw1WAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIykax0AMICbesz+yGAVx1BKmUty0Yjj99ZavzFkDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBsXesAgAH8dZKDI87+cCml1W/hU5JMjTh704AdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwIi61gEA41ZrXU3yhRHHNyf5kQFzjuayHrOfHawCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGFnXOgBgIH/aY/a5g1WMb2+f5wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG0rUOABjIn/aYfd5gFY+ilLI5yTNHHH8oyecHzAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG1LUOABjIjUkeGHH20lLK7iFjvo+fTLJhxNkbaq0rA7YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI+paBwAModa6luSjI453Sa4aMOf7+Zc9Zv/7YBUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAL13rAIABvb/H7KsHq/j/lFLOSvK8EccPJvmjAXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAHrrWAQAD+oskd484+4OllCsGbPmHrkkyPeLsH9Va9w/YAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPTQtQ4AGEqtdS3J+3rc8m8HSnlEKWVnklf3uOXaoVoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA/rrWAQAD+60kh0ecfWYp5eVDxiT5tSTzI85+sdb650PGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP10rQMAhlRr/dsk7+txyztLKTuGaCmlPDvJ1T1ueccQHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBj17UOAFgHv5FkecTZ3UneX0oZ6+9jKWVnkg8kKSPe8ldJ/nCcDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDx61oHAAyt1np7knf2uOX5Sf5zKaWMY38pZVuS65Ls6nHbG2uta+PYDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxP1zoAYJ28PcldPeZfneR9pZSNx7O0lHJOkuuTXNLjtj+otf7Z8ewFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhtG1DgDGq5Tyz0op9XivJNf2WPvL49hZSrl6oD9Laq0Hk7w+Se1x2yuSfLaU8qN995Xv+tkkNyV5So9b70/ypr77AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgPXRtQ4AWC+11k8keWfP2y5J8rlSyodLKc8tpRz1d7OUMl9KuTrJF5O8P8m2PolJfq7WenfPRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCdTLcOAFhnb03yjCQ/1uOekuQlD18PlFJuTPJ/kjyQ5FCShSRnJPnhJJck2fAY23691vrJx3gvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAJoZTSa77WOlAJAAAAwGj6vp/oum6gEibFdOsAgPVUa10ppbw4yQ1JLn4MR2xL8tyHr3F6X5K3jflMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB1V0rpNb+2tjZQCQAAAMBovJ+gr651AMB6q7Xen+Q5SW5t3fKw30/yqlprbR0CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHC8SikppYw8v7KyMmANAAAAwLEdOXJk5Nmu63q9++Dk1LUOAGih1rovyaVJ/qxxyr9P8rO11rXGHQAAAAAAAAAAAAAAAAA7k+D/AAEAAElEQVQAAAAAAAAAAAAAAAAAAAAAAAAAYzMzMzPy7PLy8oAlAAAAAMfW5/1En/cenLy61gEArdRa70/ygiT/Pkld5/X7k7ys1vqLtdbVdd4NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCo2dnZkWeXl5cHLAEAAAA4tj7vJ/q89+Dk1bUOAGip1rpaa/3FJM9MctM6rf1wkgtrrf9tnfYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKyr2dnZkWeXl5cHLAEAAAA4tu985zsjz/Z578HJq2sdAHAiqLV+NsmPJnllkluGWJHkfyS5vNb60lrrNwbYAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwQpidnR159sCBA1lbWxuwBgAAAODRra6u5uDBgyPP93nvwclrunUAMF611r9IUlp3TKJa61qSa5NcW0p5dpJXJHlBkp3HcexfJ/lEkvfUWv/m+CsBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE58s7OzI8+ura3lwIEDmZ+fH7AIAAAA4PtbWlpKrXXk+T7vPTh5TbcOADgR1VqvT3J9KaUkeWqSf5rkoiRPTvL4JPMPXxuTHEiylOShJF9P8ldJvpLkL2qtd6x7PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAYxs2bOg1v7i4mPn5+YFqAAAAAB7dQw89NPJsKaX3ew9OTtOtAwBOZLXWmuSLD18AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxgeno6c3NzOXjw4Ejzi4uLOe2007Jx48aBywAAAAD+3tLS0sjvL5Jk8+bNmZqaGrCISdG1DgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODks7Cw0Gv+nnvuSa11oBoAAACA77W2tpZ77rmn1z1933dw8upaBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDymZ+f7zV/6NCh7Nu3L7XWgYoAAAAAvmttbS133313VlZWRr6nlNL7fQcnr651AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACef6enpzM3N9brnvvvuy759+1JrHagKAAAAONWtrq7mrrvuyoEDB3rdNz8/n67rBqpi0ky3DgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODktGXLlhw8eLDXPffdd18OHjyYXbt2ZePGjQOVAQAAAKeaWmsefPDB7Nu3L6urq73v37p16/ijmFjTrQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4OW3ZsiUPPPBADh8+3Ou+Q4cO5fbbb8/CwkIWFhayefPmdF03UCUAAABwsqq1Znl5OUtLS3nooYeyvLz8mM6Zn5/P5s2bx1zHJJtuHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDJqZSSXbt25Y477nhM9y8uLmZxcTFd12Vubi4bNmzI7OxsZmZmMjMzk67rUkoZbzQAAAAwcWqtWVtby8rKSo4cOZLl5eUcOXIkhw4dyvLy8nGd3XVddu7cOaZSThbTrQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4eW3atClbt27Ngw8++JjPWFtby/79+7N///7xhQEAAACMYMeOHZmZmWmdwQmmax0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAye2MM87I1NRU6wwAAACAXjZu3Jht27a1zuAE1LUOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4OQ2NTWVxz/+8em6rnUKAAAAwEhmZmbyAz/wAymltE7hBOQtFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIObm5vLnj170nVd6xQAAACAo5qdnc3ZZ5+d2dnZ1imcoKZbBwDAqaCU8vNJ3jCGozaP4QwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaGJubi579uzJXXfdlbW1tdY5AAAAAP/Ihg0bctZZZ2V6erp1Cicw3w4AWB87kjy5dQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtDY3N5c9e/bk7rvvzurqauscAAAAgEds2rQpe/bsydTUVOsUTnBd6wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOLXNzc3nCE56QrVu3tk4BAAAAyNTUVHbv3p2zzz47U1NTrXOYANOtAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADj1TE1NZffu3dm6dWvuueeeHD58uHUSAAAAcIoppWT79u057bTTMjU11TqHCTLdOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBT16ZNm3LOOedkcXExDz74YA4ePNg6CQAAADjJTU9PZ35+Ptu3b8/s7GzrHCbQdOsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATm2llGzZsiVbtmzJyspKlpaWsri4mIMHD7ZOAwAAAE4SMzMzWVhYyOMe97hs2rQppZTWSUyw6dYBAHCK2Jfk1jGcc2GSbgznAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAJaXp6Otu2bcu2bduysrKS73znO1leXv6e68iRI6m1tk4FAAAATjCllMzMzGRmZiazs7OP/Pt3VymldSInieLlFABMjlLKYpL5R/t8fn4+i4uL61gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG3UWpMka2trjUsAAACA1rquS5KUUhqXnLgWFhaytLR0tJGlWuvCevVMuunWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBXKSVJMjU11bgEAAAAgFNN1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAA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AAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFJ0rQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZF1zoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBSdK0DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmRdc6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUnStAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJkXXOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWJF2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAirQDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWpB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAi7QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBVpBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArEg7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgRdoBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr0g4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFiRdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwIq0AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVqQdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwIu0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAVaQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKxIOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYEXaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK9IOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYkXYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCKtAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFakHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsCLtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAFWkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHQxXB0AAHeDoaGh/4mI92/BqsEt2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBNGq4OAIC7xAMR8Vx1BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP83WR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBfD1QEAcJf4IyJ+ugV7dkZE3oI9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3IShjY2N6gYA4AYNDQ0tRcTEf7s/MTERS0tLd7AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4/25ycjIuXrz4dyMXNzY2Ju9UT3dZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0kdUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdZHUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXWR0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBFVgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHSR1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1kdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBdZHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0EVWBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdJHVAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXWR1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAF1kdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQRVYHAAAAAAAAAAAAAAAAAAAAAAAAAAAA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33wzBoPBbS7+e/v27Yt33333unPvvPNO7Nu377pzi4uL8emnn8aXX34ZR44ciZv5ru3IyEi88cYb8fbbb8dbb73V8v9uY2Mjjhw5Et9++20cOnQojhw5Er/++usNnx8fH48XX3wxpqen4/XXX49XXnklMvN/2bnPMCnLsw3A98wuS2+iKFVUEJCICBZsgEYwVhSJPRGjEU00+aImGkvUWGOLRk0wKoLd2CVGRRAQFCyIgAJKE6RJlbrswu5+P4yJGpR3YWdmkfM8jjmEd67nua+Zeaf4gzeDjTeuT58+MXDgwI3mHnjggejTp89Gc2+88UY88MAD8fLLL8fcuXPL1aVu3brx+eefl2vNxsyfPz9Gjx4d7733XkyYMCE+/PDDmD17duL395d22GGH2HPPPaNTp07xwx/+MA444ICoUqVKhXbdmBYtWsSsWbOyOjOJbF7n+r333ovXXnstRo0aFW+99VYsWLAg8do6derEXnvtFQceeGB06dIlunbtWik+h4YPHx4HH3zwRnNdu3aN4cOHbzS3YMGCuO++++KFF16IsWPHRmlpabn6PPvss3HssceWa823WblyZbz66qvx5ptvxpgxY2Ly5MmxdOnScu9TpUqVaNq0abRo0SJ22mmn6NSpU3Tu3Dnat29fKV5DAAAAAAAAAAAAAAAAAADYUtSpUydWrlz5XZGVZWVldbLVZ0uXyuY/uAcANk8qlVoREbW/7f7atWvHihUrstgIAAAAAAAAAAAAAAAAAAAAAADYGs2aNSseeuiheOaZZ2LcuHEVvn+NGjWia9eu0b179zj++OOjefPmFbp/t27dYsSIERvNDRs2LLp167bB+9auXRt//vOf44477ojPPvuswro1bdo0rr766ujTp0+k0+kK2zeJinheMq1FixYxa9asjeZmzpwZLVq0yHyhSuy5556LSy+9NCZPnlxhe+bn58eJJ54Yf/jDH2LXXXf91tyW9DrNnTs3HnrooXjiiSfi/fffr7B9a9asGUcffXT07ds3Z++XAQMGxBlnnLHR3Omnnx4DBgz41vuXLl0aN9xwQ/z973+v0OvdtWjRIq688sro06dPhe2ZSePGjYuHH344/vGPf8ScOXMqbN9GjRrFCSecEL/85S+jVatWFbZvefTp0ycGDhy40dwDDzzwra9XWVlZPProo3HLLbds1nupbt268fnnn2/y+oiIJUuWxJAhQ2Lw4MExbNiwmDlz5mbt923q1KkTRx55ZPTt2ze6du2akRnflPTzNdsyfZ3rWbNmxX333RePPfZYTJ8+vcL23XbbbePHP/5x/OxnP4u99tqrwvYtr+HDh8fBBx+80VzXrl1j+PDh33r/pEmT4pprromnn3461q1bt8l9nn322Tj22GM3ef369evjueeei/79+8fQoUOjuLh4k/famOrVq0enTp2iS5cu0bt379hzzz0zNgsAAAAAAAAAAAAAAAAAAL4P6tSpEytXrvyuyMqysrI62eqzpcvuFYIAAAAAAAAAAAAAAAAAAAAAAAAAgC3W6NGj48c//nHssssuccUVV8S4ceMyMmfNmjXx0ksvxQUXXBA77bRTHHHEEfHss8/G+vXrMzKvvEaOHBnt27ePSy+9ND777LMK3XvOnDlx5plnRqdOneL999+v0L3ZOsyYMSO6dOkSxx13XEyePLlC916/fn088sgjsccee8SNN95Yad6Tm+Kjjz6KM888M3beeef4/e9/X+Hvt9WrV8fjjz8eBx98cOy///7x6quvVuj+2fLoo49G27Zt45ZbbokVK1ZU6N6ffPJJnHHGGXHwwQfHrFmzKnTvijR06NDo3r17dOzYMW677baYM2dOhe4/f/78uOOOO6JNmzZx8sknx0cffVSh+2fDxIkTo0uXLnHaaafl7Ltr7ty58Ze//CW6desW22+/fZx00knRv3//mDlzZsZmrlixIh577LHo1q1btGvXLp555pmMzdpaTZ06NX72s59Fq1at4tprr43p06dX6P6LFy+Ov/3tb7H33nvHYYcdFiNHjqzQ/bNl9erVcfHFF0eHDh3i8ccfj3Xr1uWkx/r16+Pvf/97tGjRIn784x/HSy+9FMXFxRmdWVhYGKNGjYrrr78+OnbsGC1btozf//73Ff4bCAAAAAAAAAAAAAAAAAAAYEPSuS4AAAAAAAAAAAAAAAAAAAAAAAAAAFRuM2fOjF69esX+++8fTz31VJSUlGRtdmlpabz00kvRq1evaNasWcycOTNrszfk2muvja5du8bUqVMzOuf999+Pzp07x5133pnROXy/PPTQQ9GhQ4cYOXJkRuesXbs2fv/730eXLl1i8eLFGZ1V0ZYvXx7nn39+tGvXLvr37x/FxcUZnzl69Ojo0aNHnHTSSbFgwYKMz6sIa9asiRNOOCFOPfXUWLhwYUZnDR8+PPbee+8YNWpURueU19SpU6NHjx5x6KGHxpAhQzI+r7S0NB5//PFo3759XHXVVVFUVJTxmRXhnnvuiU6dOuXs9Xv00Ueje/fu0bx58/j1r38dI0aMyOrvlC9NmjQpjj/++Nh///1jypQpWZ//fVNUVBR/+MMf4gc/+EE88MADsW7duozPHDx4cHTp0iVOO+20WLRoUcbnVZSPPvoo9txzz7jpppuy8jx9m7Fjx0aHDh2ib9++MXfu3Jz1mD59etx4443xpz/9KWcdAAAAAAAAAAAAAAAAAACArUc61wUAAAAAAAAAAAAAAAAAAAAAAAAAgMqptLQ0rr/++mjbtm08++yzua4TCxYsiOXLl+dkdklJSZx99tlxxRVXRFlZWVZmFhUVxa9+9as499xzo7S0NCsz2XL94Q9/iJ/+9KexcuXKrM0cPXp07L///jF9+vSszdwcgwYNijZt2sRdd90VJSUlWZ//xBNPxA9+8IMYMmRI1meXx9y5c6NLly7x5JNPZm3mokWLokePHjFixIiszfw2ZWVlcf3118fuu+8er776atbnFxcXx9VXXx377rtvfPLJJ1mfn1RpaWmcf/75cc4558S6dety1uNXv/pVDBkypNJ8T44ePTo6deoUf//733NdZYv1wQcfxB577BHXXHNNFBcXZ33+I488Em3atIlBgwZlfXZ5vfrqq9G5c+eYOnVqTnvceeed0blz5/jwww9z2gMAAAAAAAAAAAAAAAAAACDb0rkuAAAAAAAAAAAAAAAAAAAAAAAAAABUPp999ln06NEjLrvssigqKsp1nZzr27dv3HvvvTmZ3a9fvzjppJNi/fr1OZlP5XfuuefGNddck5PZU6dOja5du8bcuXNzMj+JkpKSuPTSS6Nnz56xYMGCnHZZsmRJ/OhHP4rbb789pz2+zbx586JLly4xduzYrM8uLCyMo48+OiZOnJj12V9atmxZHHnkkZXiu2/8+PGx1157xfDhw3Pa49v84he/iLvuuivXNSqlNWvWRN++feN3v/tdrqtscZ555pnYb7/94qOPPsppj6VLl0bPnj3juuuui7Kyspx2+TbDhw+Po48+Oj7//POc9vjd734Xv/rVr/xOBQAAAAAAAAAAAAAAAAAAtkrpXBcAAAAAAAAAAAAAAAAAAAAAAAAAACqXyZMnR6dOnWLo0KG5rlIp3HDDDXH//ffntMOTTz4Zv/jFL3Lagcrp8ssvj379+uW0w9y5c+Poo4+O1atX57THhqxduzaOOeaYuOGGG6KsrCzXdSIioqSkJH7zm9/Eddddl+sqX7N06dLo0aNHzJgxI2cdVq5cGSeeeGKsWbMm67NnzpwZe+21V7z00ktZn/1tlixZEkcccUQMGTIk11W+5qqrrop77rkn1zUqvZtvvjl++ctf5rrGFuO+++6L3r17x6pVq3JdJSIiysrK4vLLL49f/OIXleb740sTJkyIY489NoqKinLa44Ybboibb745px0AAAAAAAAAAAAAAAAAAAByKT/XBQAAAAAAAAAAAAAAAAAAAAAAAACAyuOdd96Jww8/PJYsWZLrKpXCq6++GpdddlnifOvWrWP33XePXXbZJerUqRMFBQWxatWqWLhwYUyePDnefffdWLVq1SZ1uffee6NFixZx6aWXbtJ6vn/69+8f11133Savr1atWnTs2DFat24dTZs2jZo1a0Y6nY6VK1fG/Pnz4+OPP46xY8fG6tWrN7rXuHHj4uyzz45HHnlkk/tUtDVr1sQxxxwTQ4cOzXWVDbr88sujoKAgfvvb3+a6SpSUlMRxxx0XH374YaJ8gwYNomPHjrHzzjvHDjvsEDVq1IhUKhWrVq2KTz/9NCZPnhxjx46NdevWlbvL5MmT49JLL43bb7+93Gs31bRp0+KQQw6JTz/9NGszkyosLIxjjjkmXn755ejSpUuu68S//vWvuPrqqxPnmzVrFrvvvnvsvPPO0aBBg6hZs2aUlJT857tx0qRJMWHChFi5cmUGW+fOX//612jZsmX85je/yXWVSm3AgAFx9tlnR1lZWa6r/I9+/fpFXl5e3HXXXbmuEhERq1atiuOOOy6WL1+eKF+zZs3Yc889Y5dddvnPd32VKlVi1apVsXz58vj444/jww8/jFmzZpWrx2uvvRaXX375pjwEAAAAAAAAAAAAAAAAAACA7438XBcAAAAAAAAAAAAAAAAAAAAAAAAAACqHDz/8MLp37x7Lly/f5D1atmwZBx10UHTu3DlatmwZLVq0iPr160eNGjUiPz8/CgsLY8WKFTFv3ryYM2dOfPjhhzFx4sR44403Ys6cORX4aDbfqlWr4rzzzouysrLvzLVu3TrOPffcOP7446Np06bfmV23bl2MHDky7r///njqqaeiuLi4XJ2uuOKKOPDAA6NLly7lWsf3z4cffhjnnXdeuddVqVIlevbsGT/72c+iW7duUb169e/MFxcXx6hRo2LgwIHx5JNPRmFh4bdmH3300TjppJPK3SkT1q9fHz179oyhQ4du0vq6devGD3/4w9hnn32iQ4cO0bx589hhhx3+81m2evXqWLx4cUyfPj3eeeedGDZsWAwbNixKSkrKNeeSSy6J3XbbLY488shN6llRrrzyynj99de/M7PLLrvET3/60+jdu3fstttuG91z9erV8fzzz8ftt98e77zzTrn63H333XHOOedEmzZtyrVuU8ydOze6desWc+fO3aT1zZo1i0MPPTT22muvaNeuXTRv3jwaNGjwn/fW6tWrY+7cuTF16tQYPXp0vPLKKzF+/PhyzSgsLIzevXvHu+++G82bN9+knhVh6dKlcemll240t+eee8ZPf/rTOPbYY6NFixYbza9bty6GDRsWDz74YLz88ssV0PR/5efnxw9+8IPo0KFD7LrrrrHrrrtGo0aNYvvtt49tttkmqlatGtWqVYs1a9bE8uXLY/ny5bF06dKYOHFivPvuuzF27NiYOHFilJaWlnv2RRddFPvuu2/sv//+m/04Pvnkk2+976qrroqrr756o3tceeWVcdVVV212l4oydOjQOOusszb6e2tD0ul07LfffnHYYYdFp06dok2bNtGgQYOoVatWrF27Nj7//POYNm1aTJw4MQYPHhxDhgz5zu+xb3P33XdHs2bN4uKLLy732op24YUXxowZM74z06BBgzjllFPipJNOin322Sfy8zd+KfIpU6bE008/HXfeeedGs0VFRfGzn/1sk94P9evXjx/+8IfRoUOHaNmyZbRs2TK23XbbqFmzZtSsWTOqVq0aRUVFUVRUFMuWLYuFCxfGvHnzYurUqfHxxx/H2LFj48MPP4x169aVezYAAAAAAAAAAAAAAAAAAEBFS23KP5YHAHIjlUqtiIja33Z/7dq1Y8WKFVlsBAAAAAAAAAAAAAAAAAAAAAAAfF8sWLAgOnfuHLNmzSr32rp168bZZ58dp556auyxxx6b3GHmzJnx4osvxgsvvBCvvfZalJSU/E9m3Lhx0aFDh02eERHRrVu3GDFixEZze+yxR4wfP/5b799+++3jhhtuiD59+kQqlSp3j08++SQu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c10AAAAAAAAAAAAAAAAAAAAAAAAAAMidCRMmxB//+MdyrTn11FPj9ddfj1atWmWo1X+l0+no2bNnjB49Ov75z3/Gtttum/GZ3+XII4+MRx99NPLz8yt03y5dusQLL7yQeN/S0tK46KKLKrQDW4ZrrrkmVq1alShbUFAQgwYNigMOOKDCe+y2224xePDgqFu3boXvvanKysriZz/7WaxZsyZRvn79+jFkyJD45S9/GalUqsL7nHHGGfH0009HQUFBovzll18ehYWFFd5jU/z973+Pc889t8L3bdmyZfz9739PnH/yyScrvENExMKFC+P8889PnN9jjz3i7bffjoMPPrjCu1SpUiX++te/xqWXXpooX1xcHL///e8rvMemSKfT8eCDD8YJJ5yQsw4nnnhifPDBB/HMM8/EIYccktXZTZo0iX/+859x+umnJ8ovWbIk+vXrl+FWW4bFixfHJZdcUq41t9xyS1x33XWRTlfcZbVPPvnkeP7556NatWqJ1wwYMCBef/31CuuwuY4++uh45JFHomrVqlmZ98orryTKtWvXLgYMGJC1XhFffCYdc8wxMWrUqLjxxhuzNhcAAAAAAAAAAAAAAAAAANh6Vdy/gAcAAAAAAAAAAAAAAAAAAAAAAAAAtjgXXnhhrFu3LnG+T58+8dBDD0W1atUy2GrDjjzyyGjatGnW535p1113jUcffTTy8vIysv/BBx8cf/7znxPnhwwZEmPHjs1IFyqnhQsXxoABAxLn77zzzjjooIMy1qddu3bxyCOPZGz/8nr88cdjxIgRibK1a9eOV155JaPPT0TEUUcdFffcc0+i7GeffRZ/+9vfMtoniYsuuijOOuusjO3fq1evOPTQQxNlJ0+eHFOmTKnwDldccUUsXrw4UbZdu3YxdOjQaNKkSYX3+Krrrrsu+vTpkyg7aNCgSvH5f8kll8RJJ52U0w5333137Lbbbjmbn5eXF/fff38cdthhifL9+/fPcKMtw2233RbLli1LnL/gggviwgsvzEiXww47LO67775yrbniiisy0qW8dt1113jsscciPz8/azPfeOONRLnbbrstatSokeE2326HHXbI2WwAAAAAAAAAAAAAAAAAAGDrkc51AQAAAAAAAAAAAAAAAAAAAAAAAAAgN1599dUYMmRI4vzhhx8e999/f6RSqQy2qpzS6XQMGDAg6tSpk9E55513Xhx66KGJ87fccksG21DZ/PWvf421a9cmyh5xxBFx9tlnZ7hRxJFHHhk///nPMz5nY9avXx9XXnllomwqlYpHHnkk9t577wy3+kKfPn3irLPOSpS9+eabY/369Rlu9O06dOgQN9xwQ8bnXHHFFYmzI0aMqNDZ06dPj/79+yfKNmjQIF588cVo0KBBhXb4Nv369Yt27dolyt54440ZbvPdOnXqFFdffXVOO1QWeXl5MXDgwETnyeTJk+Ott97KQqvKa9myZXHXXXclznft2jVuvvnmDDaKOPXUU+PXv/514vzrr78er7/+egYbbVw6nY5HH300atasmdW5U6ZM2WimWbNm5fo9CwAAAAAAAAAAAAAAAAAAsKVK57oAAAAAAAAAAAAAAAAAAAAAAAAAAJAbV155ZeJsixYt4pFHHol0euu8lOFZZ50V++23X1Zm9evXL6pUqZIo+9RTT8XixYsz3IjKoKysLAYOHJgoW6VKlfjLX/6S4Ub/deONN0a9evWyNm9DHnzwwZg6dWqi7K9//es4+uijM9zo62699dZo3LjxRnMLFiyIF198MQuNNuzvf/975OfnZ3xOly5dok2bNomyI0eOrNDZV199daxfvz5R9v77748dd9yxQud/l6pVq8YDDzwQqVRqo9nnn38+Fi1alIVWG3bHHXdk5VzZUmy//fZx2WWXJco+//zzGW5Tud17772xcuXKRNmaNWtG//79s/L784YbbohWrVolzt9yyy0ZbLNxZ555ZnTq1CmrM9esWRNLlizZaG7ffffdav+fAQAAAAAAAAAAAAAAAAAA2Lr4l9UAAAAAAAAAAAAAAAAAAAAAAAAAsBV6//33Y/To0Ynz/fr1i/r162ewUeVVrVq1+MMf/pC1ebvsskuceeaZibLr16+Pf/zjHxluRGXw5ptvxieffJIoe+aZZ8Yuu+yS2UJfsc0228Rvf/vbrM3bkDvvvDNRrlmzZnHttddmuM3/qlOnTlx++eWJsvfff3+G22xYz549Y++9987avF69eiXKjRs3rsJmLlq0KJ544olE2V69ekXPnj0rbHZSe++9d/z4xz/eaG7dunXx0EMPZaHR//rRj34UBxxwQE5mV2Z9+/aN2rVrbzQ3ZMiQLLSpvAYMGJA4e9FFF8XOO++cuTJfUb169bj11lsT51966aVYuHBhBht9uypVqmT1t+mXVq5cmSjXtGnTDDcBAAAAAAAAAAAAAAAAAACoHNK5LgAAAAAAAAAAAAAAAAAAAAAAAAAAZF+/fv0SZ3v16hWHHXZYBttUbj/5yU+iSZMmWZ158cUXRzqd7LKRjz76aIbbUBk8+eSTiXKpVCr+7//+L7NlNqBv375RrVq1rM+NiHjnnXfi/fffT5T9wx/+EDVr1sxsoW9x5plnxrbbbrvR3ODBg2PNmjVZaPR1F1xwQVbnde/ePVFu2rRpUVJSUiEzBwwYEMXFxRvNpdPpuP766ytk5qa4+OKLE+WeffbZDDfZsN/85jc5mVvZ1ahRI4455piN5saOHRvLly/PQqPK55133onJkycnyjZo0CAuvPDCDDf6uqOPPjr233//RNn169fHww8/nOFGG9a7d+9o2rRp1ucm+fyMiMjPz89wEwAAAAAAAAAAAAAAAAAAgMoh2RWCAAAAAAAAAAAAAAAAAAAAAAAAAIDvjXXr1sXjjz+eKJtKpeLKK6/McKPK7Zxzzsn6zBYtWsSPfvSjRNnRo0fH559/ntlC5Nyrr76aKNe1a9do3bp1htv8rwYNGkTv3r2zPjcion///olyjRo1itNPPz3Dbb5dQUFB/PSnP91orqioKIYNG5aFRv+1yy67RJcuXbI6c6+99op0euOXxy0uLo6ZM2dWyMyk50qvXr1y8j76UseOHaNjx44bzY0ZMyaWL1+ehUb/1bhx4+jevXtWZ25JDjnkkI1mSktLY+LEiVloU/k888wzibNnnXVW1K5dO4NtNuyCCy5InC3P46lIufouq1atWqLcp59+muEmAAAAAAAAAAAAAAAAAAAAlcPGr5wBAAAAAAAAAAAAAAAAAAAAAAAAAHyvjBw5MpYvX54o26NHj2jfvn2GG1VerVu3jo4dO+Zk9imnnJIoV1paGiNGjMhwG3Lps88+i0mTJiXK9urVK8Ntvl3v3r1zMveFF15IlDv99NOjSpUqGW7z3Y455phEucGDB2e4ydcdffTRWZ0XEVGrVq1o3rx5ouy8efM2e97HH38cU6ZMSZQ966yzNnve5kpyrqxfvz5ee+21LLT5r169ekUqlcrqzC1J0t9MEydOzHCTyunVV19NnO3bt28Gm3y7nj17RqNGjRJl33rrrVixYkWGG31d/fr145BDDsnqzK/OzsvL22huyJAhsW7duiw0AgAAAAAAAAAAAAAAAAAAyK10rgsAAAAAAAAAAAAAAAAAAAAAAAAAANn1z3/+M3G2T58+mSuyBejZs2fOZh955JGRn5+fKDts2LAMtyGXRo0alTh79NFHZ7DJd+vRo0dUrVo1qzPff//9mDdvXqLsSSedlOE2G3fAAQdEjRo1Npp7++23s9Dmv3r06JHVeV9q1apVotzChQs3e9a//vWvRLkGDRpE9+7dN3ve5kraIdvnyg9/+MOsztvStGjRIlHuww8/zGyRSmjJkiUxbty4RNm99tordtpppww32rD8/Pzo1atXouz69etj+PDhmS30DV26dIkqVapkdeaX8vPzo2nTphvNLVmyJO6///4sNAIAAAAAAAAAAAAAAAAAAMitdK4LAAAAAAAAAAAAAAAAAAAAAAAAAADZNWzYsES5GjVqRM+ePTPcpnI79NBDcza7Xr16sddeeyXKjh07NsNtyKUJEyYkyjVt2jRatGiR2TLfoXr16tGpU6esznzllVcS5Ro1ahR77LFHhttsXH5+frRv336juYkTJ0ZpaWkWGn0h26/blxo2bJgot3jx4s2elfRc6d69e6TTub9sb4cOHSIvL2+juffffz/zZb7ioIMOyuq8LU3t2rUT5ebOnZvhJpXPmDFjEn+uHXvssZktsxG9evVKnH3jjTcy2OR/denSJavzvqlDhw6JchdffHGMGzcus2UAAAAAAAAAAAAAAAAAAAByLPdXqAAAAAAAAAAAAAAAAAAAAAAAAAAAsmbt2rXxwQcfJMoedNBBUb169Qw3qrzS6XR07tw5px3222+/RLmkrylbpqSvb9LzJZP233//rM576623EuUOOuigDDdJbrfddttoZvXq1TF9+vQstIlo2LBhNGzYMCuzvmnbbbdNlCssLNzsWW+//XaiXJcuXTZ7VkWoUaNG7LjjjhvNTZgwIQttvtC0adNo0KBB1uZtiapWrZooN3/+/Aw3qXzGjx+fONu1a9cMNtm4/fffPwoKChJls/kejIjYY489sjrvm7p165Yot2LFiujWrVs8//zzmS0EAAAAAAAAAAAAAAAAAACQQ+lcFwAAAAAAAAAAAAAAAAAAAAAAAAAAsmfChAmxfv36RNkf/vCHGW5Tue26665Ru3btnHbYa6+9EuU+//zzmDNnTobbkCtTpkxJlGvXrl2Gm2zcbrvtltV57733XqJc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tl69enHAAQdkuBEAAAAAAAAAAAAAAAAAALC1Sue6AAAAAJVHWWlZfDp5afzrbxPiwUvfjHdf/CSWzsvMBSaXzlsd7774STx42eh4qd/E+HTy0igr3fouUAgAAAAAAAAAAAAAAAAAAACQa1WqVIkHH3wwCgoKEq9ZunRpHH744XHRRRfF6tWZuT5FRERZWVm89NJL0b1799hnn31i8ODBUVaWvWtUVKtWbYPHCwsL47jjjouLLroo1qxZs1kz3njjjejUqVMMHjw48ZpUKhV33nln5Ofnb9bsb9O3b9/E2bfeeit69epVYefBzJkzo0uXLvHYY49VyH7fV9WqVYvHH3/8W8/Rb/P0009H27Zt48QTT4xXXnkl1q5du9E169atixEjRsQZZ5wRu+yyS9x///3f+T7829/+FjVr1ixXr4r0hz/8Ifbff//E+YULF0b37t3j3HPPjcWLF2ew2dctX748HnjggTjwwAOjQ4cOce+990ZRUVHW5m/t0ul0PPzww9GgQYPEa955553Yfffd4/bbb4/i4uIMtvu6WbNmxY033hgtW7aMI444Il5++eWsza6Mevbsmfizr7i4OI477rh49dVXK2z+6NGjY999941hw4ZV2J4V6Zhjjkmcvf/++2PvvfeOp59+OgoLCzPYasP69esXVatWTZx/5513Yr/99ovx48dXyPwFCxZEjx494oknnijXuttvvz3q1atXIR22VCUlJfHEE0/EQQcdFHvssUfceeedsWjRoqzMfuihh+Loo4+O0tLSRPkzzjgjqlSpkuFWAAAAAAAAAAAAAAAAAADA1iozVwACAABgi1K0Zl1MGb0gPnh9bnz+2eZdqLa8ykrLYsb7i2LG+4ui3vY14gddmkSb/XaIqjVcgAsAAAAAAAAAAAAAAAAAAAAgW9q3bx+33nprnH/++YnXlJSUxK233hpPPPFE/O53v4szzzwzatSoUSF9pk6dGo8++mgMHDgwZs6cWSF7boorrrgirrjiiigtLf2f+8rKyv7z+C+77LL4yU9+EjVr1ky899ixY+Pmm2+OJ554oty9fv3rX8ehhx5a7nVJ9e7dO3bccceYNWtWovzLL78cnTt3jgEDBkSnTp02aeaKFSvijjvuiBtuuCEKCws3mGnYsGGsX78+li5dukkzvm/at28fd9xxR/Tt27dc69atWxf/+Mc/4h//+EdUq1YtOnXqFG3atIkmTZpEzZo1I5VKxapVq2L+/Pnx8ccfx9ixY2PVqlWJ9j755JPjmGOOiV/96leb8pAqRF5eXjz22GOxzz77xGeffZZoTVlZWfTr1y8eeeSROP/886Nv377RvHnzCu+2YMGCePnll+OFF16If/3rX1FUVFThM0iuSZMm8eCDD8YxxxwTJSUlidasXr06fvOb38Qdd9wRF198cZxyyilRp06dCu82efLkeOmll+KZZ56JN998M8rKyip8xpaqXr168ZOf/CTuvffeRPmVK1fGYYcdFr/5zW/immuu2eTfKnPmzInrrrsu/v73v2/wd8GXDjnkkHjttdc2aUZFaN68eRx44IExatSoRPn33nsvevfuHdWqVYs999wzWrduHY0aNYq6detGQUFBpFKpRPv83//9X7m7tmrVKq655pr43e9+l3jNxx9/HJ07d46LLrooLr744qhVq1a555aWlsb9998fl112WSxatKhca3v16hUnnnhiuWd+n02YMCF+9atfxQUXXBDdu3ePnj17xpFHHhlNmzat0DkffPBBXH311fHUU08lXlO1atWc/iYBAAAAAAAAAAAAAAAAAAC+/1IuCgEAW45UKrUiImp/2/21a9eOFStWZLERAFu60tKymDhsTrz9z5lRXLg+13X+o6B6fuxz1E6x+8FNI51OdkE5AAAAAAAAAAAAAAAAAAAAADbfeeedF3ffffcmra1Xr1706tUrjj/++DjggAOibt26idcuWrQo3nzzzXj99dfjX//6V0yZMuVbs+PGjYsOHTpsUscvdevWLUaMGLHR3LBhw+K5556LO+64Y6PZOnXqxGGHHRaHHnpo7L777rHzzjtHnTp1oqCgIFatWhULFy6MyZMnx+jRo+Oll16K8ePHb1L3Dh06xJgxY6Jq1aqbtD6pBx98ME4//fRyrUmn03H88cfHOeecE926dYt0Ov2d+XXr1sXo0aPjiSeeiIcffvg7r6OVTqfjlVdeibPOOitmzZq10S4zZ86MFi1alKv/lur3v/993HjjjbmuEXvuuWeMHDkyatasGS1atEj0Os2aNSuaN2+ekT7vv/9+dO3adZOuz5ZOp+Pggw+Oo446Krp37x5t27bd6Pn8TcXFxTF16tQYO3ZsjBkzJt58882YMGFCJLkW7KBBg+Koo44qd+9vGjBgQJxxxhkbzZ1++ukxYMCAzZ63Ka666qq4+uqrN5q78sor46qrrspIh/vvvz/OOuusTVpbs2bNOOqoo+KII46Igw8+OJo1a1buPVauXBmTJ0+Ot99+O8aMGRMjR46M2bNnJ15bq1atcs/8pj59+sTAgQM3mnvggQeiT58+mz1vc02fPj122223KC4uLte6+vXrx89//vPo06dPtG3bdqP51atXx/Dhw+Ohhx6K5557LoqKir4zX69evZgwYULiz7VMXRv6ueeei+OOOy4je3+bTX0sZWVlcfzxx8ezzz5b7rXbbLNN/OxnP4vTTjst2rdvH6nUd1+z7JNPPomnnnoq+vXrF9OnTy/3vNatW8fbb78dderUKffajRk+fHgcfPDBG8117do1hg8fXuHzk/q///u/RL+LIyJ+8IMfxEEHHRQHHHBA7LXXXtGyZcvIy8sr17xZs2bFiy++GC+88EIMHjy43OfZZZddFtdee2251gAAAAAAAAAAAAAAAAAAwPddnTp1YuXKld8VWVlWVlbx/7D6eyo/1wUAAADIjc8/WxNDB06OBTOW57rK/yguXB+jnpwa099bGIf8tG3U275GrisBAAAAAAAAAAAAAAAAAAAAbBXuuOOOmDdvXjz77LPlXvv5559H//79o3///pFOp6NNmzbRsmXL2GmnnaJevXpRo0aNyMvLi7Vr18bKlStj3rx5MWfOnJg0aVJ89tlnGXg0FeP666+P119/PcaNG/eduRUrVsSTTz4ZTz75ZMa6NGnSJAYNGhRVq1bN2Iwv/eQnP4m//e1vMWbMmMRrSktL//Mc1K1bNzp37hytWrWK7bffPmrUqBHFxcWxevXq+PTTT2PatGnx3nvvRWFhYaK9L7300jj00EM39eF8r91www2xePHiuO+++3LW4ctzs2bNmuVaV1BQkKFGER06dIjnn38+jjrqqFi9enW51paWlsbQoUNj6NChERFRo0aN+MEPfhA77rhjNG3aNOrWrRvVq1eP/Pz8KCoqiqKioli5cmV89tlnsWDBgpg1a1bMnDkzSkpKMvHQqGBnnnlmLF26NH73u9+Ve+3q1avjiSeeiCeeeCIiIrbddtto165dNGvWLBo3bhy1atWK6tWrRyqViqKioli7dm0sW7bsP+fK9OnTY968eRX9kL73dtlll7jwwgvjhhtuKNe6ZcuWxU033RQ33XRTbLvt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Px6NGjXKyIz27dvH4MGD47777osaNWpkZEZ5nXHGGTFixIiMnwO77bZbjBo1Ki6//PKMztkaHH/88TF58uR45ZVXonfv3pt1Lu26667xu9/9LqZNmxaPPvrod54H8+fPT7TnDjvssMl9Nkf37t1j/Pjx0a9fv2jWrFlOOnzTPvvsE3/+859j7ty58fjjj0fz5s1zXWmrl06n47zzzotp06bFb3/726hVq1auK0VBQUEcddRR8dhjj8XcuXPjz3/+c+Tn5+e6VqXQqlWreOedd+KnP/1pVub16NEjJk6cmLV5m6tOnTpx8803x6effhp33nlndOvWrVKfO6lUKn7961/HpEmT4thjj83q7E6dOsXo0aPjL3/5S6X5DVaZnHfeeXHNNddE586dI52uHJc3/+EPfxhjxoyJW265JapXr57rOgAAAAAAAAAAAAAAAAAAwFam8v7rfQD4HkmlUr+MiF9UwFY1K2APALYiY1/+JMY8NyPXNTLiy8fV6UctclsEAAAAAAAAAAAAAAAAAAAAYCtx3HHHxbHHHhsvvPBC3HrrrTFy5MiMz9xmm23ihBNOiL59+0aHDh0yPq88TjzxxDj22GPjoYceiltvvTWmTJmy2XsecMAB8ctf/jJOPPHESKfTFdCyYnXu3DnGjx8fN998c/z5z3+OpUuXVtjejRs3jgsuuCDOP//8KCgoqLB9t3apVCp69OgRPXr0iKKionjjjTdi5MiRMXny5Pjoo49iwYIFsWrVqlizZk1Uq1YtateuHXXq1Ikdd9wx2rVrF+3atYtu3bpFq1atEs+cNm1aolyjRo029WFttry8vOjbt2+ceeaZ8dxzz8Xdd98dI0aMiLKysqzMLygoiAMPPDCOOOKI6NWrV+y0005ZmUv51atXL2666aa4/PLL44EHHoi//e1v8dFHH2Vtft26daN79+5x1FFHxTHHHBP169fP2uwtTd26dWPgwIFxxhlnxMUXXxxvv/12hc/o3Llz/Pa3v41evXpV+N7ZUK9evTjvvPPivPPOizVr1sTbb78d7733XkydOjVmzJgRn332WSxatChWrlwZRUVFsW7duqx9Lm5I8+bN49lnn433338/brjhhnj66aejpKQkI7MOPPDAuPTSS+Pwww/PyP7fFy1btozLL788Lr/88li0aFG89NJL8eKLL8bQoUNjyZIlWetRpUqVOPbYY+P888+Pgw46KGtzAQAAAAAAAAAAAAAAAAAAvimVy3+YDwBbi1QqdVVEXJnpObVr144VK1ZkegwAW4gPRsyJEY99nOsaGdf1lNbxgy5Ncl0DAAAAAAAAAAAAAAAAAAAAYKvzySefxJNPPhnPPPNMjB07NtatW7fZe+bn58e+++4bhx12WPTo0SP23nvvSKfTFdD267p16xYjRozYaG7YsGHRrVu3RHuOHz8+Bg0aFK+88kpMmDAh0TWhqlevHvvss08cdthhccwxx0S7du0SzaoMVq1aFQMGDIhHHnkkxowZs0l7VKlSJbp06RKnnnpqnHrqqVFQULDRNS1atIhZs2ZtNDdz5sxo0aLFJvVi89x0001x8cUXbzT3m9/8Jm677bYsNEpm7ty58cILL8Tzzz8fb7zxRqxatarC9q5Vq1Z06NAhDjzwwDjooIPioIMOitq1a1fY/mTXhAkT4vnnn49BgwbFuHHjYv369RW293bbbRf77LPPf86TffbZJ/Lz8yts/63J66+/Hvfee28MGjQoli9fvsn77LTTTnHYYYfFmWeeGXvttVeiNf369UuUO+eccza519Zo4cKF8cQTT8QTTzwRb7311ma991KpVOy2227Ru3fvOPnkk6N169YV2HTr9PHHH8fo0aNjzJgxMXr06Pjggw+ipKSkwvavV69edO3aNY4++ug45phjYrvttquwvQEAAAAAAAAAAAAAAAAAYGtSp06dWLly5XdFVpaVldXJVp8tXaqsrCzXHQDgey+VSl0VEVdmek7t2rUTXUQQgO+/qe9+FoPv/zBia/hfvlREjzPbRau9ts91EwAAAAAAAAAAAAAAAAAAAICtVmFhYbzzzjvx9ttvx7Rp0+KTTz6JWbNmxeeffx5r1qyJNWvWRCqVitq1a0etWrWidu3aUbt27WjatGm0adMm2rZtG23atIk2bdpEjRo1Mt63W7duMWLEiI3mhg0bFt26ddukGZ9++ml8/PHH8fnnn8fKlStj1apVUVBQELVq1YptttkmWrduHTvuuGOk0+lN2r8ymTt3bowaNSrGjBkTH3/8ccycOTMWLVoUq1evjqKioqhevXrUqVMn6tevH61atYof/OAH0aFDh+jevXvUrVs31/WpYL17946nn356o7l77703zjrrrCw0Kr/S0tKYNGlSvPPOOzF58uSYPXt2zJo1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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqCUXXXSRHnjggS7vt+666+qEE07Q4Ycfro033ni5Y7Ms04svvqibbrpJf/rTnzRnzpxljp01a5ZOOeUUjR49uss1VcL111+vk08+eYX2NcZoxx131G677abttttOI0eO1NChQ9WvXz81NDSosbFRc+bM0b///W9NmjRJTzzxhO69917Nnj27S3leeOEFHXvssbrttttWqM6e8q9//UunnXbacsc0NDTo8MMP1xFHHKE999xTvXr1Wu74LMv07LPP6tprr9WNN96oQqFQdj3Tpk3TL3/5S1144YVl71OOxsZGHXfccfK+69dtXn311TV27FhtvfXW2nDDDbXhhhtq0KBB6tOnj/r06aP6+no1NjaqsbFRn3/+uWbMmKHp06fr3Xff1TvvvKMXX3xRkyZN6lIfelKSJDrooIM0ceLEFdp/tdVW09ixY7XDDjto66231vDhwzVkyBD17t1bzjktWLBAs2bN0uTJk/XCCy/o0Ucf1aOPPqo0TbuU5yc/+Yk222wzjR8/foXqBKqNy7sAAAAAAED3bfHloZr80gx9PHnZH47WirU3WE1bfHlo3mUAQE2JTCRXZ+XqbN6lVMwG2wzWoGF95QteaeKVJlnTumkpdBAriWc+y/shdJl1UbBcadL1L8ZWBdaZIHnob+Wlycr3HO8uYyJFJsx5omaP4ZjzcCXZOOQ5ouf765NMPklVUNd+8FApxkQysZF1kawzss7oP87aXr36xBXPnRRSLZ6fyMYtuY2NFEXhnkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAT3v22Wd1wQUXdGmfvn376txzz9UPfvAD1dXVlbVPFEXabrvttN122+nnP/+5zj//fP32t79VmnZ87dT/+7//03vvvdeluirhiSee0EknndTl/UaNGqWTTz5ZRx11lAYNGrTMcQ0NDWpoaNCQIUO000476fjjj1eSJLrnnnt00UUX6cUXXyw751//+ldtv/32OuOMM7pcb085/PDDtWjRog7vc87p+9//vs4880wNHjy47DmjKNLOO++snXfeWT/5yU907LHH6sknnyx7/0svvVQ//OEPNXDgwLL36cyVV16pqVOnlj3eGKNDDz1Up512mnbaaSdZa5c7fulxMWDAAK2/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vrKxkXFG1kXF287IxcW1abptXSQbm+b7ben4uHXMlI6JW8/bEm8fMy7i9xQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUCX69++vH//4xzrjjDP02GOP6f7779dDDz2kN954Q2na+f+1O2TIEG233XYaP3689t9/fw0dOrSsvOeff77OP//8blYfxuabb66rr75a/+///T89/PDDuvvuu/XQQw/pgw8+6LEcxhhttNFG2mWXXbT77rtrzz331Prrr99j8y9PllX3/4W+3nrrBa9x8ODBOvroo3X00UdLkt555x0988wzevbZZ/XMM8/o9ddfL+v5Ua4BAwZozz331AEHHKADDzxQgwcP7rG5e5pzToceeqgOPfRQTZs2Tffcc4/uvvtuPfXUU5o/f36P5enbt6+23npr7bbbbtp99921++67q1+/fj02P1BNXN4FAAAAAAC6bq31N8y7hJXK+O+fqSEbjJJPE6VJIp8k8mmqNCk0rRP5NJFP2sfSJJVPCkrTtGlMUtxOCkqTVINHhPkgVZJ8kgTLVS2sC/fRhU9rr79SuB735IfaKxNjbbBcaeCLWFYDE/QcUXv9lSTr4iB5avUcbCyvc5UUsr9pDb5PkyTjwrzOLVm0SG888WiQXB0x1so4J2udjLWyzhVvOydTGrOu+b7SWHE7lnEdxErns1amJDZo2AitNZK/+wEAAAAAAAAAqk8URbI2krUm71KaZT5TmnqlSaa04JUmvnndf2BDmBqyTHW9bLGGxAfJWQ1sHO44SAu109eljAvY3xo6bkvZQD2mv5VXiz2mv5UXqsdZlskny/4PDbJMSgpeSRW9FhoXyTpTsjTdjtvEYttyX+kSRxo4tK822n5I3g8FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFYJxhiNGTNGY8aMkSQ1NjbqnXfe0ZQpUzR37lzNmzdPktSvXz/169dPa665pjbddFOtvvrqeZYdVK9evbT//vtr//33lyR98skneuGFF/TKK6/o3//+tz744AN9+OGHmjNnjhYtWqRFixYpSRLFcaz6+nr17dtXAwcO1ODBg7XOOuto/fXX18iRI7XZZptp9OjR6t27d86PEMuy0UYbaaONNtIxxxwjSVq0aJHee+89TZ48uXmZMmWKZs2apfnz52vevHmaP3++FixYoCiK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u+qqq5o85oiImZmZmJ2dPaOuUkqzGlqbX/ct5JybzTVJWmUs3/qGmLF867NH1NVyDW/m1wurkW999oi6PM/VJd/6NuMeMf9efBJ84hOfiAMHDjSZ63Of+1y89tprS65LKUXXdQvHs7W19Omr32p9tm7dGrt27WqSLwDDkXOOJ554ou8yJtITTzwRhw4dipRS36UAwIY11XcBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA5EspRUopuq7ru5Sm/sv/8r9c8fqcc5RSIue8ajvX7efTbz3HOle/Xbt2Ncs359xsrknS6udIvvUNMWP51mePqMsarku+9bXKuJTSZJ5J03INDzFj+dZnj6ir7+e5UkqMx+NmNbS2f//++If/8B82meuJJ56Iv/7rv46u65a0+c++ztbW0qd1v5RSk9wANqJnn302Xnnllb7LmEgvv/xyPPvss3HDDTf0XQoAbFhTfRcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACw0XRdFxERo9Go50o2trvvvjs+9rGPRc45cs5RSln482pt0vuUUs75uFNKDdKNyDk3mWfSzP98tjDEjOVbX6uM5VvfEDNu9RwXMcx8I7yOqM0arku+9XkdUVfL1xFreW+52bTM9+WXX47nnnuu2Xy1pZSi67qF42rtV37lV+Kyyy6rXs8PfvCDeOqppxbmPVdd69kvpdT0+QaYfE888UTfJUy0J554Im644Ya+ywCADWuq7wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYpj179sSePXv6LmNdlVIi57ykLb+u67omtezevTt+6Id+6Ix6VqvrYvqt1qcPrfItpUQppclck6RVvhHR2xrqW6uM5VvfEDOWb332iLqs4brkW19Kqck88q1viBnbIy5cKSXG43HfZSx49dVX45FHHult/q7rouu6SCkt/Hm1tpY+a+130003xTvf+c4mj/G1116LiDhnXS33LZhER48eja9//et9lzHRvva1r8XRo0dj586dfZcCABvSVN8FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwGaRUorRaBSj0ajvUuLqq6+Oq6++utcacs5LWinljOtWahfTr9VjLqXEnj171lxXKaVJXbV1Xddsrs2S2flKKTWZJ+fcZJ5J03INDzFj+dbX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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(15, 6), dpi=800)\n", + "for n, data in gpu_res.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--x', label=f'2^{n} nodes')\n", + "\n", + "for n, data in cpu_res.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--o', label=f'2^{n} nodes')\n", + "\n", + "plt.annotate('dense \\n graph', (cpu_res[15][2][0], cpu_res[15][2][1]))\n", + "plt.annotate('gpu generators', (gpu_res[15][1][0], gpu_res[15][1][1]+2e7))\n", + "plt.annotate('cpu generators', (cpu_res[15][1][0], cpu_res[15][1][1]+7e4))\n", + "\n", + "\n", + "\n", + "plt.title('Exact generator performance') \n", + "plt.xlabel('Total edges to generate') \n", + "plt.ylabel('Edges per seconds')\n", + "plt.legend()\n", + "plt.yscale('log')\n", + "plt.xscale('log')\n", + "\n", + "# plt.savefig(\"myImage.png\", format=\"png\", dpi=800)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "d24cdc1b", + "metadata": {}, + "source": [ + "## Approximate generator" + ] + }, + { + "cell_type": "markdown", + "id": "e0f2c00a", + "metadata": {}, + "source": [ + "\n", + "### GPU" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7551999a", + "metadata": {}, + "outputs": [], + "source": [ + "import cupy as cp\n", + "import numpy as np\n", + "from pylibraft.random import rmat\n", + "\n", + "def generate_gpu_rmat_approx(a, b, c, d,\n", + " r_scale, c_scale,\n", + " n_edges,\n", + " noise=0.5):\n", + " gen_graph = None\n", + " theta_len = max(r_scale, c_scale) * 4\n", + "\n", + " base_theta = [a, b, c, d]\n", + " if noise > 0:\n", + " full_theta = []\n", + " for i in range(theta_len):\n", + " noise_uniform = noise * np.random.uniform(-1, 1, size=len(base_theta))\n", + " noise_to_add = np.multiply(base_theta, noise_uniform)\n", + " theta_n = base_theta + noise_to_add\n", + " theta_n = theta_n / np.sum(theta_n)\n", + " full_theta.append(theta_n)\n", + " else:\n", + " full_theta = base_theta * theta_len\n", + "\n", + " theta_cpu = np.array(full_theta, dtype=np.float32)\n", + " theta = cp.asarray(theta_cpu)\n", + " tmp = cp.empty((n_edges, 2), dtype=cp.int32)\n", + " rmat(tmp, theta, r_scale, c_scale)\n", + " \n", + " return tmp" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "3100aa6e", + "metadata": {}, + "outputs": [], + "source": [ + "a, b, c, d = 0.4, 0.25, 0.2, 0.15" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3d89f284", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15 | 1000000 | 0.002 | GOOD\n", + "15 | 1000000 | 377547944.6467425\n", + "15 | 10000000 | 0.019 | GOOD\n", + "15 | 10000000 | 3439822034.506443\n", + "15 | 100000000 | 0.186 | GOOD\n", + "15 | 100000000 | 10374072572.588627\n", + "20 | 1000000 | 0.000 | GOOD\n", + "20 | 1000000 | 289573449.06111413\n", + "20 | 10000000 | 0.000 | GOOD\n", + "20 | 10000000 | 2347738204.042579\n", + "20 | 100000000 | 0.000 | GOOD\n", + "20 | 100000000 | 8372976699.124822\n", + "30 | 1000000 | 0.000 | GOOD\n", + "30 | 1000000 | 210283128.73126873\n", + "30 | 10000000 | 0.000 | GOOD\n", + "30 | 10000000 | 1739389479.7683368\n", + "30 | 100000000 | 0.000 | GOOD\n", + "30 | 100000000 | 5645229391.272711\n", + "40 | 1000000 | 0.000 | GOOD\n", + "40 | 1000000 | 155410336.2012518\n", + "40 | 10000000 | 0.000 | GOOD\n", + "40 | 10000000 | 1523522982.3506944\n", + "40 | 100000000 | 0.000 | GOOD\n", + "40 | 100000000 | 4393486845.012562\n" + ] + } + ], + "source": [ + "n_range = [15, 20, 30, 40]\n", + "\n", + "edges_range = [1e6, 1e7, 1e8]\n", + "edges_range = [int(x) for x in edges_range]\n", + "\n", + "gpu_res_approx = {\n", + " n: [] for n in n_range\n", + "}\n", + "\n", + "# Random run\n", + "data_proper = generate_gpu_rmat_approx(a, b, c, d,\n", + " 18, 18,\n", + " 6_797_556)\n", + "\n", + "for n, edges in product(n_range, edges_range):\n", + " max_edges = (2**n * (2**n - 1)) // 2\n", + " density = edges / max_edges\n", + " \n", + " \n", + "\n", + " if density > 0.75:\n", + " res = \"FAIL\"\n", + " else:\n", + " res = \"GOOD\"\n", + " \n", + " f_string = f\"{n:<13} | {edges:<13} | {density:>8.3f} | {res}\"\n", + " print(f_string)\n", + " \n", + " if res == \"FAIL\":\n", + " continue\n", + " \n", + " start = time.perf_counter()\n", + " data_proper = generate_gpu_rmat_approx(a, b, c, d, n, n, edges)\n", + " elapsed = time.perf_counter() - start\n", + " \n", + " gen_edges = data_proper.shape[0]\n", + " edges_per_second = data_proper.shape[0] / elapsed\n", + " \n", + " calculated = (gen_edges, edges_per_second, elapsed)\n", + " f_string = f\"{n:<13} | {edges:<13} | {edges_per_second}\"\n", + " print(f_string)\n", + "\n", + " \n", + " l = gpu_res_approx[n]\n", + " l.append(calculated)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "304e5fee", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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srOpyN2LOz6eyoMHCWvThvBrrnE6noiIiIiIBAmVvwBmKyvZN3IU1adPE96hA8lPP03sjaNwhYc7HU1ERERERIKMyl8AsV4vJWvWULJ2LU1nzcKEhpI040HCMjKI6NZNUztFRERERORrU/kLADXnz3MuJ4eCOa9Qdfgw7sZJNLrnHkKSkkiYNMnpeCIiIiIiUg+o/DmsdPNmDv/7PdiyMiJ69KDJQ98lZtgwTGio09FERERERKQeUfmrQ2f/8hfCO3Umqk/vi/cVr11L4aLXiL1hBDFDhxLevj1x48aSMGkS4R06OJhWRERERETqM5W/OhTeqTPHZs6kxTPPEJaZwalf/5rCnIVgLTVnzxIzdCiuyEiSn3zS6agiIiIiIlLPqfzVoag+vWnxzDMcuf9+bEUFeL2Ed+xI0vRpRA8a5HQ8ERERERFpQFxOB6jvovr0JnrwIPB6ib99MmkL5hMzZAjG7XY6moiIiIiINCAqf3WsZP0GStdvIGna/RS9tZSS9RucjiQiIiIiIg2Qyl8dKlm/4eI1f41nzKDFM89wbOZMFUAREREREbnqVP7qUPmunbR45pmLq31euAawfNdOh5OJiIiIiEhDY6y1TmeoNVlZWXbTpk1OxxAREREREXGEMWaztTbrco9p5E9ERERERKQBUPkTERERERFpAFT+REREREREGgCVPxERERERkQZA5U9ERERERKQBUPkTERERERFpAFT+REREREREGgCVPxERERERkQZA5U9ERERERKQBUPkTERERERFpAIy11ukMtcYYcxo4BMQBhbV02No6VhJwphaOI86qzZ+tYBfs34tAy+9knqvx3nX1HrV93No4ns739UegnSecFMzfi0DM7lSmq/W+wXDOr8/n+xRrbePLPVCvyt8Fxpg/WWv/XyAdyxizyVqbVRuZxDm1+bMV7IL9exFo+Z3MczXeu67eo7aPWxvH0/m+/gi084STgvl7EYjZncp0td43GM75DfV8X1+nfS4O0GNJ8NPPw6eC/XsRaPmdzHM13ruu3qO2jxtoPxfiLP08fCqYvxeBmN2pTFfrfYPhnB+IPxd1rl6O/AWiYPyXARER+ep0vhcRaRiC8XxfX0f+AtGfnA4gIiJXhc73IiINQ9Cd7zXyJyIiIiIi0gBo5E9ERERERKQBUPkTERERERFpAFT+REREREREGoAQpwM0RMYYF/ATIBbYZK19yeFIIiJSR4wxA4Cp+P7M7WCt7edwJBERqQPGmNbAs0A+sMda+98OR/onGvmrJcaYF4wxp4wxuz53/0hjzCfGmL3GmCf8d48FWgJVwNGrnVVERL6Zr3LOt9ausdbeB7wO6B/7RESCyFf8O35nYL619ttA96se9gqo/NWeF4GRl95hjHEDzwOjgA7A7caYDkA7YK219mHg/qucU0REvrkXufJz/gVTgDlXK6CIiNSKF7ny8/164DvGmJXAW1c55xVR+asl1trV+IZ4L9UL2Gut3W+trQRexTfqdxQo8D+n5uqlFBGR2vAVz/kXpgIVWmuLrm5SERH5Jr7i+f5u4Elr7RDgpqub9Mqo/NWtFsCRS24f9d+XA9xgjPkdsNqJYCIiUuu+6JwP8B3g/656IhERqQtfdL5/C5hhjPkjcNCBXF9KC744wFpbiu8vAiIi0gBYa590OoOIiNQta+0uYKLTOf4VjfzVrWNAq0tut/TfJyIi9Y/O+SIiDUPQnu9V/urWB0CmMSbNGBMKTAb+4XAmERGpGzrni4g0DEF7vlf5qyXGmFeAdUA7Y8xRY8x3rLXVwAPAUuBjYK619kMnc4qIyDenc76ISMNQ3873xlrrdAYRERERERGpYxr5ExERERERaQBU/kRERERERBoAlT8REREREZEGQOVPRERERESkAVD5ExERERERaQBU/kRERERERBoAlT8REalzxphGxpht/l8njDHHLrkd+rnnPmSMibyCY64yxmR9zTypxphdX+e1V3j8wcaYfnV1/Lrm//5McTqHiIjULpU/ERGpc9bas9babtbabsAfgWcu3LbWVn7u6Q8BX1r+AtxgIKDLnzEm5F88nAqo/ImI1DMqfyIi4ghjzFBjzFZjzE5jzAvGmDBjzAygOfCOMeYd//P+YIzZZIz50Bjz4ys4bk9jzLvGmM3GmKXGmORL7t9ujNkOTL/k+ZHGmLnGmI+MMQuNMRsujCgaY0YYY9YZY7YYY+YZY6L99/+3//k7jDG//Nz7pwL3ATP9I5sD/CNpK/3PX2GMaX2Z3I2NMcv9n/MvxphDxpgk/2N3GGM2+o/3v8YYt//+YmPMT/2fa70xpuklx1pgjPnA/6u///6njDEvG2PeB17251rj/3xbLhmt/G9ggP/9Zhpj3MaY//Efa4cx5t4r/o0WEZGAofInIiJOCAdeBG6z1nYGQoD7rbXPAnnA9dba6/3P/YG1NgvoAgwyxnT5ooMaYzzA74CJ1tqewAvAT/0P/x/woLW26+deNg0osNZ2AH4E9PQfKwn4ITDMWtsD2AQ8bIxpBNwCdLTWdgH+69KDWWsP8tnRzTX+TC/5n58NPHuZ+E8CK621HYH5QGt/jvbAbUB//8hpDTDV/5ooYL3/M60G7vHf/1v/+18LTAD+csn7dPB/ptuBU8Bw/+e77ZJcTwBr/PmfAb4DFPqPdy1wjzEm7TKfQUREAti/mvIhIiJSV9zAAWvtHv/tl/CNxv3mMs+91Rjz//D9mZWMr7zs+ILjtgM6AcuNMRfe57gxJh6It9au9j/vZWCU/+vr8JUlrLW7jDEXjt3H/17v+48VCqwDCoFy4K/GmNeB16/g8/YFxl/y3r+4zHOuw1cqsda+ZYwp8N8/FF8h/cCfIwJfaQOovOT9NwPD/V8PAzr4nw8Qe2HUEviHtbbM/7UHeM4Y0w1fqWz7BflHAF2MMRP9t+OATODAF39kEREJNCp/IiISsPyjS48C11prC4wxL+IbNfzClwAfWmv7fu448V/n7YHl/hGyz+fqha+UTQQeAIZ8jeN/lRwvWWtnXeaxKmut9X9dw6d/rruAPtba8s8cyFcGSy65ayZwEujqf81nnv+5DA9aa5d+rU8gIiIBQdM+RUTECTVAqjEmw3/7TuBd/9dFQIz/61h8ZaXQfz3bKP61T4DGxpi+4JsGaozpaK09B5wzxlznf97US17zPnCr//kdgM7++9cD/S9kNMZEGWPa+kfQ4qy1S/CVp89PI/38ZwBYC0y+5L3XXOY1l+YYAST4718BTDTGNPE/lmiMSfmS78My4MELN/wje5cTBxy31nrx/R64vyD/UuB+/7Ra/N+HqC/JICIiAUblT0REnFAO3A3MM8bsBLz4rpMD+BPwljHmHWvtdmArsBuYg68gfSH/yqETgZ/7F3bZxqerbt4NPG+M2YZvJOuC3+MrjB/hu37vQ3zXt50G7gJe8U8FXQdcg68Uve6/7z3g4ctEWQzccmHBF3xF7G7/a+4EvnuZ1/wYGGF8W1BMAk4ARdbaj/Bde7jM//rl+Ka//iszgCz/4iwf4VuA5nJ+D3zL/726hk9HBXcANf6FZGbiu2bwI2CLP9//otlDIiJBx3w6W0RERKTh8a+c6bHWlhtj0oG3gXaX2YKirnOEATXW2mr/yOUf/Au8iIiI1Ar9q52IiDR0kfi2lvDgGxGcdrWLn19rYK4xxoVvIZd7vuT5IiIiX4lG/kRERERERBoAXfMnIiIiIiLSAKj8iYiIiIiINAAqfyIiIiIiIg2Ayp+IiIiIiEgDoPInIiIiIiLSAKj8iYiIiIiINAD/HwbrCmo81Uw2AAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(15, 6))\n", + "for n, data in gpu_res_approx.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--x', label=f'{n}')\n", + " plt.xlabel('Total edges to generate') \n", + " plt.ylabel('Edges per seconds')\n", + " \n", + " plt.legend()\n", + "\n", + " plt.legend()\n", + " plt.yscale('log')\n", + " plt.xscale('log')" + ] + }, + { + "cell_type": "markdown", + "id": "0f6346ce", + "metadata": {}, + "source": [ + "\n", + "### CPU" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "343eb3fb", + "metadata": {}, + "outputs": [], + "source": [ + "from syngen.generator.graph.utils import effective_nonsquare_rmat_approximate " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "0fcc8f5a", + "metadata": {}, + "outputs": [], + "source": [ + "a, b, c, d = 0.4, 0.25, 0.2, 0.15\n", + "theta = np.array([[a, b], [c, d]])\n", + "theta /= a + b + c + d" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "423f40bd", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 6/6 [00:11<00:00, 1.93s/it]\n" + ] + } + ], + "source": [ + "part, _, _ = effective_nonsquare_rmat_approximate(\n", + " theta,\n", + " 6_797_556,\n", + " (18, 18),\n", + " noise_scaling=0.5,\n", + " batch_size=1_000_000,\n", + " dtype=np.int64,\n", + " custom_samplers=None,\n", + " generate_back_edges=False\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "74e28c87", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(6797556, 2)" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "part.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "0fc54d1f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 6/6 [00:11<00:00, 1.93s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15 | 1000000 | 0.002 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:01<00:00, 1.61s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15 | 1000000 | 598743.1903602927\n", + "15 | 10000000 | 0.019 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 10/10 [00:15<00:00, 1.60s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15 | 10000000 | 625014.7747632738\n", + "15 | 100000000 | 0.186 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [02:42<00:00, 1.63s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15 | 100000000 | 615010.6596347046\n", + "20 | 1000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:02<00:00, 2.26s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20 | 1000000 | 425055.51696833596\n", + "20 | 10000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 10/10 [00:21<00:00, 2.17s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20 | 10000000 | 459605.83053238585\n", + "20 | 100000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [03:33<00:00, 2.14s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "20 | 100000000 | 467651.7660398217\n", + "30 | 1000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:03<00:00, 3.35s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "30 | 1000000 | 289359.8013957824\n", + "30 | 10000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 10/10 [00:32<00:00, 3.22s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "30 | 10000000 | 310214.21684405487\n", + "30 | 100000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [05:17<00:00, 3.18s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "30 | 100000000 | 314738.7339784047\n", + "40 | 1000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:04<00:00, 4.37s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "40 | 1000000 | 222316.41207967116\n", + "40 | 10000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 10/10 [00:42<00:00, 4.24s/it]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "40 | 10000000 | 235354.96102985306\n", + "40 | 100000000 | 0.000 | GOOD\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [07:07<00:00, 4.27s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "40 | 100000000 | 234091.36246754852\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "n_range = [15, 20, 30, 40]\n", + "#n_range = [2 ** x for x in n_range]\n", + "\n", + "edges_range = [1e6, 1e7, 1e8]\n", + "edges_range = [int(x) for x in edges_range]\n", + "\n", + "cpu_res_approx = {\n", + " n: [] for n in n_range\n", + "}\n", + "\n", + "# Random run\n", + "part, _, _ = effective_nonsquare_rmat_approximate(\n", + " theta,\n", + " 6_797_556,\n", + " (18, 18),\n", + " noise_scaling=0.5,\n", + " batch_size=1_000_000,\n", + " dtype=np.int64,\n", + " custom_samplers=None,\n", + " generate_back_edges=False\n", + " )\n", + "\n", + "for n, edges in product(n_range, edges_range):\n", + " max_edges = (2**n * (2**n - 1)) // 2\n", + " density = edges / max_edges\n", + " \n", + " \n", + "\n", + " if density > 0.75:\n", + " res = \"FAIL\"\n", + " else:\n", + " res = \"GOOD\"\n", + " \n", + " f_string = f\"{n:<13} | {edges:<13} | {density:>8.3f} | {res}\"\n", + " print(f_string)\n", + " \n", + " if res == \"FAIL\":\n", + " continue\n", + " \n", + " start = time.perf_counter()\n", + " data_proper, _, _ = effective_nonsquare_rmat_approximate(\n", + " theta,\n", + " edges,\n", + " (n, n),\n", + " noise_scaling=0.5,\n", + " batch_size=1_000_000,\n", + " dtype=np.int64,\n", + " custom_samplers=None,\n", + " generate_back_edges=False\n", + " )\n", + " elapsed = time.perf_counter() - start\n", + " \n", + " gen_edges = data_proper.shape[0]\n", + " edges_per_second = data_proper.shape[0] / elapsed\n", + " \n", + " calculated = (gen_edges, edges_per_second, elapsed)\n", + " f_string = f\"{n:<13} | {edges:<13} | {edges_per_second}\"\n", + " print(f_string)\n", + "\n", + " \n", + " l = cpu_res_approx[n]\n", + " l.append(calculated)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "9159ec79", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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S5k/fz6FhYVceeWVO+3cP9rDaIzZD/jSWjsv9DjDGDPCWjuride4AvgayIhz7gKg0lq7LWpbd2vtku12fRK4D3h6u+O9wP3AGJxg+Jkx5g3gY2vtVGNMG+BO4MwmtlVERERERKRJGusRTE7wcsXhPbj0+c+5/LDuPDvrB644vAcju+UBkJOasEM9itHatGkT+f6CCy7gmGOO2Snnhabdw/ggTm9dWFlo248yxrQHjgYebWCXUcDrxpjE0P4XAPduv5O1dhpO7+b2hgNLrLXLrLU1wIvA8dbaYKi+BUhsSltFRERERER2lvA9i/edMZjJR/TivjMGu+5p3JnWrFkT+f61115zzaC6o5pyD6Ox1trwA2tt0BjTlOMA7gauAdLjFa21LxtjugD/NMa8DJyH01vYVEXAyqjHxcAIY8xJwJE460feF+9AY8yxwLHdu3f/CZcTERERERH5cQuKS7jvjMGRHsWR3fK474zBLCguiWz7OU4//XQ++ugjNm7cSPv27fn973/PRx99xPz58zHG0LlzZx5++OGd9TSaFBiXGWMup75X8WJg2Y8dZIw5BlhvrZ0bmoQmLmvtbcaYF0Pn72atLWto36ay1r4KvPoj+7wJvDl06FAtESIiIiIiIjvVr0d1i9k2slveDoVFgBdeeCFm28SJE3fonI1pypDUXwMjgVWEevCAXzXhuAOA44wxK3CGih5mjHl2+52MMQcB/YDXgJub1uyIVUCHqMftQ9tERERERERkBzVlltT11tpfWGsLrLVtrLVnWGvXN+G466217a21nYFfAFOstb+M3scYMxh4BDgeZybWXGPMn35C+z8DehhjuhhjEkLXeeMnHC8iIiIiIiIN+NHAaIzpaYz5MLykhTFmgDHmhp10/RTgVGvt0tBENWcD38dpwwvADKCXMabYGDMRwFpbB1wKvIczE+tL1tovd1LbRERERERE9mpNuYfxH8DVwMMA1toFxpjngSb3BFprPwI+irP90+0e14aut/1+pzdy7neAd5raFhEREREREWmaptzDmGKtnb3dtrpd0RgRERERERFpOZoSGDcaY7oBFsAYMx5Y0/ghIiIiIiIi0to1JTBegjMcdR9jzCrgN8BFu7JRIiIiIiIiEmvlypUceuih9OnTh759+3LPPfcAsHnzZsaMGUOPHj0YM2YMW7Zs2SnXa8osqcustYcD+cA+1toDrbUrdsrVRURERERE9kSf3A3Lp7m3LZ/mbN8BPp+PO+64g6+++oqZM2dy//3389VXX3HrrbcyevRovvvuO0aPHs2tt966Q9cJa8osqVcYYzKACuAuY8w8Y8wRO+XqIiIiIiIie6KiIfDyOfWhcfk053HRkB06bWFhIUOGOOdIT0+nd+/erFq1in//+99MmDABgAkTJvD666/v0HXCmjJL6nnW2nuMMUcCucBZwDPAf3dKC0RERERERFqjJ46O3db3BBh+ARQNhfRCeOZE57/b1kD+PrB1pbNf+SZ46Wz3see+/ZMuv2LFCj7//HNGjBjBunXrKCwsBKBt27asW7fuZzyhWE25h9GE/nsU8HRonUPTyP4iIiIiIiKSlOWExZKVzn+TsnbaqcvKyjj55JO5++67ycjIcNWMMRizcyJbU3oY5xpj/gt0Aa43xqQDwZ1ydRERERERkdaqsR7BhBQ45FpnGOrB18Ccx5zHXQ526qm5P7lHMay2tpaTTz6ZM888k5NOOgmANm3asGbNGgoLC1mzZg0FBQU/69zba0oP40TgOmCYtbYCSADO3SlXFxERERER2ROF71k85Uk47HfOf6PvafyZrLVMnDiR3r17M3ny5Mj24447jqeeegqAp556iuOPP36HrhPWlFlSg9baedbaraHHm6y1C3bK1UVERERERPZEq+Y5ITHco9jlYOfxqnk7dNpPP/2UZ555hilTpjBo0CAGDRrEO++8w3XXXcf7779Pjx49+OCDD7juuut2+ClA04akioiIiIiIyE9x4G9it3U5uD5A/tzTHngg1tq4tQ8//HCHzh1PU4akioiIiIiIyF6o0cBojPEaY77ZXY0RERERERGRlqPRwGitDQDfGmM67qb2iIiIiIiISAvRlHsYs4EvjTGzgfLwRmvtcbusVSIiIiIiItLsmhIYb9zlrRAREREREZEW50cDo7V2qjGmE9DDWvuBMSYF8O76pomIiIiIiEhz+tFZUo0xFwCvAA+HNhUBr+/CNomIiIiIiEgcVVVVDB8+nIEDB9K3b19uvvlmAJYvX86IESPo3r07p512GjU1NTvlek1ZVuMS4ACgFMBa+x1QsFOuLiIiIiIisgd6fNHjzF4z27Vt9prZPL7o8R06b2JiIlOmTOGLL75g/vz5vPvuu8ycOZNrr72WSZMmsWTJErKzs3nsscd26DphTQmM1dbaSDw1xviA+CtFioiIiIiICP1y+3HV1KsioXH2mtlcNfUq+uX226HzGmNIS0sDoLa2ltraWowxTJkyhfHjxwMwYcIEXn/99R26TlhTJr2Zaoz5LZBsjBkDXAy8uVOuLiIiIiIi0kqd++65MduO7Hwkv9jnF/TP709+Sj4Xvn8h+Sn5bKjYQNesrqwuXw3AlqotTP5osuvYJ8Y+0aTrBgIB9t13X5YsWcIll1xCt27dyMrKwudz4l379u1ZtWrVDj47R1N6GK8DNgALgQuBd4AbdsrVRURERERE9lAZCRnkp+SzpnwN+Sn5ZCRk7JTzer1e5s+fT3FxMbNnz+abb77ZKeeNpymzpAaNMU8Bs3CGon5rrdWQVBERERER2as11iOY7EvmooEXcdXUq7hwwIW89O1LXDTwIoYXDgcgOym7yT2KDcnKyuLQQw9lxowZbN26lbq6Onw+H8XFxRQVFe3QucOaMkvq0cBS4O/AfcASY8y4nXJ1ERERERGRPVD4nsXbR93OpYMv5fZRt7vuafy5NmzYwNatWwGorKzk/fffp3fv3hx66KG88sorADz11FMcf/zxO/oUgKbdw3gHcKi1dgmAMaYb8Dbwn53SAhERERERkT3Mok2LuH3U7ZEexeGFw7l91O0s2rQosu3nWLNmDRMmTCAQCBAMBjn11FM55phj6NOnD7/4xS+44YYbGDx4MBMnTtwpz8P82OhSY8xn1tphUY8NMDt6W2s2dOhQO2fOnOZuhoiIiIiItHBff/01vXv3bu5m7JB4z8EYM9daOzTe/k3pYZxjjHkHeAnnHsZTgM+MMScBWGtf3bEmi4iIiIiISEvUlMCYBKwDRoUebwCSgWNxAqQCo4iIiIiIyB6oKbOkxi4uIiIiIiIiInu8pqzDKCIiIiIiInshBUYRERERERGJS4FRRERERERE4vrRwGiMucIYk2Ecjxlj5hljjtgdjRMREREREZFYgUCAwYMHc8wxxwCwfPlyRowYQffu3TnttNOoqanZKddpSg/jedbaUuAIIBs4C7h1p1xdRERERERkD7Tp0UcpnznLta185iw2PfroTjn/Pffc41pP8dprr2XSpEksWbKE7OxsHnvssZ1ynaYERhP671HAM9baL6O2iYiIiIiIyHaS+vVn1aRJkdBYPnMWqyZNIqlf/x0+d3FxMW+//Tbnn38+ANZapkyZwvjx4wGYMGECr7/++g5fB5q2DuNcY8x/gS7A9caYdCC4U64uIiIiIiLSSn1/1tkx29LHjSXnjDNIHjgAX0EBP5x/Pr6CAurWryexWzdqV68GoG7LFlZdfoXr2E7PPN2k6/7mN7/htttuY9u2bQBs2rSJrKwsfD4n3rVv355Vq1btyFOLaEoP40TgOmCYtbYCSAC0NqOIiIiIiEgjvBkZTlhcvRpfQQHejIwdPudbb71FQUEB++67705o4Y9rSg+jBfoAxwB/AFKBpF3ZKBERERERkZausR5BT3IyeZdcwqpJk8i7+CK2vPAieZdcQup+IwDwZWc3uUcx2qeffsobb7zBO++8Q1VVFaWlpVxxxRVs3bqVuro6fD4fxcXFFBUV/ezn5XoeTdjnAWB/4PTQ423A/Tvl6iIiIiIiInug8D2LRXfdRf7ll1N0112uexp/rr/+9a8UFxezYsUKXnzxRQ477DCee+45Dj30UF555RUAnnrqKY4//vid8TSaFBhHWGsvAaoArLVbcIalioiIiIiISBxVixZSdNddkR7F1P1GUHTXXVQtWrhLrvd///d/3HnnnXTv3p1NmzYxceLEnXLepgxJrTXGeHGGpmKMyUeT3oiIiIiIiDQoNzSDabTU/UZEAuTOcMghh3DIIYcA0LVrV2bPnr3Tzh3WlB7GvwOvAQXGmD8DnwB/2ektERERERERkRblR3sYrbXPGWPmAqNx1l88wVr79S5vmYiIiIiIiDSrHw2MxpgcYD3wQtQ2v7W2dlc2TEREREREpKWx1mKMae5m/CzW2p98TFOGpM4DNgCLge9C368wxswzxuyexT9ERERERESaWVJSEps2bfpZwau5WWvZtGkTSUk/bYXEpkx68z7wirX2PQBjzBHAycATOEtu7Ly7NkVERERERFqo9u3bU1xczIYNG5q7KT9LUlIS7du3/0nHNCUw7metvSD8wFr7X2PM7dbaC40xiT+1kSIiIiIiIq2R3++nS5cuzd2M3aopgXGNMeZa4MXQ49OAdaGlNrS8hoiIiIiIyB6qKfcwngG0B14PfXUMbfMCp+6qhomIiIiIiEjzasqyGhuByxooL9m5zREREREREZGWosHAaIx5E2hw+h9r7XG7pEUiIiIiIiLSIjTWw3h76L8nAW2BZ0OPTwfW7cpGiYiIiIiISPNrMDBaa6cCGGPusNYOjSq9aYyZs8tbJiIiIiIiIs2qKZPepBpjuoYfGGO6AKm7rkkiIiIiIiLSEjRlWY1JwEfGmGWAAToBF+7SVomIiIiIiEiza8osqe8aY3oA+4Q2fWOtrd61zRIREREREZHm1uCQVGPMNVEPj7PWfhH6qjbG/GU3tE1ERERERESaUWP3MP4i6vvrt6uN3QVtERERERERkRakscBoGvg+3mMRERERERHZwzQWGG0D38d7LCIiIiIiItt5fNHjzF4z27Vt9prZPL7o8WZq0U/TWGAcaIwpNcZsAwaEvg8/7r+b2iciIiIiItJq9cvtx1VTr4qExtlrZnPV1Kvol9uvmVvWNA3Okmqt9e7OhoiIiIiIiOxO1lqCNkjQBvEYD16Pl9pgLRW1FQRtkIANROrZSdkkehMpry1nfcV6Vz1gA3TJ6EKKP4WNlRtZUbICi3XqwSBn9zmbK6deyWm9TuOlb1/i9lG3M7xweHM//SZpyjqMIiIiIiKyGwWCAQI24AokABkJGQBsqdpCVV2VK9D4PD7ap7cHYFnJMiprK131FH8K++Q4K+XNXTeX8tpyAsFQnSA5STns22ZfAP674r+U15a7QlH79PYcWHQgAM99/RyVdZVYayP1Xjm9GN1xNAB3zrmTOlsXuXbQBhnWdhhHdj6S2kAtt8y4JRKmgjj1wzsezlFdj6K0ppRrpl5DwAZc5z+l1ykc0/UY1pav5fIpl7ueW9AG+fXAX3N016NZsmUJF75/YeS84evcuP+NjOsyjnnr5jHxvYnO+aPutLv70LsZ3XE0M1bP4JIPL4n5mfzjiH+wX+F+fFz8MVdPuzqm/txRzzEgfwBTV07llhm3xNRP7XkqDy94mAsHXNhqwiIoMIqIiIjIjwi/abfWYozB5/ERCAYoqy2LedOenpBOqj+VmkANxWXFBINRvTQEaZfajuykbMpqyvhm8zcxvTR9cvuQl5zHxsqNzF0313XugA0wst1IClIKWFm6kk9Wf+JsDwYivTnHdD2GgpQCvt70NVNWTqkPRKHjz+13LnnJecxeM5t3V7zrqgVtkGuHXUtWUhbvf/8+by19yxU6rLXcecidpPpTeenbl3hz6ZtOPfQcLZYXjn4Bn8fHg188yFtL33I9N7/Hz7snvwvAH2f8kXeWv+OqZyZk8tFpHwEw+aPJTFk5xfVzKEorihx/9bSrmbVmlqveI7sHrx73KgA3fHIDCzcudNUH5Q/imaOeAeAPM/7AspJlrvoB7Q5g3zFOYLzts9tYV7HOVR/TaUwkMN4//3621Wxz1U/ofkIkML68+GWCNojXePF4PHjwkJGQwZGdj8RimbtuLgaD1+N1evaMly3VWyK/b6U1pXiMJ/Ll8/jwhO6m83l8FKQURI4L75OdmA1AWkIaB7Y/0NmOJ9Jz2D7NCdNtUttwTr9zIscbY/AaL10zuwLQLasb1wy7xnV+r/HSJaMLAAPyB3DrQbe6ah7joVNGJwAOan8Qjx7xaKRdXuPl681f88D8B7hwwIW89O1LDG87vNWERgVGERGR3ezxRY/TL7ef683C7DWzWbRpEef1O68ZW9b6BIIB6mxdJBSE39RnJmZijKGkuiTSSxKpYyNvDFeVrWJL1RZXT4bHeBhcMBiArzd9zYbKDa7zJ/mSOLj9wQBMXz2ddeXrXIEjIyGDo7oeBcCbS99kXcU6V9sKUgoY33M8AE8uepL1lesjoSdog3TN6sqZvc8EnDftmyo3uXpZ+uf3j/yeTP5oMttqtrmuf0C7A7hw4IUAnPH2GVQHql31o7sczUWDLqImUMO4f41zhblgMMhZfc7iokEXsaVqC4e9dFhML8wVQ67g/P7ns6Z8DeNeHRfzM7l++PWc0fsMlpcsZ/yb42Pqfzzgj5zQ/QS+2/od5753bkz9zkPuZEynMXy7+VuumnpVTP3hwx92AuHmr/nLrNilwYcUDKEgpYBvt3zLQ1885HrT7jEeTux+InnJeazctpIPf/jQFRg8xkNVoAqAkuoSVpatrA8coeAT7unzGi+JvsSY48OvVduUtvTN6+sKFX6PP9LOQQWDSPAmuNqW4k+J1I/uejT98vq56ukJ6ZH62X3O5qguR7nq4d5HgCuHXklZTZmrbdH12w6+jZpADR5P/fGp/tRI/elxT2OxrkCW5E2K1D8Y/0FM4DKmfiGFGWfMiPnZhCV4EyLBN57MxEyeP/r5But5yXncN/q+ButtU9vy+5G/b7BelFbEFUOuaLR+Vp+zGqy3S2tHu7R2DdYLUgooSCmIPJ69ZjYPzn+QO0bdwfDC4QxvO5yrpl7VaoalGmv37glPhw4daufMmdPczRARkb3IrDWzuGrqVdwx6g6GtR3Gv5f+m7999jcm7zuZPrl9CNogucm5tE1tS22wlvnr57sCQ8AG6JzRmY4ZHamorWDaqmmuetAG6Z/Xn25Z3SipLuHtZW87vS9RQ88OaHcAvXJ6sbZ8La8sfiWml+f4bsfTK6cXy7Yu49mvn42pn9v3XHrl9OKLDV/w+MLHI+cND/26Ztg1dM/uzsfFH/PIgkdi7gW6fdTtdM7szJtL3+TBLx6M6eV5/qjnKUwr5Okvn+aBLx6oD1Sh3p6PTv2I7KRs7pl3D48ufDTmNZ77y7kkeBP4y6y/8MI3L7hqPuPj87M/B+B3n/yON5a+4apnJGTw6emfAk4ge//79131wtRC/jv+vwBc+P6FTF893VXvntWd145/DYCz3jmL+Rvmu+oD8wfy7FHPAk6gW1ayzAkloTfuQ9sM5Y5D7gBgwn8msKFyg+tN+36F+3Ht8Gsj1y+vLXeFkv3b7c/E/hMBmPS/SQRswFUfWTSSE7qfQF2wjj/N/JMrUHiMh/0L92dUh1FU1lXyjwX/iKkPbzucQQWDKKsp4/Ulr8eEhkEFg+iW1Y3SmlI+Kf7EFUi8xss+OfvQNrUt22q28dWmr2ICXaeMTmQmZlJeW87qstWua3uMh7zkPJJ8SVQHqimrKXP1YHmMh0RvIl6PN9IbKtLcWsOHhMaYudbaoXFrCowKjCIi8uOCNkhlXSVlNWWU15XjN346ZHQA4N3l77KlegvlteWU15ZTVlNG79zenNTjJADO/s/ZbK3eSnltORW1FZTXlnNIh0OYv34+43uO5x8L/xFzvXP7ncvkfSdTUl3CgS8eGFO/dNClXDjwQtaUreGIfx0RU7922LX8ss8vWbp1KSf8+4SY+u9H/p6TepzEgg0LOPOdM2OGVv3lwL8wutNo5qydw5VTr4yp/+GAPzCs7TBmrpnJbZ/dVv+mPhR8btrvJnrl9GL66uk8vuhx1/HGGK4ddi3t09szfdV0/r303zG9NJcPuZycpBxmrJ7BtOJpMaHg/P7nk+JP4bO1n/HFhi9ihqad1us0fB4f89fPZ3nJclfg8Hq8jO08FoBvNn/DuvJ1rrYleBMi93GtKFnBtpptrtCT4Emgc2ZnADZWbnR6aaLO7/f4yUzMBKCqrgpjTKTdHuNRiBGRFkeBsREKjCIie75NlZsiQxPLasuoqK3A7/VHhhU+9/VzrChZ4ap3yujEjfvfCMApb57CN5u/cZ3zoKKDeODwBwAY/fJo1lesB5zeqxR/CmM7j40cP/mjyRgMqf7UyNeA/AEs2LCAhxc8zOiOoxnbZawrVHVM70jXrK7UBeuYt25eTC9P29S2FKQUUBus5fuS7929NB4PmQmZpCWkUReso7SmNCaQ+T1+fB6femFERKTRwKh7GEVEpEUJBANU1FVQUVtBm9Q2AHy35Tu+L/2estqySC9ewAa4aOBFADy68FFmrJ4RqZXXlpORkMHrJ7wOwG8/+W3MsMEumV0igfF/P/yPb7d8S6o/lRR/Cmn+NLye+tWljul6DId0OIRUXyqpCamk+lJd9688O+5ZErwJpCWkkeBJiAlgdx5yZ8zznL1mNi99+1JkAoQz9jkj7r0sPo+v0Xtc/B4/3bO7N1j3eXzkJOU0WFdYFBGRxigwiojIDgsEA5TXOcMtw0M2y2vKGdJmCEm+JL7Y8AWz1syK9N6Fe/L+76D/I8WfwqMLH+W5r5+jvLacyrrKyHnnnzUfr8fLC9+8wMuLX3ZdM9WfGgmMlXWV1AZryU7Kpn16e9L8aeQm50b2ndB3Aid0P8HVwxc9+cOjR8beAxdtQt8JjdYL0wqb/FpB/aLN4QkPWtsECCIisvdQYBQR2UvVBesApweqtKaUZVuXOYEv1ItXUVfB6I6jaZvalvnr5/PCNy84Ya/OuUevoq6Cvx/6d7pmdeWf3/6Tv87+a8w13j7xbTpmdGTeunnc+/m9+D1+0vxpkV686kA1Kf4UOqZ3ZFT7Ua5Al+pPJUgQL14m9p/Iab1Oc9USvAmR61w2+LJGn+vIdiN37ou3gxZtWuQKh8MLh3P7qNtZtGmRAqOIiLQouodR9zCKSCtSF6yLTJxSVltGTlIOucm5lFSXMOWHKfVhL1Q/rttxDCoYxDebv+GmT29yDdmsClRxz6H3cFjHw5hWPC3uIsUPj3mYke1GMnXlVG6dfStpCWmk+FJIS0gj1ZfKpYMvpWNGR77d/C2z1syKCXx9cvuQ5EuiJlAD4Ap5IiIi0jLsdfcwGmMOAf4IfAm8aK39qDnbIyJirWV1+WpXmCuvLad9env65valqq6K++ff75p0pay2jOO7Hc+JPU5kbflajn3t2Mj6YGHXDLuGs/qcxabKTdw0/abI9kRvIqn+VIa2GcqggkEkehPJT8mns7+zE+ZC9+J1zugMQL+8fjww+oGYQBhe82tUh1GM6jCqwefXK6cXvXJ6NVhXUBQREWmddllgNMYkAdOAxNB1XrHW3vwzz/U4cAyw3lrbb7vaWOAewAs8aq29FbBAGZAEFP/sJyEie63aQK2z2DfByIQhs9fMZnP1Ztd9eh3SO3BM12MAuGrqVWys3BhZVqGiroIxncZww343AHDUq0cRtEHXdc7Y5wz65vbFYzy8+M2LkaGa4clXwhOSZCRkcPo+p5PiTyHVnxoZ1tk7pzcAHTI68N7J70WOi14cGpwJXu4ffX+DzzcnKYeD2h+0c148ERER2WPssiGpxnmXk2qtLTPG+IFPgCustTOj9ikAKq2126K2dbfWLtnuXAfjBMCnowOjMcYLLAbG4ATDz4DTgW+stUFjTBvgTmvtmQ21U0NSRfYctYFa1yya5bXlAAxpMwSA/yz/j2vphPLacgpSCrh62NUAXPzBxSzauIjy2nJqgs4QyhFtR0QmRDnq1aNYuW2l65qHdzycuw69C4Bfv/9raoI1pPrqZ9oc3GZwJFC+sfQNkrxJriGbecl5ZCdl7/oXR0RERKQBzTIk1TpJtCz00B/62j6djgJ+bYw5ylpbbYy5ADgJGLfduaYZYzrHucxwYIm1dhmAMeZF4Hhr7Veh+hacHk4RaaFqAjX4PX6MMawtX8vqstWu0FcdqObM3s5nPq8sfiVmpk2/x88Lx7wAwOSpk/lo5Ueu8xelFfHuye8C8Np3rzFjzQySfcn1k6pE9fj1z+tPYWphZNmEtIQ0itKKIvW7DrkLr/E6xyakkuJLweep/zP60JiHGn2ux3U7bkdeKhEREZHdbpfewxjqAZwLdAfut9bOiq5ba182xnQB/mmMeRk4D6e3sKmKgOiP+4uBEcaYk4AjgSzgvgbadixwbPfuDa9dJSKxrLXUBGucQFdTTnldOV0yu5DoTWTJliV8vuFz17IJFbUVXDn0StIT0nl58cv1M22G6nXBOmafOZtkXzJPffkUz379bMw1T9/ndDzGww/bfuCbzd9Eeu8K0wpd68ud2P1E9ivczzVkMzMxM1K/57B7SPAkuNbXi3bRoIsafe6N3aMnIiIisifapYHRWhsABhljsoDXjDH9rLWLttvntlDP4INAN2ttWZxT/dTrvgq8+iP7vAm8OXTo0At29HoirUV1oJr15etdyyaU1ZQxtO1QClIKWLxlMa9991pke3gtvZv2v4ke2T14c+mb3DT9pshyDGGvHfca3bO7M2vtLG6dfWtke4rPud/u1wN/TXpCOmn+NNqntXctq5DqT8Xg3Kd3Ss9TOLj9wTEzbYbrk/edzOR9Jzf4/A7reFijzz/Zl/xzXzoRERGRvdJumSXVWrvVGPM/YCzgCozGmIOAfsBrwM3ApT/h1KuADlGP24e2ibR61lqqAlWU15aT6E0kPSGditoKZq+d7bpHr7y2nIPbH8yA/AF8X/o9f53115iZNm/e/2aO6HwE89fP5/z/nh9zrXsPu5eClALWlq/ltSWvRWbQDP83PGyzW1Y3JvSZEJlJM9yT1ya1DeAMuRzdcXQkEHqMx3WdcV3GMa7LuJjrh3XN6krXrK478VUUERERkR2xK2dJzQdqQ2ExGWeo6f9tt89g4BGcGVCXA88ZY/5krb2hiZf5DOgRGta6CvgFcMbOeg4iP0dlXWVMoMtJyqFbVjfqgnU889UzrjBXXlvOIR0O4bhux7G1aiunvnVq5LiADQBwxZArOL//+Wyu2sxlU9wLlBsMecl5DMgfgMFQWlNKij+F3ORcZ8ZMXwrt0toBTuD7y4F/iZlps21KWwAObn8wM8+YSUP65PahT26fBuvpCemRZRhEREREpPXblT2MhcBTofsYPcBL1tq3ttsnBTjVWrsUwBhzNnDO9icyxrwAHALkGWOKgZuttY9Za+uMMZcC7+Esq/G4tfbLXfWEZM9kraU2WBtZJ27xlsVsrdrq6qXLS85jdKfRANw6+1bWV6x3Ddncv93+XDv8WgBG/XMUlXWVrmuc3ONkbhl5Cx7j4a65zoya4eUP0vxpDMwfCECyP5lhbYe5llWIrrdJacMLR78QGaqZ5k8jyZcU6cnrmNGR549+vsHnmpecx7Hdjt2Jr56IiIiI7Ml22bIarYWW1WidrLWRnrzwxCk9snsAMGP1DH4o/cE102Z6QjqXDnZGO9/06U0s2LCgfqbNunIG5A3gmaOeAeDEf5/Ikq2ulV0YUTiCR49wllY4+z9nU1pd6rrHbt82+/LLPr8E4Lmvn6ufSTMU6gpTC+mQ4YyerqitINmXHFlfT0RERESkOTXLshoiDSmtKWVT5aZImAsHt2O6HoMxhve/f5/P1n7mTMoSGrZprY2shfe7T37Hm0vfxEat0pKfnM+UU6cATmCbWjwVAI/xkOpPpUdWj8i+WUlZdM3qSoovJXIvXof0+lthb9jvBoI26JqUJdWfGqk/Pe7pRp9feAmIhqT4U5r4SomIiIiINC8FRmlU0AaprKukrKaMnKQc/F4/a8rW8NXmr2Lu0zun7zlkJmby3or3eHnxy6579Mpry3nv5PfITMzk8YWP89iix2KudUTnI0j0JjJ//XzeXva2qwcvPSEday3GGA4qOoi2qW1dYS566YRbRt4COEM+k7xJMT15jc2yCbBvm313/IUTEREREdkDKDC2II8vepx+uf0YXjg8sm32mtks2rSI8/qd1+TzBG0wss5duAevvLacHtk9yEvOY2XpSt5d8W5M4Lt40MX0yunF/374H3+a+SfK65wevnBP3ovHvEjf3L58svoT/jDjD65r+oyPY7sdS2ZiJjWBGqrrqslIyHAWQQ+FuvB9dkd2PpIe2T0iE66Eh236PX4Arh52NVcPu7rB5ze2y1jGMrbBel5yXpNfKxERERERaZgCYwvSL7cfV029ilsPupW0hDTmrpvLwwse5rSep/Hc188xqGAQfXP7srZ8LffMuycm8F02+DKO6HwECzYs4Kz/nBVz/ttH3c6RnY+kuKyYv3/+d3zGR2pC/UyZ4YlaClIKOLD9ga5lE1L8KbRJcZZOGN1xNP3z+pPqC03KkpBGgich0pN3bLdjG51YpXdub3rn9t4Fr6CIiIiIiOxMmvSmhU16M3vNbCZ/NJmSmpKY2m+G/IaJ/SeyqmwVE9+bGOm5C99rd0rPUxhROIKNlRt5e9nbMffgdc3sSnZSNnXBOgI24Ap5IiIiIiKyd2ps0hsFxhYWGAH+Pu/v/GPhPziu23Gc3efsSPBLS6gftikiIiIiIrIzNBYYPbu7MdK42Wtm88riV7hwwIV8XPwxJdUldEjvQHZStsKiiIiIiIjsVgqMLcjsNbO5aupV3D7qdi4dfCm3j7qdq6Zexew1s5u7aSIiIiIishdSYGxBFm1axO2jbo/Mkjq8cDi3j7qdRZsWNXPLRERERERkb6R7GFvgPYwiIiIiIiK7i+5hFBERERERkZ9MgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREREREJC4FRhEREREREYlLgVFERERERETiUmAUERERERGRuBQYRUREdrNNjz5K+cxZrm3lM2ex6dFHm6lFIiIi8SkwioiI7GZJ/fqzatKkSGgsnzmLVZMmkdSvfzO3TEREdrbW/iGhr7kbICIi0hpYa7E1NQQrKrCVldhAgIQOHQCo+Pxz6tatI1hRSbDSqXsyMsg+9VQA1t9zDzVLlhKsrAx9VZDUuzerJk0i+/RfsPHhR/AkJbFq8mQwBowhdf/9KfrbbQAsH38KdRs3hmpgMKQdeihtb7wBgGUnnYQtr4gcizGkH3kEBVdc4dSPPwGsddUzjz2W3PPOJVhVxfe/PCuq5pw/8+STyD71VAJbt7Ly0ksBZ3t4v+xfnEbGUUdRu24da67/revcGMg580zSRo2iZuVK1v3lr+7zG0PO2WeTMmwY1UuXsuHe+yLbQ9+Qc845JPfvR9U337D5iSfrjwcwhtyJ55HYrRuVCxey9eVXIufGGIwx5E6ciL+oiIrPP6f0nf/EnD/3/In48vKomDOHso8+Cp27/jnknj8Rb3o65bNnUzFrdsz5c847D09iIuUzZ1G5YEH9+UPnyTn3HIzHQ/mMGVQvXuw6v/H7yf7FaQCUz5hBzfff11/bY/AkJZN57DFOfeZMatesdZ3fk5ZG+mGHheqzCGzeFGqfB4zBm5lB6n77OfXZswlu2xaqOe33ZWWRPGiQ87s7bx7BikrX+b3Z2STtsw8AlfPnY+vqol5/gzc7i8Qu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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(15, 6))\n", + "for n, data in cpu_res_approx.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--x', label=f'{n}')\n", + " plt.xlabel('Total edges to generate') \n", + " plt.ylabel('Edges per seconds')\n", + " \n", + " plt.legend()\n", + "\n", + " plt.legend()\n", + " plt.yscale('log')\n", + " plt.xscale('log')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "5e3ededb", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAJscAABDBCAYAAAByq32BAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAHsIAAB7CAF4JB2hAAEAAElEQVR4nOzdZ5QlV3U24He3RjkSBIigTBQ5Z5FzEMmASBLJH8FgDDbJJBtsAwaDwQSDjRBJBBFFTpLJGREEmCQwYBDBRBEktL8f1cMIMZrpe/veW92j51mrF7amzj5v3646dc6pma7q7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcM6wNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDiLI0dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxVkaOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuzNHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZ2nsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALM7S2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFicpbEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwOEtjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYHGWxg4AAAAA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AAAAAAAAoJ9pdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP1MowMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOhnGh0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA/0+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6mUYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQzzQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAfqbRAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9DONDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoJ9pdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP1MowMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOhnGh0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA/0+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6mUYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQzzQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAfqbRAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9DONDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoJ9pdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP1MowMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOhnGh0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA/0+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6mUYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQz9boAADg1tJa+2KSacmVSvJwpxwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODG8MQkbcn5l6rqtl4xN7pWVaMbAIBbSGvN/3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABrV1VtdMONYhodAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAP9PoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+plGBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0M80OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgH6m0QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQzjQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCfrdEBAMAtp5K0ZRfOnDnTKQUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALgRXLly5agr1aPjZrE1OgAAuOU8nOTM9Q7PnDmTy5cvd8wBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOuzvvvDNXrlxZduXhXi03g2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+ptEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0M40OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgn2l0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/UyjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6GcaHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQD/T6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPqZRgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDPNDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB+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/h/qAITOMIwhkiZZHH/ANM377WtjnWEYXSV9bnH8E9M0e9nZpyJG2VmKApKsnPGl2DTNsPzJ0TCMayW9HuKy2AruLw1xv56maS4Occ3vGIbRQtIySbUqGN2mstfzfyT9IGmvpARJjSR1kjRA0sWSKjpr1EjTNJ+rQmVIMgxjn6QjnmWlZs2a2rdvn4ONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAsWTjxo169dVX9eabb2rTpk2V2qNOnTq66KKLNGTIEF144YUVzi9YsEALFiyocO68887TeeedV6lOh7No0SL16NGjwrlu3bpp0aJFFc6tXLlSL730kmbNmqUtW7ZUqlPjxo01cOBA3XzzzWratGml9gAOZ9euXZo0aZImT56sn376qVJ7JCUlqVevXho0aJD69eunmJiYcueXL1+u999/v8J9O3TooMsvv7xSneywf/9+LV68WF9++aW+/PJLLVu2THv37rW8vl69eurSpYvOPvtsXXTRRTr99NPtK2tR06ZNLX1N37Bhg6WvPV9++aUmTpyojz76SLm5uZXqdOKJJ6p///666aab1LJly0rtEWl79uzRggULfn2t/PjjjyosLLS01jAMNW/eXF27dlXXrl112WWXqUGDBjY3Lt/GjRvVrFmzCueaNGmijRs3Vji3d+9eZWVlacaMGVqyZImKi4tD6vPMM89o5MiRIa0pT3FxsZYvX65vvvlGOTk5+u6777RmzRp5vd6Q9nG5XDrttNPUvn17derUSRdffLEaNXL2ohNZWVkaOnSoo5lWjB07Vvfff78jWXl5efrPf/6jL774Ql988YV++OEHBQIBS2tjYmLUokULnX322eratasuuOACNW7c2ObG1nTv3l2LF1d8StqFCxeqe/fu5c6YpqmPP/5YU6ZM0fz587Vnz56QuqSnp2vFihUhrSnPd999pwULFmjJkiVavny5NmzYoJKSkpD3SUlJUdOmTdW0aVO1bt1aZ511ljp16qR69eqFrSsAAAAAAAAAAAAAAAAAAAAAAABQWde89rU+XxPaZ3mOBovu6q6mdd2252zPK1Tnxyo+N0F1YhjS+Ix0ZXR09rOKAICjW61atZSfn1/eSL5pmrWc6lPdxUW6AACEWWoIsztta2GRaZqmYRi7JR1vYTzeMIyapmmW+13QohhJsWHY51Ch7mdUNdA0zXWGYQyQlC0pvpzRhpL+78CtsrJM03yuCusBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQevXr9fo0aP17rvvKhgMVmmvvXv36u2339bbb7+t9PR03Xffferfv/8R5z/77DM98sgjFe4bFxen8847r0rd7PDNN9/ogQce0Ny5c2WaZpX22rJli8aNG6fx48crIyNDjz/+uJo1axamptYsWrRIPXr0qHCuW7duWrRokf2FDiMrK0tDhw6tcG7w4MHKysqyv1AU27lzpx544AG9+uqrKi4urtJefr9fM2fO1MyZM9WiRQtlZmZq2LBhiomJOex8Tk6Opff24MGDdfnll1epW1WZpqm5c+dq2rRpmjlzZkUn+C3Xrl27lJ2drezsbGVmZur000/XoEGDdNNNNyklJSWMrZ03d+5cPfTQQ1qyZEmV99q8ebOefPJJPfPMM7ryyiv12GOP6cQTTwxDS3v5fD698847euedd7RgwQKVlJRUah/TNLVu3TqtW7dOkydPVkxMjLp3764hQ4ZowIABiourvqdG3rJlix5++GG9+eab8vv9EethmqaWLl2qefPmaf78+fr6669VWFhY5X0DgYCWL1+u5cuX6/XXX5cktW3bVtdee62GDBmitLS0Kmfg8ILBoLKzszVlyhTNnTtXRUVFld5nzZo1WrNmjbKysmQYhrp27aqBAwfqmmuukdtt/wVY7FRSUqKXXnpJzz33nNauXRvRLhs2bNDLL7+sd999Vxs2bAjLnl6vV16vV8uXL9eMGTN+/fWmTZuqU6dOuuyyy9S7d2/VqsW5+AEAAAAAAAAAAAAAAAAAAAAAAI4lxaVBeX0BefwBeQoOHH1lt2Z13fpbu4aO9Eh1uxzJiTa5voCa1rX/s1kpSUff82uaUub0HElSRsdGEW4DAAAOp/qeAQIADi+Us6Pk2dYiNHmSjrc4myap8meQOgqZpjnHMIyBkqZKircp5m1JN9i0NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGxUXFys+++/X08++aQCgUDY98/JydGVV16prKwsvfzyy2rcuHHYMyLF7/dr9OjR+te//qVgMBjWvYPBoN59913NnDlTd999t/75z38qLo7TZMI60zT13HPPacyYMSooKAj7/uvWrdPNN9+sSZMm6bXXXtNpp50W9gwnFBcX680339QTTzyh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L0979+5VXl6etmzZom+//Vbffvut/ve//yk3Nzfk3HXr1unqq6/W3Llzq/wYhgwZoiFDhhzxfqs/G5ihXknDRqWlperXr5+WLVtWqfX169fXRRddpB49eujUU09V06ZNVbNmTcXGxio/P187duzQTz/9pC+//FJz5szRzz//HHLG7t27dfHFF2vp0qU67rjjKtUzXNauXau77767wrlzzz1X11xzjS677DI1aNCgwnm/36958+bptdde09atWyucf+WVV7RgwQJLnQ9lGIbS09PVo0cPtWrVSi1btlTTpk2VnJyspKQkud1umaapoqIi+Xw+7d69W7t27dKGDRu0evVq/fDDD/r222+1c+fOkLMBAAAAAAAAAAAAAAAAAAAAAAAixTRNFRSVyOsrVq6vSF5/QLkFAXn9AbWsl6zzTqnvSI80t8uRnGjj9QVUNznB9pyUY/T5zfUFHMtqdpxb6Y3rKM3tUkqSS2nJB45ul1LcLqUecquVGBfS5/GnL92qzOk5qszH7wxDGp+RroyOjX736wf/vzL7mmbZukP3AQAAzjOi6cP5AKKHYRhDJE2yOP6AaZr329fGOsMwXpc01OL4UNM0s2ysY4lhGJMlXWtx/FrTNKfY2QdHJ8Mw7pc0NtI9rKhZs6b27dsX6RoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCaefTRRzV69OiQ1jRt2lTjx49XRkZGpTJLSko0ceJEjRkzRrm5uUecS09PV05OToX7jR07Vvfff3+luhzOokWL1KNHjwrnWrRooR07dsjn8x1xJiMjQ08++aSaNGkScg/TNDVp0iSNGjVKu3btCmntk08+qTvvvDPkzPJYfV66deumRYsWhTXbqqysLA0dWvGp9QYPHqysrCz7C0XQ1KlTNWjQoJDWHHfccXr44Yd1/fXXKzY2tlK577zzju6++25t3rz5iDNW39t2/j79/PPP6tSpk/bu3RvSuhNOOEE33XSThg4dqsaNG4e01jRNffrpp3rssce0YMGCkNbecsst+ve//x3SGiuaNm2qTZs2VTjXunVr/fTTT4e9zzAMDRkyRGPHjq3U1zpJ2rFjh4YPH67s7GzLawzD0MqVK3XqqadWKtOqt99+WwMGDAh5Xfv27TVixAj1799ftWrVCmltYWGh3nnnHT322GNavXp1SGvfffddXXHFFSGt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W7ZYmm3UqJGuuOKKsGWfc845luaCwaAmTpyosWPHhi37SO655x7t3LnT9pzq4h//+IdeeOEFlZSUVDi7atUqDRo0SB988IFiYmJs6XPbbbfpiy++sGXvUHTp0kWdO3fWkiVLKpxdtWqV/v73v+uVV15xoBmizU033aTHH39c+fn5Fc5OnjxZF1xwgQYO5OIA0aJZs2aW5ubMmaNgMGjb175D3X333dqwYYPtOVa0atXK0tw333yjESNG2Nzm8E477TTLX68l6cYbb9TSpUvlctl/4bNbbrlFeXl5lmZr1aqlq666yuZGKM/atWtVWlpqabZJkyY2twEAAAAAAAAAAAAAAAAAAIgupUFTXn9AXl9Aub7fHz3+gDy+324H7ysqCUa6doVyfQHHslLd9v8b5mjk8QXUODXJ9py05Oh+fmMMKSXJpVS3Sylul9IOPSa5lJbs+vX+g7fE+NhI1wYAAFa0O/CZ0ewRkswQF5sH1h2yT2WsmFrJfEkypD4TqpYPAAAsi4t0AQCIBqZp/tcwjDMlDZZ0h6Q24Y6Q9B9J40zTXBTmvQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBjVufOndW7d299+OGHlub//e9/q2bNmnr00UfD2qO4uFiDBw/W7Nmzw7pvJBQUFKhfv3764osvVKNGDVsy3nzzTb388suW5//+978rPj4+bPknn3yyTjjhBP3yyy8Vzv7rX//SyJEjVbt27bDl/1F2drZeeukl2/avjk488UQNHz5czz//vKX5mTNnasiQIXr99dcVFxfeU65mZmZG1e/PU089pS5dulianThxolq2bKm7777b5laINmlpabrvvvs0atQoS/M33HCDGjZsqG7dutncDFakp6dbmvvll180ZcoUDR482NY+b731ll544QVbM0LRunVrS3Nz585VSUlJ2L8vWDV69GhddtlllmZXrlype+65R88884ytnd544w29++67ludvvfVWW38Gikamaco0TcXExES6iqSy3zMr4uPj1apVK5vbAAAAAAAAAAAAAAAAAAAAOGuvP6DpS7fK4wv8/uYvO+YVFss0I90y/Ly+gGNZqW6XY1nRxON35jmuER+rhLgYFZUEHclLcsUqJcmltGRX2dHtUorbpdTD3ZJcql0jXjExhiPdAABABLQbWHbMHiEp1B+czQPrDtknFCumVjJXkgypz4TK5QIAgEqJzCfyAdjGNM1Fkvibv0owTTMoaZKkSYZhnCfpWkkXSapfhW1XSZotaaJpmj9XvSUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAP3r66ac1b948FRUVWZp/7LHHtHnzZr300ktKTk6ucv6OHTt09dVX69NPP63yXtFi2bJluuqqq/Tee+/J5QrvBU4++eQTDRs2zPJ8w4YNNXz48LB2kKS+ffvqhRdeqHDO4/HovvvuszRbGf/73/90zTXXyDwar8RTRQ888ICmTZumPXv2WJqfMmWKduzYoTfffFP16tWrcv6+fft000036e23367yXuHUuXNnXXXVVZZ73XPPPQoGg7r33nttbmaNaZqaNWuWPv74Y7344ouRrnNUu+OOO/Tyyy9r48aNFc4WFhaqd+/e+uCDD3T++efbX86CwsJCTZw4UcFgUCNHjox0HUd16dLF8uzo0aPVr1+/sPxMczhz5szRddddZ8veldWpUydLc7t27dJbb72lwYMH29zo8C699FJ16NBBy5YtszT/7LPPqk2bNrY931999ZVuvPFGy/Nut1t33HGHLV2iWV5enjp37qz77rtPAwcOVGxsbMS67Ny5UxMnTrQ026VLF8XHx9vcCAAAAAAAAAAAAAAAAAAAwFm+QKkenv1TpGs4LtcXcCwr1R3ez45VF54CZ55jwzCU5nbpl7z9Ia+NMaSUJJdS3C6lul1KTXIpNfnA0X34W2J85P79MwAAiFLtBpYds0dICvXz7OaBdYfsY8WKqZXMkyRD6jMhtDwAAFBlMZEuAADRyDTNBaZpDpF0vKQzJN0maYKkRZLWStopyS8pKClf0i+SfpI0W9KTkoZKamaaZmvTNO8yTfNnpx8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcKxo2bKl7rvvvpDWvPXWW0pPT9cHH3xQ6dzS0lK98soratu2rT799NMjzqWnp1c6I5JmzZqlv/3tb8rLywvbnh988IF69+6t/futX8zj8ccfl9vtDluHg/r372959sUXX9T7778f9g5ffPGFevXqpYKCgrDvfTRISUnRU089FdKa+fPnq02bNnrttddUWlpa6ez33ntP6enpevvtt484E8n39rPPPqt69epZnh81apSGDBkS0dea3+/Xq6++qrZt26pPnz763//+F7Eux4qEhAS9+uqrMgzD0nx+fr4uvvhiPffcczLNylxwIDy2b9+uBx98UE2bNtXf//53bd26NWJdIuW0005T06ZNLc1u27ZNV1xxhYqLi8Pe4+2331a/fv0UCDh3YTUrWrdurbp161qaveOOO7RixQp7C5Xj6aefDmn+xhtv1OTJk8Pe48svv9TFF1+soqIiy2vGjBlj+Xk+2qxatUrXXnutWrVqpaefflper9fxDiUlJRo0aJB2795taf6yyy6zuREAAAAAAAAAAAAAAAAAADjW+QMl2ur167ute5VXGP5/v3w4qUkuR3Kijdfn3L/hTnUfo8+x37nnOOXAc1wjPlYN69RQm4a11e2k49S3fUNd37WZMi88WY9d3kYvXd1R793cWZ/8o5uWj+mlNY9coqVjeumTf3TTuzd11kvXdNSjfdvorgtP1nVdm6lP+4Y696TjdHrD2jqhTg0lxsc69pgAAEA1026g1GeCJGufN/09U8oeIa2Yam18xdSyeVXmc6pGWc92AyuxFgAAVEVcpAsAQDQzy87Es/TADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECUGj16tD755BN9/vnnltesX79e/fr1U3p6um666Sb16dNHxx9/fIXr1q1bp3fffVevvvqq1q9fX+5s37591bZtW+Xk5Fju5bTExETt37//sPd9/PHHOuOMMzR58mR16dKl0hk+n09jxozRM888E9K6c845R4MGDap0bkV7n3rqqfrxxx8rnDVNU1dffbUSEhJ02WWXVTnbNE09//zzuuuuu1Rc7MzFgKqra6+9Vh9//LGmTZtmec2uXbt0ww036PHHH9ewYcN0xRVXqFmzZhWu27Ztm2bMmKFXXnlF33//fbmzZ5xxhm6++WbdcMMNlnuFU/369ZWVlaVLL71UZadOrNjkyZO1ePFivfDCC7rkkktsbvibb7/9Vm+++aYmT56svXv3OpaLMj179tTdd9+tcePGWZovKSnRyJEjlZ2drRdeeEGnnnqqzQ3LFBcXa/78+crKylJ2djZfGyVdddVVevzxxy3NfvzxxxowYICysrKUnJxc5ez9+/dr9OjRevrpp6u8lx0Mw9Bf//pXvf766xXOer1ederUSbfddpuGDRumk046yYGGv+nWrZuGDh2qSZMmWZovLS3V0KFD9fPPP+uhhx5SbGzVL042adIk3XLLLSosLLS8pk2bNrrzzjurnF3dbdiwQXfeeafGjBmjq666Stdee63OPfdcGUZlLgJj3e7du9W/f38tWrTI0nxCQoIGDx5saycAAAAAAAAAAAAAAAAAAHB0KQ2a2usPyOsPKLfgwNEXkNf3h6M/IE9BQB5/QPuLg7+uf33IGTrvlPq296zhilWN+FgVFpfanhVNvP6AY1mpbpdjWdEk1+fcc/zGdX9RkitONVxV//fhAAAAldZuYNkxe4Qka59N/o15YN0h+xzOiqmV3F+SDKnPhPL3BwAAtomLdAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICqio2N1VtvvaUzzjhDu3btCmltTk6ORowYoREjRqh169Y67bTT1KJFC9WqVUuJiYny+/3yer1au3atcnJytGnTJkv7pqamasKECXrppZcq85Acc9ZZZ6lGjRr6+OOPD3v/2rVr1bVrV1155ZXKzMxUhw4dLO9dUFCgKVOm6JFHHtG2bdtC6lW7dm1NmTJFhmGEtM4qwzB0xx13aNiwYZbm9+/frz59+mjUqFEaM2aMXK7KXfjlyy+/VGZmppYsWXLEmdatW+unn36q1P5Ho5deeknLli3Tzz//HNK6tWvX6p577tE999yjZs2aKT09XS1btlSdOnVUo0YNFRYWKi8vT+vWrdPKlSu1evVqS/smJCTo9ddf19KlSyvzcMLm4osv1r333qvHHnvM8pqNGzfq0ksvVdeuXZWZmalLL71UsbHhvbBOaWmp/vvf/2rOnDl67733tGbNmrDuj9A99NBDWrJkiT777DPLaxYtWqQ2bdpo4MCBuv3223XmmWeGvVdBQYEWLFig2bNn6/3331dubm7YM6qz4cOH68knn1RJSYml+ffff185OTmaPHmyunTpUqlM0zQ1ffp0jR49utz3rmEY6tatmxYtWlSpnHAYOHCgXn/9dUuzRUVFevLJJ/Xkk0/qxBNPVPv27dW0aVOlpaUpKSnJ8tfBTp06qVOnTiF3ffLJJ/XJJ59oy5b/Z+/e4yS76zrhf6ovp6erai5dnelOQgLESIjh4oCIwAKBRZGwsMR1H5WAclEjRFwFdBUVgWcVdVdxXXUEuSyumkdXZcMCArqsICjIzQgqIpeEBAjdk65OZurUTFdPdz1/dE9mcplkZtJ1qjLzfr9ev9e36lSd3+dTp7sn053p7htP6Pn9fj+/+Iu/mD//8z/Pf/2v/zWPf/zjTzozSb7whS/k5S9/ed7+9ref1HlFUeQtb3lLJib8CPMjut1u3vKWt+Qtb3lL7n//++ff//t/n2c84xl5whOesKXXaWVlJW9+85vzC7/wC/nqV796wuc9//nPz+7du7esBwAAAAAAAAAAAHDf0+0dTrvs3eVa7vay1NmcZS/LZS+3HFxNv3/qeUud3taVvwetRpGv3HKwsrxRsNxdzfp6P2Njg/m+qmO16qf2PVL3dctlde/Ds82pyrIAAO7Wnis25jVXJTnZTwj6m+cds8+xrr36FPdNklpy+d673hcAqITvLAcAAAAAAAAAAAAAAAAAAAAAAAAATgvnn39+3vWud+XJT35yOp3OKe3xmc98Jp/5zGfudZfJycn86Z/+ac4+++wTPmdsbOxe556q3/md38lDHvKQHDhw4C4f7/f7+cM//MP84R/+Yfbs2ZPLLrssj3nMY/IN3/ANmZubS7PZTK/Xy/79+/PFL34xn/70p/N//s//yXvf+97s37//lDq94Q1vyAMe8IB787Lu0fOe97z8yq/8Sj772c+e0PPX1tby8z//8/nd3/3d/NiP/ViuuOKKE3ob33TTTbnmmmvye7/3e/nwhz98t8990pOelOc+97n5gR/4gRPqdCbYsWNH3vOe9+Sxj31svva1r53SHtddd12uu+66Lenz5je/OQ972MPyiU984oSeP8iP7V/4hV/IV77ylfyP//E/Tuq8D33oQ/nQhz6Uc845J9/xHd+Rpz/96Xnc4x6XmZmZk+6wuLiYf/iHf8hHPvKRfOQjH8kHP/jB3HLLLSe9D4MzOTmZt7/97XniE5+YT3/60yd83vr6en7/938/v//7v5+HPexhufzyy/O0pz0tj3zkI7Nt27aT6rC+vp4bbrgh1157bT7ykY/kwx/+cD7ykY+k16vul0nd19z//vfP933f9+Utb3nLCZ/z+c9/Pv/qX/2rXHrppfmRH/mRPPWpT8327dvv8bx/+Zd/ydve9ra89a1vPaH/Jr70pS/N9u3b8/73v/+Eu221pzzlKdmzZ0+uvfbakzrvhhtuyA033HBKma961avymMc85qTPa7Va+ZM/+ZM88YlPzMrKygmf94lPfCJPeMITcumll+aHfuiHctlll2XXrl13e87Kyko+8IEP5M1vfnP+1//6X1ldXT3pvr/xG7+RRz3qUSd93pnihhtuyOte97q87nWvy44dO/KEJzwhj3/84/PYxz42D3vYw9JqtU5qv16vl7/6q7/KO9/5zvzxH/9xvvrVr57U+bt27crP//zPn9Q5AAAAAAAAAAAAwGhbW+/nlm4vy91eljqbs+xlubzD7PbS7vTS7vZyaHW90o7L3er+Lfhss8hXbjlYWd4oWFvvZ/+h1eyqFwPPmmkMPqNqY7Vkpl5kplGk1SjSqhdpNTfn5rGvn2sOuyYAwHDsuWJjXnNVkv5JntzfPO+YfZLk2qtPcb8kqSWX7739fgBA5SaGXQAAAAAAAAAAAAAAAAAAAAAAAAAAYKs86lGPytve9rY861nPysGDw/ulJ7/zO7+TJz3pSSd1TlEM7xeJnH/++XnDG96QK6645x8afe211+baa68daJ+f+7mfy3d/93cPNCNJJicn82u/9mt5+tOfflLn3XjjjXn5y1+eH//xH88ll1ySPXv25IEPfGB27NiR8fHxdLvdtNvtXHfddfnUpz6V66677oT2nZuby9VXX533vve9p/JyTmsPfOAD8+53vzvf9m3flptvvnloPV796lfnOc95zkmdM8iP7Vqtlje/+c259dZb8/a3v/2kz7/pppuyd+/e7N27N8nGdX7wgx+c8847L2effXbq9Xq2bduWtbW1rKys5ODBg1laWsrXvva13HTTTfmXf/mX3HLLLVv8qhiEXbt25T3veU8uvfTSfP7znz/p8z/96U/n05/+dP7Tf/pPmZiYyIMf/OBceOGFOe+883LWWWdleno6U1NT6fV6WVlZSbfbzeLiYr72ta/ly1/+cj73uc/l0KFDA3hlp7df/MVfzNve9raT/jj7wAc+kA984AMZHx/Pwx72sDziEY/I7OxsZmZmMjU1lbIss2/fvnz+85/P3//93+emm2464b0f/vCH57WvfW1+8Rd/8SRfzdb7xV/8xVx22WXDrnFCHv3oR+e3f/u388IXvvCkzz327fmN3/iNueSSS/KABzwg27dvz/j4eDqdTm666ab88z//cz7+8Y+n2+2ecs8XvehFufLKK0/5/DPN/v378653vSvvete7bjs2Pz+fiy66KOeee27OPffc7NixI9u2bUtRFDl48GDKskyn08mXvvSlfPazn80XvvCFHD58+JQ7vPGNb8xZZ521FS8H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t95SW1tbxj02bNigiy++WLW1tRmvzcbmzZs1ffp0rVixwpG8TDQ2Nuqoo47SkiVLtPfeezuSOXv2bD377LNZrx8+fLj2228/TZgwQYMHD1ZJSYlaW1u1efNmffTRR1q+fLkaGhp63MeyLM2aNUv77rtv1l3s8NRTT+mMM85QKpVyu8rnrFy5UkcccYRef/11DRs2LOf7X3bZZVq2bFnO9wWQHa/bBQAAAAAAALAL6EhJm2JSY53UVCc1RrYd66S2T3KblUxILRukstz/AvtzSodIvoCUjNuf5RZPnjRwrFQeliqq/n0cMdHtZgAAoA+yLEsej8eRLMNvOJLT16xKrFJnV6fy8/Jtz9qzfE/9bebflOfhwkkA2NVZHR1KrVqtZDSiVCSiZCSqZDSq1MqVsnJ0EWMyUqcBhxyck7164guH1LJkiSNZtvJ4VFBZKV8oJF84pMJwWL5QWL7QOOWVlLjdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAaqidXSpLm1KyQZWW21rK61+24TzpqljZklSdJHo80t3piRnkAcicej+v5559Pe/6II46wr8w29fX1mjZtmlavXt3j7NChQ7Vw4UL913/9l+29eis/P18PPvigRo0apZ/85Cc9zj/yyCPyer168MEHHbt3J3onmUxq2bJleuutt7R8+XLFYjGZpql4PK4tW7aoq6tLxcXFKi4uVllZmUaNGqXKykoZhqGJEydq8uTJGjduHP+9bTB//nz99re/3enMiBEj9K1vfUtf//rXtd9++ykvb+f3V02lUvrLX/6i++67T4sWLcqoz5NPPqkXX3xRRx11VEbrMtXZ2anTTz9dy5Yty2r9sGHDdNxxx2natGnaa6+9ZBiGysrKlJ+fr+bmZn388cf617/+pddee03PPPOMPvzww4wzNm7cqOOPP15Lly7VkCFDsuqZrscee0wPPvhgxusGDx6s73znOzr77LM1ceLEHuffe+89Pf7445o/f77Wr1//pXNbt27VrFmzdOGFF2bcyQ7PP/+8qqur1d7entX6SZMm6fDDD9cBBxygcDisMWPGyO/3q7i4WO3t7WpublZ9fb0++OADvfrqq1q4cKHWrFmTUcbKlStVXV2txYsXq6CgIKueX+TZZ5/VI488ktXaCRMm6KijjtIee+yhUCikcePGqays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6+Vj28ZEI1vqW1IbrQ21GwAMy8LsbGanuum192S200mv3Umv3c7s7bcn8/OLWqPXafe55dfUWs2BZQ3V6GjGL744tWYz461maq1WRp8Cv9AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsCQ3vSW5+a1HHaiSG689tLvtmqFU6otbbjh8XUd9F/iR677iuqFUgmEqiiLNZjMvfOEL843f+I255JJLUpZlNm/enPXr12f9+vWZm5vLvn37cvfdd6fT6eQf/uEf8tGPfjR//dd/nflFfjfvE33hC1/I933f9+XDH/5wRkdHV/iqBuc973lPfuzHfixVVZ188FHOOeec3H///Yse3+12c+WVV+bmm2/OBRdcsNSaTxojIyO59NJL88IXvjDf8A3fkEajkbIsc+6552b9+vVZt25dDh48mEceeSR33XVX9uzZk7/7u7/LRz7ykXzmM59Z8n+HI2666ab823/7b/P7v//7K3xFi/crv/Ir+dM//dMlzxsbG8vLX/7yfNd3fVde+MIXZsuWLTnjjDNSVVUefvjhdLvd/P3f/30++MEP5iMf+ciS/86+733vy3Of+9z87M/+7JK7AQCsRsVyXzSSFEWxkMfdURlOjRVY40TX0O/1j2RUVVU9ed8NA7BoRVHMJNl4vPMbN27MzMzMABsB8FS2s70zk7snUw3ordtIMZILNlyQxkQjZb1MOVGmrJdpTDRy5tozUxQr8RYLAJ58Fnq9zE5NpdfupNfek9lOJ712J7N33JEs8xdtjhidmMjWv/7UQP6dnX9kX2594Qv7njMwY2MZv/ji1Fqt1JrN1FrNjLdaGS/LjIyPD7sdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADNX8/HxuvfXWRY9/xjOekdHR0T42YqBuekty81uPc7JIrr4+2XbNQCv1xS03JDdemxzvu8Av/5nkiusGWglWwvvf//685jWvWfT4s846K9/1Xd+Vl7/85fnO7/zOnH322cvKve+++/J7v/d7ecc73pH7779/WWu89a1vzZve9KZlzR22G264IT/0Qz+UhYWFRc8piiJvf/vb8yM/8iO5+uqrc/PNNy8pc+vWrbn55ptz/vnnL7XuwLztbW/LT//0Ty96/IUXXphXvvKVefnLX56rrroqExMTy8qdmprKu971rvy3//bfsnfv3mWt8d73vjc/8AM/sKy5p+Kmm27KS1/60iX9WRofH88b3vCGvPnNb8655567qDn33HNPfuVXfiXvete7cvDgwUVnjY6O5iMf+Ui+4zu+Y9FzgNVh165dueKKK0467vLLL8+uXbv6Xwj64OlwP6Ner5/s9c3eqqrqg+rzZFdU1XFuCnBSRVEs5Lh3Vfofv4w5K911qR2Ol18kqaqqenL93wiAZSmKYibJxuOd37hxY2ZmZgbYCICnqp3tnZncPZlqAG/bihT5D9/wH/LDz/7hjI+O9z0PAFarhQMHMnvbbel1OuntaafX6WS23c7snXcmS/gFgKXa+omPZ+yss/q2/tH2XHFl5u65ZyBZK2bNmtTKizPeaqXWbKXWaqbWamV8y5YU4167AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwLHMz8/n1ltvXfT4ZzzjGRkdHe1jIwbmprckN7/1JIOK5Orrk23XDKRSX9xyQ3LjtcnJvgv88p9JrrhuIJVgpbz//e/Pa17zmhOO2bBhQ773e783P/iDP5iXvexlGRsbW7H8ffv25Vd+5Vfya7/2a5mbm1vS3FqtlltuuSWXXnrpivUZhPe973255pprMj8/v+g54+Pjec973pMf+IEfSJL0er28/vWvz/ve974lZV966aXZtWtXzj333CXNG5S3ve1t+emf/ukTjjnzzDPz2te+Nv/qX/2rfOu3fmuKolix/AcffDDXXXddfvd3f3fJc88888x86UtfylkD+g7pJJmZmcmll16ae5bwXdKXXnpp3v/+9+fZz372sjI/97nP5fu///uzZ8+eRc85//zz86UvfSn1en1ZmcBw7Nq1K1dcccVJx11++eXZtWtX/wtBHzwd7mfU6/Xs3bv3REP2VlXlH+lFWrl3Qk9Pd+Skd1b6an2Ssw53ON67iCf2O9a4hSR7k/QOP8aS1JKcdvhxvHWPXvuJ6x7dqZfk3uOsAwAAsOJ2tndmcvdkqgG9ZatS5Tc/85s5Z9052d7aPpBMABimhf370+vcltlOO712J712O71OJwfvvDOpBn/LtNfuZGxAv9hQa7Uyt4RfaBikYs2ajDcaqbVaGW81U2u2UtvayvhFF6VYs2bY9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWv5vektz81kUMrJIbrz20u+2avlbqi1tuONx/Ed9FeuT5uOK6vlaCQXn2s5+dN7zhDXn961+fer3el4z169fnv/7X/5pXv/rV+d7v/d7cs4TvxO31evkv/+W/5H/8j//Rl2798Gd/9md53etel/n5+UXPmZiYyI033pjv+I7veOxYrVbLe9/73mzevDnveMc7Fr3Wl770pVx55ZXZtWtXzj777CU0H75v+qZvyrXXXpvXvva1Wbt2bV8yzjzzzLzrXe/Kq171qvzrf/2vMzMzs+i5Dz74YN7ylrfk7W9/e1+6HcvP//zPL+nvzOWXX54PfOAD2bBhw7Izn/e85+Xv/u7v8spXvjK7d+9e1Jx77rknv/ALv5Bf//VfX3YuAMBqMDbsAk9mVVWVw8ouiuK7k/xOjn935+jjxeHtfUk+leTvkvxzkluT3JvkK1VVHXOdoijWJzknSSPJM5M8J8k3J3luktGjso7ML46aXh3+eU2SDyZ5U1VV+xZ3hQAAAMuzs70zk7snUy3mw/AnKFLkRee9KJ++99NLnl+lyuTuySTJ9tb2JWcDwGq0sG9ferfdll67k9lOO7097fQ6nRz88peTY99SHIpeu531L/mmgWTVms3s+/jHB5J1PMX4eMYvuSS1ZjO1ra2MN5upNVsZ33JRijG3/QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACW5aa3JDe/dQkTquTGaw/tbrumL5X64pYbDvdewveTHnlerriuL5VgEL7jO74j1113Xb7zO79zYJkveclL8td//de54oorctttty163p/92Z/llltuybZt2/pXboXs3LkzP/iDP5i5ublFz7ngggvyoQ99KM997nO/7lxRFPk//8//MxdccEH+83/+z6kW+V3KX/ziF3PVVVflYx/7WM4666xFdxmGoijy6le/Otddd12+6ZsG893MSfKqV70qf/VXf5WrrroqDz744KLnXX/99fnpn/7pnHfeeX1sd8g//uM/5rd+67cWPf4lL3lJPvCBD2TDhg2nnF2v1/OhD30oV111VT796U8vas5v/uZv5t/8m3+TZz/72aecDwAwLGPDLsDSFEWxNslvJ/mhI4eeMKR6wvFbk/xRkhurqvr8UvOqqtqXZOrw42NH9agn+Z4k35fkVTn0Z6k6Rn6VZCTJv0vyyqIo/nVVVZ9cag8AAIDF2Nnemcndk6mW8mH4YUWK7LhsR7a3ti97nSpVJndPJkm2t7YvuQMADMv8I/sye1snvT3t9Dqd9Np7Mtvu5ODddw+72qL0Ou2BZdVazYFlFbVaxpuXpNZspdZqpdZqptZsZs1FF6UYHR1YDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICnvHs+l9z8q8uYWCU3Xntod9s1K1qpL2654XDfpX8XeG7+1eTS707Of96K14J+esUrXpGf//mfz0te8pKh5G/ZsiUf+chH8uIXvzhf+cpXFj3vd37nd/LOd76zj81O3Qc/+MG89rWvzcGDBxc951nPelb+4i/+IhdddNEJx/3UT/1UNm/enB/5kR/J7Ozsotb+/Oc/n5e97GX56Ec/mk2bNi2606AURZEf+IEfyM/+7M/m2c9+9lA6PP/5z8+HPvShfPu3f3sOHDiwqDkHDhzIu9/97rzpTW/qc7vkzW9+c+bm5hY19qyzzsr73//+bNiwYcXyN27cmPe///3Ztm1bHn744ZOOn5uby5vf/Obs3LlzxToAAAza2LALsHhFUZyb5H8meUGS4hhDqqOOfzTJW6qq+lg/ulRVNZPkhiQ3FEVxXpJrk/zHJBsP9zjSpThqv0zy0aIofrSqqj/qRy8AAODpa2d7ZyZ3T6ZaxofhRYrsuGxHtre2J8lj2+WsV6XK5O7Jx60DAKvF/N69me100mu302t30ju8P3fPPcOudkpm97QHllVrtVZ8zeK001K75JLUWs2MN1uptVqptZpZc8EFKUZHVzwPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCc4/3nJ1dcnN16bLPm7sqvD85Jsu2alm62cW25Y5vUlSXHo+Tn/eSvdCvrmJS95Sd761rfm8ssvH3aVNBqN/OEf/mFe8YpXLHrOe9/73rzjHe9IrVbrY7Pl+/CHP5zv+77vy+zs7KLnfNu3fVt27tyZM844Y1Hjr7nmmpx33nn5l//yX2ZmZmZRc2655Za87GUvy0c/+tGcfvrpi+7WT0VR5BWveEXe8pa3ZNu2bcOukxe96EV5xzvekTe84Q2LnvPud787b3rTm/rYKvnCF76QD3zgA4se/9//+3/PBRdcsOI9tmzZkt/5nd/Ja1/72kWN/5//83/mi1/8Yp71rGeteBcAgEEoqmo5NwoYtKIoGkluSnJRkiJfu8PzxP09Sf5dVVUfG0LHTUl+OcmPH304j78bdeTnn6mq6tcGWA+AVaIoipkkG493fuPGjYu+GQgAR+xs78zk7slUy/gwvEiRHZftyPbW9oGtCwD9Nj8zk167k157T2Y7ncP77czdd9+wq/XF6Bln5Bmf+uRAsub37s2tL3rxsuYW69al1mweerSaGW+1Umu1smbz5hQjIyvcFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgV8/PzufXWWxc9/hnPeEZGR0f72IiBuOWG5MZrk2V8t3VSJFdfn2y7ZqVbnbqn6nXBcezbty/r168fdo2v87rXvS433HDDosd/7GMfyxVXXNHHRsvzkY98JK961aty4MCBRc/5vu/7vvzhH/5h1q5du+S8z372s3nlK1+Zu+++e9FzXvSiF+UjH/lI6vX6kvNW2mr881hVVb7t274tu3fvXvSc2267LY1Go2+dXv/61+f/+X/+n0WNffnLX56/+Iu/6FuXJLnqqqvysY99bFFjX//61+fd7353X/sAK2PXrl2L+rf18ssvz65du/pfCPrg6XA/o16vZ+/evScasreqquG/EHySGBt2AU6uKIpNST6UZEsO3d2pkhSHTx+521Mk+W9JfrqqqsW/W1tBVVU9lOTaoij+NMkNSc7J13c98vNbi6K4v6oqr6QBniSKovj3Sa5dgaVW150yAJ70drZ3ZnL3ZKplfBhepMiOy3Zke2v7Mc8fOb6c9atUmdw9+bh1AKDf9n7kI7n3F38pcw88MOwqAzX/8MOZe+ihjG3a1Pes0Y0bM3buuZm7777jjhlZty7jrVZqrVZqzWZqWw9tx84/P8XISN87AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBM2645tL3x2mTJ351dHZ531DqrwS03LPN6kqRIrr5+dV0PLML69euHXeGYfvEXfzHvfe97s7CwsKjxN910U6644oo+t1qam266Ka9+9atz4MCBRc/5D//hP+Qd73hHRpb5/b7Pf/7z86lPfSqveMUr8k//9E+LmvPpT386r3jFK/LhD384GzduXFbuSlmNfx6Losgv/dIv5aqrrlr0nJtuuimNRqMvfR544IG8973vXdTYoijytre9rS89jvb2t7893/AN37CosX/8x3+ct73tbTn77LP73AoAYOWNDbsAJ1YUxWiSnUmeka/d3SmesL+Q5A1VVf3u4Bt+vaqqbiqK4sVJPpDkuTnUtcjXeh/5+V1FUUxVVfVXQysLwFKcneRZwy4BAEfb2d6Zyd2TqZbxYXiRIjsu25Htre0nHHfk/HJyqlSZ3D35uHUAoJ9GNmzI3AMPDLvGUPT2tDP2TS8eSFat1crcffdlZMOG1JrNjG9tpdZspdZqptZqZey881IUxUC6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALDCtl1zaHvjtcmSv0O7OjzvqHWG6ZYblnkdSVIkV1+/Oq4DniJarVauvPLKfOQjH1nU+E9/+tN9brQ0H//4x/OqV70q+/fvX9T4oijylre8JW9605tOOXvLli35xCc+kVe/+tXZvXv3ouZ86lOfyitf+cp86EMfyoYNG065w1PNlVdemVarlXa7vajxn/70p/O//W//W1+6/PEf/3EOHjy4qLGveMUr8pznPKcvPY62bdu2vPSlL13U39eDBw/mT/7kT/LGN76x770AAFbayLALcFI/leSyfO3uTvGE/YUk/6aqqt8dQrfjqqrqziRXJvmnI4cOb4ujfl6T5PeLolg34HoAAMBTwM72zkzunky1jA/DixTZcdmObG9tX9T47a3t2XHZjhSPvaVZvCpVJndPZmd755LnAsBS1ZrNYVcYml5ncb/8sBLO/S//Ja1dN+UZn/7blH/y3mz+5V/OmT/y/8uGb/u2rDn//BTF0l8zAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALCKbLsmufr6ZBnfbZ1UyY3XJrfcsNKtluaWGw71WMZ3gSfFoevfds1Kt4KnvX/5L//losfu2bOnj02W5pOf/GRe+cpXZt++fYsav2bNmrznPe/Jm970phXrsGnTpnzkIx/J1Vdfveg5n/jEJ/I93/M9efTRR1esx1PJavnz+Id/+IeLHvsTP/ETfevxRD/5kz+56LFLuQYAgNVkbNgFOL6iKLYm+fl87e7O0XeqisPH/2tVVe8edLfFqKrqwaIovifJ3yeZyKG+Rb7WPUnKJL+SZPGvvgEAgKe9ne2dmdw9mWoZH4YXKbLjsh3Z3tq+pHlHxi8nt0qVyd2Tj1sHAPph9KyzMjIxkYXp6WFXGbjZdntgWbVLGgPLAgAAAAAAAAAAAAAAAAAAAAAAAAD4/9i787io6v2P4+8Dwwyg4IKZO+KMW5uU3dKszL1NRdst2xelvK2/ForqZnnrVrdrqWVqpha2mVi2b3rTzNTEskydcVfcN9xmWM7vD+RmhXJmmDOD8no+HjxA5v35ft4HQWDGx2MAAAAAAAAAAAAAAAAQJekDSl/nZkpBP6e2eXDukHMiKS8nxN6SZEgZo6LTG6gGzjnnHMvZVatWqaSkRDExMTY2qtjcuXN1wQUXaM+ePZbySUlJmjJlinr06BH2LvHx8ZoyZYqGDBmiUaNGWZqZOXOmevfurenTpyshISHsnY5m55xzjp599llL2RUrVtjSwev1at68eZayDRs2VPfu3W3pUZ5evXqpfv362rx5c4XZuXPnyufzye12R6DZsWXv3r366quvtHDhQi1evFhLly7Vjh07tHv3bu3du1cul0uJiYmqV6+e0tLS1LJlS3Xo0EFnn322mjZtGu36YWOapjZu3KiVK1dq48aN2rdvn/bu3avCwkIlJiaqRo0aqlWrllJTU5WWlqb4+PhoVw6rgoICffXVV/r++++1ZMkSLVu2TDt27FBBQYECgYBq1qyp5ORk1alTR61atdIJJ5ygdu3aqVu3bkpOTo52/ajYs2ePVq5cqTVr1qigoED79u3Tvn37FBcXpxo1aqhGjRpq0qSJWrRooZSUlGjXDQvTNLVu3Tpt2LBBW7Zs0fbt2+X3++X3+xUTE6PExMT/vSQkJPzva+a4446LdnWgSnNEuwCO6DFJ8Sq9h8c4+L6yt01J3x/MVFmmaa40DGOwpMn66z1VZdeSaRjGc6Zpro94QQAAAABHnWneacqenS0zhAfDDRka2mmo+nr6hrS7bC6U/aZMZc/O/sM5AIBjm2maKt66VX6vV063W3H169u+0zAMuTwe7V+wwPZdVY3f64t2BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxr0geUvs7NlIJ+bm3z4Nwh50RCXk6IfSXJkDJGRbYvUM20bNlShmHINCv+Gi0uLtbevXuVlJQUgWblmz9/vnr16qXdu3dbyjdo0EAff/yxTj31VNs6xcTEaOTIkWrcuLEefvhhSzNff/21+vbtqw8++EDx8fG2dTvatG7d2nJ2165dtnT4+OOPLWevuOIKxcTE2NKjPLGxsbriiiv00ksvWcp//PHHGjJkiM2tomPVqlVKS0urMJeamqpVq1ZVmCsuLta7776rN954Q1999ZUOHDhw2Oy+ffu0b98+bd26Vb/99ps++eQTvfjii5Kk9u3b68orr9TNN9+s2rVrW72cKmHfvn368ssvNWvWLM2aNUt5eXnav3+/pVnDMNSsWTN17NhRZ599tnr06KFWrVrZ3Dj8ioqKlJubq9GjR2vmzJkqLCw8bHbnzp3auXOn1qxZo0WLFv3v/XFxcercubOuvPJKXXPNNXK5XJGoHnFFRUWaPXu2Zs2apdmzZ2v+/PnasmWL5fnatWurQ4cO//t8OeOMM2xsGz7r1q3TF198oe+++07z5s3TsmXLLH+dHCoxMVGpqalq3ry5PB6PzjjjDHXo0EEej8eG1sDRx7DyywkizzCMZpK8kmLL3qXf7+0xJJVIOtM0zQVRqBc0wzBmSjpHpddgHHx32dumpBdM07wvSvUAABYYhvG4pMfs3pOUlGT5zkgAQPUzzTtN2bOzZYbwYLghQ0M7DVVfT99jpgcAoGowTVNFm7fI712ugM8nv9cnv9crv8+nkoMPtDccNky1+/eLSJ/8Rx/TznfeiciuqiQ2JUWtZs+Kdg0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCMKC4u1rJlyyznW7VqpdjYWBsbIarycqTcTCmE57aWDCljlJQ+INyt/upo6QlUcykpKdq+fbul7IYNG9SwYUObG5Vv4cKF6tatm3bs2GEp37p1a3366adq3ry5vcUOMXHiRN18880qLCy0lL/gggs0depUuVwum5sdHQoKCpScnGwp63Q65ff7w96hd+/emj59uqXsN998o/POOy/sHY7kyy+/VI8ePSxle/furQ8++MDmRtGxatUqpaWlVZhLTU3VqlWrDnt7UVGRRo8ereeee+6IuWAlJydryJAhysrKUmJiYtjOtcMXX3yhCRMmaNq0adqzZ0/Yzj311FN11VVX6aabblLdunXDdq4dSkpKNH78eD322GNav3592M5t0KCB7rrrLt11112H/Xd+xowZ6tKlS4Vnde7cWTNmzAhbt1B9++23evPNNzVlyhRt3bo1bOe2aNFCV111lTIzM9WoUaOwnRsOu3bt0oQJE/TGG29o/vz5Ms1QfrexJiUlRWeeeaZ69OihSy65RE2bNrVtVyRVh/szkpOTVVBQcKRIgWma1n7IgQw7v9AQOsMw/inpAZXey2McfHfZ26akz03TvCBK9YJmGEYvSZ/or9ejg38ukHScaZqBKNQDAFhgGMbtkjLDcFQbSTGHuzEpKUm7d+8OwxoAwLFmmneasmdnywzhwXBDhoZ2Gqq+nr7HbB8AgP1M01TRpk3yL/fK7/Mq4PMdfNunkiPfaa26N92o4//v/yLSc/vESdo0bFhEdlUVsfXqyeXxqOnoVxTDfwgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhUFxcrGXLllnOt2rVSrGxsTY2QtTl5Ui5mVIIz20tGVLGKCl9QLhb/a6q9wPwP02bNtW6dessZdevX69GjRrZ3OivfvrpJ3Xt2lXbtm2zlO/YsaM+/PBDpaSk2Nzsrz777DNdeuml2rNnj6X8xRdfrClTpsjpdNrcrOorLi6Ww+GwlI2Li1MgEAjr/sLCQtWtW9fS311iYqJ27NgR8b+3AwcOqE6dOjpw4ECF2aSkJG3btk1xcXERaBZZq1atUlpaWoW51NRUrVq1qtzb5s+fr1tuuUV5eXnhLXeItLQ0vfbaazrvvPNs2xGq999/X0899ZR+/PFHW/fUrFlTgwYN0n333afjjz/e1l2hWLhwoW644QYtWrTIth1t2rTR2LFj1alTp7/cNmPGDHXp0qXCMzp37qwZM2bY0K5iJSUlys3N1dNPP6158+bZusvlcun6669Xdna2GjdubOuuiuzYsUNPP/20Ro4cqb1790Z8v2EY6tChgy677DINHDhQ9erVi3iHcKkO92ckJyeroKDgSJEC0zSTI9XnaGftp0FEQ4aOfC/PqxHqERamaX5mGMYqSakqvS7j4EvZNdaU1E3SJ1EpCACokGmaIyWNrOw5hmHslpRU+UYAgOpkmneasmdnywzhwXBDhoZ2Gqq+nr5h7VR2Xii9TJnKnp39h3MAAFWHaZoqys+X3+eTf7lXfp9XAa9Pfp9PJRb/Y8Kf+b3eMLc8PJfHHbFdkeY47ji5WnrkdHvkcrtL327RQo46daJdDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMe69AGlr3MzpaCfc9s8OHfIOeGUlxNiL0kypIxR9vQCUK6CggLL2Zo1a9rYpHy//PKLunfvrm3btlnK9+nTR2+99ZYSEhJsbla+Xr16acaMGbrooou0adOmCvPTp0/XFVdcoXfeeUdxcXERaFh1Rftzcd68edpj8bnDzznnHDmdzrB3qEh8fLw6deqkr776qsJsQUGB5s+fr44dO0ag2dHlmWee0cMPP6zi4mJb96xcuVI9evTQ8OHDlZmZaesuq5YvX67bbrtN33zzTUT27dmzR88995zGjBmjZ555RrfeeqsMw4jI7oq8+OKLuv/+++X3+23d89tvv+mcc87Rk08+qaysLFt3hduCBQs0aNAgzZ8/PyL7/H6/Ro8ercmTJ+upp55SZmamYmJiIrL7UDk5ORoyZIi2b98e8d1lTNPUnDlzNGfOHNWpU0fXX3991LoAkeaIdgH8lWEYHkmtVXpPT9l38kPv9SmU9Fmke4XBx5KOdA/WxZI+iVwdAAAAAEeDad5pyp6dLTOEB8MNGRraaaj6evra0Ez/OzeUfqZMZc/O/sM5AIDIMktKVLghXwGfV36vV36vT36fTwGvVyX79oV1V8DrC+t5R+J0eyK2yy6O44+Xy+2Wq6VHTrdbLk9LudwtFFurVrSrAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoDpLH1D6OjdTCvq5t82Dc4ecEw55OSH2kSRDyhgV3j4AjqiwsFC7d++2lI2NjVXNmjVtbvRHS5YsUbdu3bRlyxZL+dtuu00jR45UbGyszc2OrH379vruu+90/vnna/ny5RXmc3NzNWDAAE2ePFkOhyMCDaumbdu2Wc7Wrl077Pvnz59vOduhQ4ew7w9m91dffWUpu2DBAnXs2NHmRkePQCCgW2+9VRMmTIjYzqKiIt1+++3as2eP7r///ojtLc+IESN03333ye/3R3z3rl27NGjQIL355pt655131KBBg4h3KFNSUqLMzEyNHj06YjtN09TDDz+sNWvWVInvUxUJBAK6//779dJLL6mkpCTi+3fv3q0hQ4Zo6tSpeuedd5SSkhKRvYFAQLfccosmTpwYkX0Ayld9fxqu2s47zPsNld4D9KNpmvsiVyds/isp8zC3GZI6R7ALAAAAgKPANO80Zc/OlhnCg+GGDA3tNFR9PX1taPa7svND6WnKVPbs7D+cAwAIP7OkRIXr18vv9crv9Srg9cnv88m/YoXMfZG5m61w/XqV7N2rmBo1bN/lqH+cYpKTVWLxP6dEk6NhQ7ncbrk8Hrk8bjkPvh2blBTtagAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAED50geUvs7NlIJ+Dm7z4Nwh51RGXk6IPSTJkDJGhacHAMt++eUXmaa1r9nmzZsrJibG5ka/W7Zsmbp166ZNmzZZyj/xxBPKzs62uZV1LVq00HfffaeLL75Yc+fOrTD/3nvvKTY2Vm+++aZiY2Mj0LDq+fnnny1nW7RoEfb9P/74o+Vs+/btw77fqtNPP91yNphrOtYVFRXpkksu0fTp06Oy/4EHHlD9+vV1/fXXR3y33+/X4MGDNX78+Ijv/rNvv/1Wp59+ut5//32dccYZEd9fVFSkAQMG6N133434bkkaPXq0iouLNWbMmKjst2LNmjW69NJLNW/evGhX0ddff63TTz9dH3zwgU4++WRbd+3bt08XXXSRZsyYYeseABVzRLsAynVCBbcviUiL8Pv1MO83JRmSWhqG4TBNsyiCnQAAAABUUdO805Q9O1tmCA+GGzI0tNNQ9fX0taHZX5XtCaWvKVPZs7P/cA4AIDRmcbEK162T3+eT3+uT37tcAa9P/hUrZB44EO168q9YqYSTT7J9j2EYcrnd2r9woe27rIpr1EhOj1sut0cuj0cuj1tOt1uxNWtGuxoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQvPQBpa9zM6Wgn4vbPDh3yDmhyMsJcb8kGVLGqMrtBxCS+fPnW862atXKxiZ/5PP51LVrV+Xn51eYdTgcevXVV3XDDTdEoFlw6tWrp6+//lpXXHGFpk+fXmH+7bfflsPh0MSJExUTExOBhlVLtD8ff/zxR8vZ0047Lez7rTr99NMtZ4O5pmOZaZq67rrrLH0d2ikzM1N/+9vfdOKJJ0Zs54EDB9SnTx998cUXEdtZkfXr1+u8887T9OnT1bVr14juHjx4sN59992I7vyzsWPHyuPx6IEHHohqj/L8+OOP6tWrl7Zu3RrtKv+zatUqdenSRV9//bVOOeUUW3YUFxfr0ksv1YwZM2w5H0BwHNEugHJV9NPLuoi0CL/15bzP0O/3bjkktZL0a8QaAQAAAKiSpnmnKXt2tswQHgw3ZGhop6Hq6+lrQ7PDK9sXSm9TprJnZ//hHADA4ZnFxSpcu1Z+r1d+r6/0tc+nwIoVMv3+aNc7LL/Pq4STT4rILpfHrf0LF0Zk16HiGjeWy+OR0+OWy+2Rq6VHzrQWiq1ZI+JdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFulDyh9nZspBf2c3ObBuUPOCUZeToh7JcmQMkaFthdApX3wwQeWs2eccYaNTX63cuVKdenSRevXr68wW6NGDb377ru64IILItAsNImJicrNzdWgQYM0duzYCvNvvvmmHA6HXnvtNcXExESgYdURzc/HoqIiLVmyxFI2KSlJjRs3Duv+YDRp0kQ1a9bUnj17Ksz++uuvKioqksPhiECzqis7O1s5OTmWsgkJCTrttNPkdrvVtGlT1ahRQ06nU/v27dPGjRu1fPlyzZ07V7t37w66x/79+3Xttddq3rx5Efn69vv96tevn7744gvbdwVr//796t27tz7++GN17tw5IjuHDRtm6d/hw6lbt65OO+00tWnTRvXq1VPNmjV14MAB7dq1S16vVz/99JN8Pp+lsx566CG1b9++Sn1tzp07V+eff7527twZ7Sp/sW3bNnXt2lXffvut2rZtG/bzhw4dqk8++STs5wIITdX5lxGHStWR7/UpiFSRMLPSu5mkX+0uAgAAAKDqmuadpuzZ2TJDeDDckKGhnYaqr6evDc0qVrY3lP6mTGXPzv7DOQBQ3ZlFRQqsWSu/d7kCPp/8Xp/8Xq8CK1fKDASiXS9oAa83YrtcHo99hxuG4po0kcvtlqulR063Wy5PS7lapCkmMdG+vQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBVkz6g9HVuphT0c3ObB+cOOceKvJwQ90mSIWWMCm4fgLDZtWuXPv/8c8v58847z74yB61evVpdunTR2rVrK8zWr19f06dP19/+9jfbe1VWbGysxowZo8aNG+sf//hHhfkJEybI4XBozJgxMgwjAg2jb+nSpfr5558t58P9+bhmzRoVFRVZynrsfN5ui9xutxYtWlRhrrCwUGvXrlVaWloEWlVNX3zxhYYNG3bETO3atXXNNdfo8ssvV4cOHRQXF3fEfHFxsb755huNHj1aU6ZMkWla/znoxx9/1Guvvaabb77Z8kyobrvtNn366achzdauXVs9e/ZUt27ddNJJJ6lFixZKTk6W0+lUQUGBtmzZot9++01z587VJ598ooULFwa9Y9++ferTp4/mzZunVq1ahdTTqpkzZyo7OzvouRo1aujqq6/W9ddfrzPPPFMxMTFHzK9YsULvvfeeXnnlFa1cufKwOdM0dcstt+ill14KupMdfvrpJ/Xo0UMFBQUhzbdq1UrdunXT6aefrlatWqlZs2aqU6eOEhISVFxcrD179mjt2rVatmyZZs+erU8++UTLly8Pase2bduUkZGhH374QbVq1QqpZ3kWL16sJ598MqTZ1NRUde/eXSeccII8Ho/cbrdq1aqlGjVqKDExUQ6HQ36/X/v379fWrVu1ZcsWrVmzRsuXL9eSJUs0f/58+Xy+sF0LcKxwRLsAypVUwe1H628tVnon294CAAAAQJU1zTtN2bOzZYbwYLghQ0M7DVVfT18bmllXtj+U6zBlKnt29h/OAYDqwCwsVGDNGvmXe+X3eRXw+eRf7lVg1SqZhYXRrhc2fm/kHqRwusPwILthKK5ZU7ncHrk8Hrk8bjndbrlatFBMQkLlzwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOBekDSl/nZkpBP0e3eXDukHOOJC8nxD2SZEgZo6ztAWCLV199VX6/31K2du3a6tixo6191q1bp65du2r16tUVZt1utz777DO53W5bO4Xb448/riZNmmjQoEEqLi4+YnbcuHFyOBx6+eWXZRhGhBpGz4svvmg526ZNGzVv3jys+1euXGk527Jly7DuDkXLli21aNEiS9mVK1cqLS3N5kZVU0FBga655hqZZvk/q9SoUUNZWVkaMmSIkpKSLJ8bGxur7t27q3v37po/f75uuOEGLV682PL8448/ruuuu05xcXGWZ4L18ssva8KECUHPud1uZWVl6aqrrlLCYZ5Dvk6dOqpTp45atWqlPn366KmnntJPP/2kf//735o0aZJKSkos79u9e7f69++v77//XjVr1gy6rxU7duzQwIEDg+plGIZuuukmDRs2TMcdd5zluRYtWuj+++/Xvffeq1deeUXZ2dnasWNHudlVq1bpkUcesXy2XTZv3qw+ffqooKAgqLk6deropptu0s0336zWrVsfNudwOORyuZSSkqL09HRdfvnlGj58uObOnat//etfmjp16mG/Rv9s2bJluvrqqzV9+vSguh5JVlZWhd+TD5WUlKTbbrutwusuk5iYqMTE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556a60ePHp0BAwY0MBH96fRpp+eMW87odq2kZMKYCRnbNrafU9Vf1/SudEztSJWq2/VPv+nT+cxOn+nnVLDqfvnLX+Z973tfzfUjRozIIYcckoMOOigHHnhgNtxwwz7NnTlzZn784x/n1FNPzeOPP96nPU455ZR8+ctf7lNvs/385z/PRz7ykSxZsqTmnlJKvvOd7+Soo47KuHHjcuWVV/Zq5jbbbJMrr7wyI0eO7G3cfjdt2rTsvPPOK1zfcccds88++2T33XfPW9/61rS1ta3yzGeeeSa//OUvc8455+SKK65IVXX/fr8yW2+9dW6//fYMHjx4lfPU6pxzzslHP/rRXvUMGTIkX/jCF/L5z38+w4YNq6ln+vTp+drXvpbzzz+/V9+bddddNzfccEO23377XmUEmu+ss87KUUcd1WPdRz/60Zx11lmNDwQNsCY8zxg2bFjmzZu3spJ5VVXV9gcBaWl2ALr1aJLnlp6//C/VKklJcnAp5ZX2/3dIkmXvOGUFNff3UxZgDVBK2aCUckgp5WullAtKKTeWUqaXUp4spTxXSplbSnmolPLnUsoVpZTvl1I+UkrZtpSyovcpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABepU6fdnrOuOWMFa5XqdIxtSNd07v6MVX9dU3vSsfUjlSpVlhzxi1n5PRpp/djKug/Q4YMyZFHHpnf/e53mTFjRs4555x86EMfyoYbbtjnPTfeeON85Stfyf3335+vfOUraW1t7fUeX//613PXXXf1OUOz/OIXv8iRRx6ZJUuW1NwzcODAnHfeefn85z+f4cOH5+KLL8773//+Xs299957s++++2bmzJm9jdx0G2ywQT70oQ/l5z//eWbOnJnbbrst3//+9/OhD30obW1tdZkxZMiQfOxjH8vll1+eq6++Om94wxt6vcf999+fU089tS55avHggw/m05/+dK969thjj9x55535+te/nmHDhtXc19bWlp///Oe57LLLsvHGG9fc9+yzz+aDH/xgFi9e3KucAACro5ZmB+DvVVVVJbk9SXnZ0vL/3jjJuP7KVCefqqHmzw1PAbyqlVLWKqUcXkqZnOSJJL9L8s0k706ya5JRSTZIslaSoUk2S/KGJO9IclySc5LcleQvpZSvllJG9v9dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ306fdnrOuOWMHuuqVOmY2pGu6V39kKr+uqZ3pWNqR6pUPdaeccsZOX3a6f2QCvrHjjvumO9///t59NFHc/bZZ+eQQw5Ja2trXWesu+666ezszNVXX52RI0f2qnfRokU58cQT65qn0X7961/nQx/6UBYvXlxzz2te85pcfPHF+cAHPvC3a4MGDcr555+fE044oVfz77rrruy777554oknetXXDJtttlk+97nP5eqrr87jjz+en/70p/ngBz+YjTbaqOGzx4wZk5tvvjknnXRSSim96j3llFPyzDPPNCjZS51wwgmZP39+zfX/8A//kCuvvDKbbrppn2fus88+ufnmm7PtttvW3HPLLbfktNNO6/NMAIDVRUuzA7BC1/SwXpK090eQeiiljEnyjiRVXsy+IlP7JxHwalRK+ViSh5P8b5L9s/L3m55snmRCkodKKf+vlLLeqicEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGB1dPq003PGLWfUXF+lSsfUjnRN72pgqvrrmt6VjqkdqVLV3HPGLWfk9GmnNzAVNN7ee++diy++OLfddluOO+64DBs2rOEzd9999/zhD3/I1ltv3au+X//615k2bVpjQtVZV1dX/uEf/iEvvPBCzT2ve93rcvXVV2fvvff+u7VSSv7zP/8z3/72t1NKqXnPO+64I/vtt1+efPLJmnv62xve8IY89NBDOfXUU7PXXnulpaWl3zO0tramo6MjZ511Vq++v3PmzMnPf/7zBiZ70e9///tMmjSp5vpx48bl3HPPzVprrbXKszfZZJNcfvnl2WqrrWru+drXvpbHH398lWcDADRT//9VSq2uWcH1kvztqc7OpZRP9FOePiultCQ5dQXLyz+heqyqqgcanwh4tSmlbFZKuSjJT5JsXOftW5N8PMntpZR313lvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACa7K5Zd+W/bvmvXvdVqdIxtSNd07sakKr+uqZ3pWNqR6pUve79r1v+K3fNuqsBqaCxDj744Fx33XWZMmVKDjzwwH6fv/nmm+fSSy/NiBEjetX33//93w1KVD+//e1v8/73vz/PP/98zT077LBDrrvuurzhDW9Yad0XvvCF/PSnP83AgQNr3vvWW2/NAQcckFmzZtXc058GDBjQ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SUpKJoyZ0JTcsCZ429veVnPtX/7ylyxZsiQtLS0NTNSz66+/PoccckieeeaZmuqHDh2aX/3qVznggAPqnmXw4MH51a9+leOPPz6nn356TT1XXnll3v3ud+fCCy/M2muvXfdMr3SjRo2quXbevHl1nz9lypTMmDGjptq3vvWtGT16dN0zrMg//MM/5IQTTsjzzz/fY+0FF1yQZ555JkOGDOmHZK8uTz/9dCZPnpxbbrklt99+e+69997Mnj07c+fOzYIFCzJ48OCss8462XjjjbPVVltl9OjR2XPPPbPXXntlo402anb8ulmyZEkeffTRPPDAA3niiSfy7LPPZv78+Vm8eHHWXXfdrLPOOllvvfWy1VZbZYsttshaa63V7Mh19dRTT2Xy5Mm54YYbcuedd+bee+/NnDlzMm/evCxevDhDhw7N0KFDs8EGG2S77bbLjjvumJ133jl77733GvvePnv27Nx///159NFH88wzz2T+/PlZsGBBBg4cmHXXXTdDhgzJ5ptvnq233jqvec1rmh23LhYvXpyHHnooM2bMyBNPPJHZs2dn0aJFWbRoUVpbW7POOuu85FhvvfWyxRZbZL311mt2dFittTY7ACtXVdXiUsonk1yXpCSpln59uWVry9bXS/L/JflaKeUXSf43yaVVVfX8122NSimbJBmX5CNJ3rJcjqwk5/JrVZIrq6r6cb0yAWuM9/aw/q2qqm5blQFVVT1XSjkqyV1JBq6gbNtSyutXdRYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKufsW1jkyQdUztSpepVb5UqHVM7XrJPf+ia3tWnvElSUjJhzIR+zQtrmm222SallFRVzz+jixcvzrPPPpuhQ4f2Q7Lu3XjjjTnooIMyd+7cmupf+9rX5ne/+1123nnnhmVqaWnJaaedlte97nU58cQTa+q5/PLLM3bs2FxwwQUZPHhww7K9Eq233no11w4YMKDu83/3u9/VXPvBD36w7vNXZv3118/BBx+c3/zmNz3WLliwIFOmTMm73/3ufkjW/6644orss88+Pda94x3vyBVXXNFj3cKFC3POOefk/PPPz9VXX50XXnhhhbXPPvtsnn322TzxxBO57bbbkiTf+c530tLSkr322itHHHFEjjzyyKy99to138/qYM6cObn44otzzTXX5Jprrsntt9+e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6jgLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBXiLFtY5MkHVM7UqXqVW+VKh1TO16yTy26pnf1aV6SlJRMGDOhV/OA+pkzZ04uueSSmuv33nvvxoVZ6sEHH8w+++yThx9+uMfajTbaKBdeeGHe/OY3NzzXqhowYEB+9KMf5XWve12++c1v9lh/9tlnp7W1NT/60Y9SSumHhM138cUX56c//WlNtW9729uy22671XX+/fffX3NtW1tbXWf31ogRIzJ8+PDMnj27x9qHH344L7zwQlpbWxsfbDV15pln5mc/+9lKa0aOHJmPfOQjef/735+dd945LS0tK61/7rnnctFFF+W0007L5MmTe5Wnq6srl112Wfbbb79e9fXW4sWLc9hhh+Xmm2/uU//GG2+cgw8+OPvss0922GGHbLnllhk6dGgGDBiQefPm5bHHHsudd96ZqVOn5ne/+13uvvvuXs944okncsghh+Smm27Khhtu2KectTr33HPzox/9qNd966+/fj7+8Y/nwx/+cN70pjf1WH/77bfnvPPOy5lnnpmZM2eusG7hwoU56qij8slPfrLXmRrhkksuyeGHH57nn3++T/077bRT3vGOd2S33XZLW1tbNt988wwbNixrr712nn/++cybNy8PPvhg7rrrrlxzzTW58MIL8+ijj/Zqxv3335/DDz88l19+edZaa60+5ezO73//+5x99tl96t12222z3377ZbvttsuoUaOy9dZbZ+jQoVl33XWz7rrrppSSRYsWZf78+XnyySfzxBNP5IEHHsi9996bO+64IzfccEMeeeSRut0LvFqUqur9AwZWT6WU9ZN8Pslnkqy39HJ3/8H1+NSzsn2vS3JyVVW/q8McoM5KKYOSjE6yWZKhS4/BSZ5JMi/J3CT3JflLVVVLmpVzZUop309y3AqWZyXZtKqqBXWa9aMkn1jB8twkr63XrDVFKWVuXnzddWvo0KGZO3duPyYCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgJdavHhx7rnnnprrR48enQEDBjQwEauzruld6ZjakSpVr3tLSiaMmZCxbWNXmzlAY3z729/Ol770pZpqhw8fnsceeyyDBg1qWJ5HHnkk73jHO3L//ff3WDtq1KhcfPHFGTVqVMPyNMqZZ56ZY445JosXL+6x9lOf+lTOOOOMlFL6IVnz3HbbbXn729+ep59+usfatdZaK9dff3123nnnumb4f//v/+UTn/hETbVf+tKX8q//+q91nd9bb37zm3PjjTfWVHvfffdl6623bnCi/nXFFVdkn3326bFuiy22yOOPP54FCxZ0u77BBhtkwoQJ+fjHP97n97dLLrkkn/jEJ/Lwww/X3POWt7wl119/fZ/m1erLX/5y/u3f/q3XfTvvvHO+8pWvZPz48Wltba2575prrsm3v/3tXHDBBb2eue++++aSSy5p2OeX+++/PzvttFPmzZtXc89aa62Vz3/+8/nqV7+aoUOH9nrmwoUL82//9m855ZRTVvj6S5I3velNueWWW3rc76Mf/WjOOuusXueoxd13353dd989s2fP7lXfJptskk996lM56qijstlmm/Wqt6qqXHbZZfn//r//L5dffnmveo899tj84Ac/6FXPynLstNNO+fOf/1xzz4YbbpjPfe5z+fCHP5wttthilTPMmDEjl112WS699NJceOGFeeqpp/6uZsqUKdl7771XeVazrAnPM4YNG9bTe8y8qqqG9VeeV7pSVb1/yMDqrZQyMMm4JEcmOSDJWsst1/M/fPlPTo8m+XmSs6uquqOOM6BPSikbJ9ktyRuT1Prp44qqqq5oWKgmKaWsn+TAJIcm2T3J1klq+e2/MMldSa5M8rskV1ZVtahROXujlLJtkjvz0veh5X2pqqpv12HO1nnxe7DWCkr+s6qqf1rVOWuaUsrcJCv85Dd06NDMnTu3HxMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwEstXrw499xzT831o0ePzoABAxqYiNVd1/SudEztSJWq170lJRPGTMjYtrFN2x9orOeeey6jRo3KI488UlP90UcfnR/+8IcNTsWa6LLLLsv73//+zJo1q6b6b33rWznxxBPrnuOrX/1qTj755Jpqf/CDH+TYY4+te4beOOyww/LrX/+6ptpLL700++23X4MT9a8rrrgi++yzzyrtMXbs2Jx55pkZMWLEKueZOXNmDj300Nx8880190ydOjV77rnnKs/uzuTJk3PggQf2qmedddbJf/zHf+Too49OS0tLn2dfeumlOeqoo2r+/bLMSSedlI6Ojj7PXZkDDzwwkydPrrl+8803zy9+8Yu89a1vXeXZt912Ww4//PDcfffdq7TPRz/60Zx11lmrnOfl5s2bl1133TX33ntvzT1DhgzJ17/+9Rx33HEZPHjwKmfo6urKZz7zmfz1r3+tuefyyy9f5feA5MXfQfvvv3/N9V/60pfyjW98I2uvvfYqz+7OCy+8kClTpuSss87Kr371qyxatChJMmXKlOy9994Nmdkf1oTnGcOGDcu8efNWVjKvqqph/ZXnla612QGov6qqnkvyiyS/KKWsm2TvJAck2TPJjknq8c761yR/SnJ5kslVVd1Whz2hT0opGyXZNcluy319XR+3u6JOsZqulLJvks8meVeSvvy2H5xkp6XH55I8U0o5O8n3q6patb+4V1FVVXeXUn6e5EMrKPlqKeWiVXlvKqUMTPLjJGutoOSZJP/Z1/0BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHj1GNs2NknSMbUjVape9Vap0jG14yX7LK9relef9k2SkpIJYyZ0uy/Qf0499dQ88sgjNdcfddRRDUzDmujxxx/PF77whZx77rk19xx88MH5l3/5l4bkeeCBB2qufe1rX9uQDL3Rmwy9ubc1xVe+8pWcfPLJKaXUZb+NN944F198cXbffffcd999NfX893//d/bcc8+6zF/eggUL8ulPf7pXPVtvvXUuvPDCbL/99qs8f//998+0adPyvve9L1OmTKm57+STT84HPvCBjB49epUzLO+CCy7I5MmTa67fbrvtctlll2WTTTapy/zXv/71ue6663LggQfmxhtvrMue9fTFL34x9957b831e+65Z372s59lyy23rFuGsWPHZvfdd89hhx2WqVOn1tTzyU9+MrfeemsGDx68SrPPPvvsmupaWlryP//zPzn88MNXaV5PWltbc8ABB+SAAw7I9773vfzwhz/Mqaee2tCZsDpqbXYAGquqqmeT/HbpkVJKS5JtkmyX5HVJNkny2iRDkwxeegxI8lyShUkWJJmV5K9JHk3yYJJbq6qa1a83AkuVUkYk2S3Jrst93aypoVYzpZS9k5ya5E113npIkmOTfKaU0pXkn6qqauYn4M8m2S8vvoe93LAkvy2lHFxV1Z293biUsm6Sc5K8YyVlX6iq6uHe7g0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwKvT2LaxSZKOqR2pUvWqt0qVjqkdL9knSbqmd/VpvyQpKZkwZsJL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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAV5n58+fnve99b+bOnVtzT3t7e9ra2hqYCl5qvfXWy6c//encc889Ofvss7PVVlv1y9wXXnghzz77bE21a621VgYPHtzgRD0bNmxYzbWzZ89uXJBXiJ122imHHXZYv82rddYtt9ySqqrqMrOrqytPP/10TbXDhw/PySefXJe5tfjHf/zH7LrrrjXXn3XWWas88+c//3nNtSeddFJaW1tXeWatOjs7+21Wd37729/mgQceqKn25JNPzmabbdbgRH/v+OOPr2nutGnTcvPNN/dpxrx582qq23TTTfu0P9B3Lc0OAEDflFLGJTknq897+YZJLiuljGpWgKqqJldVtXeSLZPU/imle9OTHJVkk6qqjquq6pFV3A8AAAAAAAAAAAAAAAAAAAD+f/bsO8yusl4b8PNOKoGE3kFapKgQwIIQEBugCM7hQz1i4YBHaSK2Yz+j4ogo2BsqIiJ2UBnFgihYiIAgggKHEkCaQTokJKS+3x8mGjFl7Zm9Zyfkvq9rXbNnred9f8+azOzZswMAAAAAAAAAAAAAAAAAAAAAAKwCjjzyyPz5z39unH/GM56Rd7/73R1sBP/00pe+ND//+c9z99135/Of/3y22mqrYZ0/e/bsxtnVV1+9g02aa6VHK/f3ePXmN785pZRhm7fPPvs0ys2YMSN33HFHW2aeccYZjbNvf/vbs/baa7dlbhOllJx44omN89/61rcyd+7cQc+rteY73/lOo+zEiRNz8MEHD3rWYOy5557Zc889h3Xm4r70pS81ym255ZY5+uijO9xmycaMGZM3velNjbI/+MEPBjVjzpw5jXIjR44c1P7A4PV0uwAArSul7JDk60kG8+rpuiQfSHJAkq2SrJlkVJL1kjw5ySuTfCHJfYPYe6MkPyilrDaItUNWStmmlPKZJBcnecUQt5uYpD9Jfyll56F2AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4PHvwx/+cL7+9a83zo8bNy5nnnlmRo4c2cFW8E/f+9738t73vjcnnnhirrzyymGfP3fu3MbZFeXnopUec+bM6WCTFd/48ePzkpe8ZFhnbrnlltlggw0aZa+//vohz5sxY0bOP//8RtnVVlstRx555JBntmqfffbJU57ylEbZe++9N7/+9a8HPeuqq67KHXfc0Sh75JFHppQy6FmDdfTRRw/7zCT561//mp/97GeNsv/zP//T1ee8//qv/8qoUaOWm2t6P481duzYRrnbb799UPsDg9fT7QIAtKaUMi7JWUlWb3HplCR71Vp3qLW+r9b641rrX2qtD9da59Va76u1Xltr/Wat9egkGyc5PEmrr9B2TPK5FtcMSSll41LK15Ncn+TY/L17O2yW5Jgkfyyl/KSUsmub9gUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBx5uyzz8673/3ultZ89rOfzbbbbtuhRvDvFixYkEsuuSTvfe97s8suu2SvvfbKueeem1rrsMyfM2dO4+zIkSM72KS5UaNGNc62cn+PR8973vMybty4YZ/7pCc9qVHur3/965Bn/epXv8rcuXMbZV/2spdlnXXWGfLMwTj66KMbZ88///xBz7nwwgsb5UopecUrXjHoOUNx0EEHdeX78txzz82CBQuWmxs7dmxe+cpXDkOjpVt33XUzefLk5eauuOKK3HfffS3vv9566zXK/eQnP2l5b2BoerpdAKBDbk5yVpKBbhfpgJOTPLmF/Jwkr6+17llrvajpolrr3FrrV5Nsl+SrLTVMDi+lvKTFNYNSSvmPJH9O8sokIzo46oVJLimlvLuU4vcnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/3DppZfm0EMPTa218ZrXve51OfzwwzvYCpbvoosuyoEHHpgdd9wxv/71rzs+b86cOY2zI0eO7GCT5lrp0cr9PR7tu+++XZn7xCc+sVHu7rvvHvKs888/v3H2pS996ZDnDdZLXvKS9PT0NMq2ck+PdeGFFzbKPe1pT8smm2wy6DlDsdpqq2W//fYb9rk/+clPGuVe8IIXZK211upsmQb22Wef5WYWLFiQyy+/vOW9t9pqq0a5M888M3fddVfL+wOD1+w3BcCK7eYkZyV5Z5LnJ1mn1rpNrfVlSc7pZrF2K6XsmuSoFpZMT/KcWuvnBzuz1jqr1np4kre2uPTjpZTVBzu3iVLKG5L8IMm6y4n+Jcmnk7w0yXZJ1ksyIsnqSZ6QZPck/5Pkx0nmL2OfUUlOSPL9UsqooXQHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg8eH666/PAQcckFmzZjVe89SnPjWf+cxnOtgKWnPNNdfkuc99bt72trdl9uzZHZuzYMGCxtkRI0Z0rEcrWunRyv09Hj31qU/tytwNNtigUe7ee+8d8qzf/e53jXKrr756nv/85w953mBtsMEGmTx5cqPsVVddlUceeWRQcy6//PJGuW5+LZJk3333HdZ58+bNyy9/+ctG2Re84AUdbtNM05/fK6+8suW9J02alFLKcnMPPvhgDj300Dz66KMtzwAGZ2S3CwC06OYkf1j8qLU+0N1Kw6P8/dXU55L0NFzyaJL9a63N/oJZjlrrx0spo5Oc2HDJ5kn+N8m72jH/sUopRyf59HJiU5O8N8l3a63zl3B95sLj9iSXJPlYKWXrJO9I8rokS3sF25vku6WUlyxlXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFYBt912W/bZZ5/ce++9jdc84QlPyMDAQMaMGdPBZqzMXv3qV+dpT3vacnNz5szJ7Nmz88ADD+Suu+7KLbfckmuvvTYPP/zwoOYuWLAgH/3oR/Pzn/885513XjbaaKNB7bMsI0eObJydN29e2+cPxty5cxtnR40a1cEmK76nPOUpXZm73nrrNcrNmjVrSHPmz5+fa665plH2mc98Ztef55/97Gfnt7/97XJzCxYsyNVXX53ddtutpf3vu+++TJs2rVF2jz32aGnvdtt9992Hdd61116bGTNmNMo+61nP6nCbZp70pCc1yv3pT39qee+11147O+20U6666qrlZs8///zss88++eY3v5nNN9+85VlAa5q/MgMYfjcn+cPiR631ge5W6qqDkjyzhfwba60XtbNArfXDpZSnJTm44ZI3l1I+VWu9q509Sim7JPnUcmLfSfK6Wuv0Vvautd6c5MhSyg+TfC3JOkuJ/keSdyX5YCv7AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8Phw11135XnPe15uv/32xms22GCDnH/++dl000072IyV3X777Zf99ttv0Ouvv/76/OpXv8r3v//9XHDBBZk3b15L6//0pz/lOc95Ti688MJstNFGg+6xJKNHj26cnTt3bltnD1YrX79Ro0Z1sMmKbd111824ceO6Mnvs2LGNcrNnzx7SnBtvvDGzZs1qlJ08efKQZrVDKx2uuuqq7Lbbbi3tf8011zTOPu1pT2tp73Z7ylOekjFj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sbcDrdqvd2Jv+if3p6S0vPaoSUdl+3W270AraL8TTjghtdaW1vz2t7/NGmuskVLKCnUcdthhnfki0VX33XdfPve5z+WZz3xmNtlkk7zmNa/Jt7/97dx2221tmzF37tz88pe/zBve8IZsuummOeqoo3LnnXe2vM/IkSNzxhlnZNy4cW3rtizHHHNMdt9998b5e++9N8997nPz/ve/P7NmzWp53u23357/9//+X97ylrdkwYIFjde99a1vzaRJk1qex+PTRz/60Wy++eaN87XWnHjiidltt91y0UUXDXruTTfdlP/4j//Ia17zmpa+/0ePHp2vfOUrGTly5KBnL8vrXve6vPjFL25pzS9+8Ytsv/32ecc73pHbb7+9pbV/+9vfcvzxx2fbbbfNOeecs9Tc6quvnre97W0t7d1uL3zhC/POd76zpTV/+ctf8qIXvSh77bVXfvjDH2b+/Plt7zV//vxMmTIl73nPe7Ltttvm6U9/ej71qU/lwQcfbPusRebOnZuzzjorBxxwQDbZZJMcc8wx+clPfjKo5/JlWbBgQb75zW9ml112yXe+853G6/bbb7/stNNObe0CK6rO/DagHS5cyvmSZNFfvGsmeXOS/mFpNEillHFJ3p5/9v63yMJrf6i1zh62YrBim9NCdlTHWrSmld8pczvWAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWnTMzsckSU656pRG+ZKS/sn96Z3Y28labbeob9+UvtTURmuOnnT0P74+ALTXXXfdldNPPz2nn356kmTjjTfOLrvsku233z7bbbddNt9882y44YbZYIMNssYaa2Ts2LEZPXp05s+fnzlz5uSRRx7J3Xffnb/97W+56aabcsMNN+Tyyy/PZZddlpkzZw653ymnnJLdd999yPs0NWLEiHz729/OLrvskvvvv7/Rmvnz5+f444/Pl7/85bzpTW/KK17ximyyySbLXHPFFVfkq1/9ak499dQ8+uijLXWcPHlyTjjhhJbW8Pi2zjrr5Oyzz86znvWszJ49u/G6P/zhD9lrr72y995758gjj8wLX/jCrLXWWstcM3v27Pz617/Oaaedlh/84AeZO3duy30/85nP5GlPe1rL61px2mmnZZdddskdd9zReM2sWbNy0kkn5WMf+1j23nvv7LvvvnnqU5+abbfdNuuss07GjRuXWbNm5YEHHsiNN96YP/7xj/n5z3+eCy64oNHX4UMf+lAmTJgwlNtqixNOOCF33nlnvva1r7W07qKLLspFF12UjTfeOAcddFD233//7LHHHll77bVb7nD33Xfn6quvziWXXJJLLrkkv/3tb/Pggw+2vE+73HPPPTnllFNyyimnZLXVVssee+yRPffcM5MnT85OO+2UDTfcsKX95s+fn0svvTQ/+tGPcvbZZ2fq1KktrR81alQ+8YlPtLQGVmYju12AJau13lpK+WOSXZLUJOWxkYXn3lVK+Uat9ebh7tiC45NsliXfx+K+Pzx1YKUwp4XsivJcPqqFbCv3R3vMTjK92yUWGt/tAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj3XMzsckSU656pRl5kpK+if3p3di73DUartFvfum9KWmLjN79KSj//F1AaDzpk2blmnTpuUnP/lJt6vk+OOPz2tf+9phn/uEJzwhZ555Zg488MAsWLCg8bo777wzb3vb2/KOd7wjO+ywQ572tKdl0003zVprrZW5c+fmwQcfzI033pjLL788d9xxx6C6rb/++vn2t7+dkSNHDmo9j1/PeMYzcsopp+Q1r3lNy2t//etf59e//nVGjBiRSZMm5UlPelK22GKLjB8/PiNGjMiMGTMybdq0XHfddbn88sszc+bMQfc86qijcsQRRwx6fVPrrbdezj333Oy1116ZPn16S2vnz5+fCy64IBdccEHb+uy///459thj87Wvfa1tew5WKSWnnXZaHnrooQwMDLS8ftq0afn85z+fz3/+80mSLbfcMtttt10222yzbLTRRhk3blzGjh2b+fPnZ/bs2Zk1a1buu+++3HXXXZk2bVpuuOGGPPjgg22+q/aZNWtWfvnLX+aXv/zlP86ts8462W677bLJJptkk002ydprr52xY8dmzJgxmT17dmbMmJFHHnkkd9xxR66//vrceOONmT179qA7nHjiidlhhx3acTuwUvCqZsX2gyS7LOF8Sf7xjs7YJN8opexda50zbM0aKqU8P8mbkuW8A/V3Z3W2DaxU5raQHd2xFq1ppccK93z1eFdrPTHJid3ukSSllIeTjO92DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxzpm52OSJKdcdcoSr5eU9E/uT+/E3uGs1XaL+vdN6UtNXWLm6ElH/+PrAcCqo5SSj370o3nLW97StQ77779/vvjFL+aII45IrUv+PbU0CxYsyDXXXJNrrrmmrZ3WWmutnHfeedlss83aui+PH4cffnimT5+eN77xjYNaP3/+/FxxxRW54oor2tzs7w499NB87nOf68jeSzJp0qScffbZOfDAAzNnzpxhm7ukHt/5znfS09PTtQ6PNXLkyJx99tk56qijctpppw1pr7/85S/5y1/+0p5iK6j7778/F1988bDMesUrXpG3vvWtwzILVhQrzrMjS/K1JPMXPn7sq+Ky2LlnJDl1uEo1VUrZNsm388/vs/KYSM0/7+O3tdbbhrEerOgeaSE7vmMtWtNKj5kdawEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENwzM7H5OhJR//b+ZKS/sn96Z3Y24VW7dc7sTf9k/tTUv7t2tGTjs4xOx/ThVYAdNOECRPy3e9+N295y1u6XSWvfe1r85nPfKbbNZIk48ePz89+9rPssssu3a7CCu64447Lpz71qfT09HS7yr84/PDDc/rppw97r3333Tfnnntu1lhjjWGdu8jEiRO7On9ZRo4cmS9/+cv5wAc+sMJ9v6yqDj744JxxxhndrgHDzjPQCqzWeluSc5IlvHPzdyVJXfjxVaWULw9TteUqpWyX5MIk6yw6tZwlH+tsI1jp3N9CdkLHWrSmlR6t3B8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyrY3Y+JkdPOvofn5eU9E/uT+/E3i62ar/eib3pn9yfkvKPc0dPOjrH7HxMF1sB0A2TJ0/OVVddlZe85CXdrvIPr3/96/Otb30r48aN61qHrbbaKhdddFF22223rnVg5XLcccfl3HPPzZprrtntKhkxYkQ+9rGP5Stf+Up6enq60mGfffbJL3/5y2y66abDOne33XbL7373u2y22WbDOrdVfX19+dWvfpUtttii21VWaW9729vy3e9+NyNHjux2FRh23fntQCs+tpzrJUld+PHwUsqPSildfRVSStkvyZQkGy/stiSLn7++1vqjjheDlcv9LWTHd6xFa1rpcV/HWgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBscs/MxOXrS0Skp6Z/cn96Jvd2u1BG9E3vTP7k/JSVHTzo6x+x8TLcrATCMNtlkk3zlK1/Jb37zm2y55ZbdrvNvXv7yl+d3v/tdtt5662Gfve++++byyy/PTjvtNOyzWbm98IUvzB/+8IfsvffeXevwxCc+MRdccEHe8pa3dK3DIs94xjNy5ZVX5oADDuj4rFJKjjzyyFxwwQVZf/31Oz6vHfbaa69cddVVOe644zJq1Khu11miJz7xiTniiCO6XaPtNtlkk/zwhz/MSSedlJ6enm7Xga7wnb+Cq7VekuScJCVJXUps0bWSZP8kV5RSnj8sBRcvUcq4UsrJSc5Nsk7+2bcsbcnCzLuGoR6sbO5rIbtOx1q0Zu0Wsvd3rAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALTJMTsfk+8e+N30TuztdpWO6p3Ym+8e+N0cs/Mx3a4C8Lhywgkn5LOf/Wz23XffjB49utt1/sUWW2yRk08+OTfccEMOP/zw9PT0dLvSUk2aNCl//vOf8573vCdjxozp+LyNNtooX/va13LeeedlnXXW6fg8Hp+22WabXHjhhTn11FOz4YYbDtvc1VZbLe95z3vypz/9Kc961rOGbe7yrLfeevnRj36Ub33rW9lyyy07MmO77bbLBRdckC984QsZN25cR2Z0ypprrplPfepTueaaa/KSl7xkhXhOXnvttfOa17wmF154YW644YYcccQRg97rm9/8Zo488shsvvnmbWw4eKuttlre9ra35dprr82BBx7Y7TrQVd1/tqGJtySZvfBxXUqmLLxWkmyV5LxSyndLKU/pdLlSyshSymuSXLuw64jFepYlLFnUsyb5Wa11oNMdYSV0XwvZjTrWoqFSypgkazeMz6i1zulkHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaJft19m+2xWGxapynwDDadNNN83rX//6nHfeebn33ntz1lln5dBDD82mm27alT6rrbZaDjrooHzve9/LTTfdlP/5n//J6quv3pUurRo3blw++MEP5uqrr85rX/varLbaam2fsdFGG+X9739/rr/++rz61a9u+/6sekopee1rX5tbbrkln/70p7PFFlt0bNaaa66Zd77znbn11lvzwQ9+MGPHju3YrKF4+ctfnuuuuy6nnHJKdtxxx7bs+YxnPCNnnXVWrr322jz72c9uy57d8sQnPjFnnXVWbrrpprztbW/LeuutN6zzN9988xxxxBE599xzc9ddd+W0005ry9d0//33zxe+8IXcdtttufLKK3PCCSdk8uTJGTVq1NBLt2DjjTfO//7v/+amm27KSSedlDXXXHNY58OKqNRau92BBkop707ywSQ1SVlGdNE/aFn4uCb5eZLTk/yw1jq7jZ22SfKqJK9JstlivRbvsKx+DyfZpdZ6S7s6wWOVUg7L37//mzi+1vr+zrVprpSyUZJpDeO31Fq37mSf5SmlbJmk6c/ydbXWHTpYhxVcKeXhJOOXdn38+PF5+OGHh7ERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPyr+fPn54Ybbmic33bbbTNixIgONgIAHm9uvfXWXHzxxbn44ovzu9/9LldddVXmzp3b1hk9PT15ylOekr322ivPec5z8oIXvCCrr756W2d0y3333ZevfOUrOeecc3LppZdm/vz5g9pn9dVXz3Oe85z853/+Z172spdl9OjRbW4K/7RgwYL85je/yTe/+c386Ec/yl133TWk/SZMmJDnP//5OeSQQ3LAAQdk7NixbWo6fC699NKce+65Oe+883LllVc2eh5cb731svPOO2f//ffPgQcemIkTJw5D0+6YN29efvOb32RgYCA//elPc+ONN7Zt71JKttpqqzzzmc/MXnvtlWc961l50pOe1Lb9m3j00Udz+eWX55JLLvnHceedd7Z1xsSJE7Pffvult7c3z3nOczJy5Mi27r+iWRXez5gwYUKmT5++rMj0WuuE4eqzsiu11m53oIFSSklyfpLnJqlJyjLii/5Ry2M+n5nkt0l+meQPSf5ca72v4fyeJNsm2THJnkmen2T7pcxZ/NySupWFH19eaz2ryXwYrFLKYUlObxg/vtb6/s61aU0pZWaS1RpEZ9Vax3W6z7KUUp6Z5OKG8Z/WWvfvZB9WbKWUh5OMX9r18ePH5+GHHx7GRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwr+bPn58bbrihcX7bbbfNiBEjOtgIAHi8mzNnTm6++ebcdNNNmTp1am666abcdNNNueeeezJjxox/ORYsWJAxY8ZkzJgxGTt2bNZdd91suOGG2WCDDfKEJzwh22+/fbbffvs86UlPyoQJE7p9ax33wAMP5IILLsif//znXHvttbnhhhty//33Z/r06ZkxY0ZGjBiR8ePHZ4011siGG26YHXbYITvssEN23XXX7LXXXhkzZky3b4FV1E033ZQpU6bkT3/6U26++ebccsstufvuuzNz5sw88sgjWbBgQcaNG5dx48Zl7bXXzlZbbZWtt946O+ywQ/bYY49MmjQpPT093b6Ntpk3b16mTp2aqVOn5sEHH8yMGTMyf/78jB8/PuPHj8+6666b7bffPhtssEG3q3bNAw88kMsuuyxXXHFFbrnlltx66625/fbb8+CDD2bmzJmZNWtW5syZk1GjRmXMmDFZffXVs84662S99dbLJpts8o/voe233z477bTTCvk74u677/6X34M33XRTbr311jz00EP/+D04ffr0PProo/9yn+uvv3423HDDPOEJT8h2222XHXbYIbvtttsq9/2yKryfMWHChEyfPn1Zkem11hXvm3sFVWqt3e5AQ6WUDZJckWTjRaeWs2TRP25ZwrlFHk4yLcldSR5J8miS+UnGJBmbZO2F8zZKMnLxOkvZc1md6sLrNcmna61vXk5/GLJSymFJTm8YP77W+v7OtWlNKeXaJDs0jG9Sa53WyT7LUkp5ZZKvN4x/vtb6+k72YcVWSnk4yfilXR8/fnwefvjhYWwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9q/vz5ueGGGxrnt91224wYMaKDjQAAAACWbVV4P2PChAmZPn36siLTa60ThqvPym5ktwvQXK317lLKPkl+k2SdJDVJWcaSsjBTH3NucWsuPLZbxh5LrdQwt3i2JvlWrfXNy8kDyS1JdmiYnZhkWge7NJnf1M0dawEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsV0+3C9CaWuv/Jdk/ycOLTi1nSVnsWJRf0lGWcjRds8zai3X5QZJDl5MH/u76FrJP7FiL9s+/oWMtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgOXq6XYBWldrvSzJnkluT1KS1IXH8pQlHP/YdhnH0tY3qrvY2s8leVmtdUHDtbCq+2ML2Z061qKZSS1kr+hYCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGC5erpdgMGptV6TZLcklyQpi04PYqvSwtFSxYVHSTI3yRtqrW+otS4YREdYVV3RQvapHWuxHKWUcUl2aBi/u9Z6Zyf7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMvW0+0CDF6t9W9J9kzy3iTzkpQkdeHRtVqLzS9Jrkry9Frr57pXCVZa1yWZ2TC7SymlW8/pOycZ0TB7RQd7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA30dLsAQ1NrXVBr/WCSpyf5ZZKy8KiLHcNSZbFZJclDSd6Z5Om11j8PUwd4XKm1zk9yWcP46kme2sE6y7J3C9lLOtYCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaKSn2wVoj1rrn2qt+yTZL8klScrCI0nqY462jHzMsWje9CQnJdm61npSrXVem+bBqur8FrL7dKxF++a2cj8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAB/R0uwDtVWs9v9a6R5JdknwpycNJymJHktQ2HHnMvr9P8rokm9Ra31lrfbCT9wmrkPNbyO7bsRZLUUpZPckeDeMP5e/PFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAXjex2ATqj1npVkqNKKccm2SvJAUmek+QpWfa/e13scVlG7p4klyT5SZJza613Dq0xsBSXJ3kgydoNsnuVUjautU7rcKfF/UeSMQ2zF9Za53WwCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDAyG4XoLNqrfOSXLjwSCllTJKdkuyY5AlJNk+yaZIJSVZbeIxM8miSWUlmJrknye0LjxuT/LHWesew3gisomqtC0opA0kOaxDvSfKfST7ZyU6P8YoWst/vWAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgsZHdLsDwqrXOTnLZwgNYOZyZ5LCG2dcm+WTHmiymlPKEJPs2jM9M8oMO1gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa6ul2AQCW61dJ7miYfXIp5YUd7LK4NyUZ2TD7g1rrjA52AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABrq6XYBAJat1rogyVdbWPK/HaryD6WUDZO8toUlp3eqCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCanm4XAKCRzyZ5tGF2j1LKIZ0sk+TEJOMbZv9Qa/1lJ8sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzfV0uwAAy1dr/VuSr7aw5GOllPU70aWU8twkh7Ww5COd6AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzshuFwCgsZOSvCbJ6AbZjZOcWUrZv9a6oF0FSikbJvlGktJwyf8l+V675tNdpZTXJzmmDVut3oY9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGKSR3S4AQDO11ltKKR9L8q6GS/ZL8sVSyhG11jrU+aWUtZOcl2SjFpYdV2tdMNTZrDDWT/KkbpcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgaHq6XQCAlnwwye0t5F+b5KullLFDGVpK2TLJBUkmtbDs7FrrL4YyFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGi/nm4XAFiSUsqzSyl1qEeS01sY+752zCylHNahL0tqrTOTHJ2ktrDs0CSXlFKe3uq88nevSnJFkp1bWHp/kje3Og8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADovJ5uFwCgNbXWHyf5WIvLJiW5tJRyVilln1LKMp//SynjSymHJflDkjOTrN1KxSSvrrXe0WJHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBiM7HYBAAblXUmemWTPFtaUJC9ZeDxQSrk8ydVJHkgyK8mEJBsk2SXJpCRjBtntw7XWnwxyLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBhI7tdgO4qpYxOstrCY1SSsvj1Wutt3egFLFutdV4ppTfJhUl2GsQWayfZZ+HRTl9N8p4278mK454k17Zhn+2T9LRhHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZhZLcL0HmllLWTPC3Jzkl2SrJFkk2TbJJk9DKW1vgegRVWrfX+Usrzk/wqyZO6XCdJvp3kv2uttdtF6Ixa6+eSfG6o+5RSHk4yfuiNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGIyR3S5AZ5RSdk5yUJIXJNk1Sc9jI8PdCWi/Wus9pZS9knwnyfO7WOXkJO+qtS7oYgcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACggZHdLkD7lFLGJjk8yWuT7Lzo9FLidXnbtaHP55M8bTmxL9ZaTxvqLFiV1VrvL6W8IMmJSf4nbfj5bcGMJK+ttX5nGGcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQzCy2wUYulLK6CTHJHl7kg2TlMdE6rKWL+HcsvKtOC/JUQv3W9KcJJmQ5LQ2zYNVVq11fpK3l1K+n+RzSXYdhrFnJXlzrfXOYZgFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtElPtwswNKWUvZP8OcnHkmyUpCy8VBc7svD8ko6OqbUOJLl64Zz62MsLPz6xlPKsTvaAVUmt9ZIkT0/ymvz9uaHtI5L8LMlzaq0vq7Xe2YEZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAeN7HYBBqeUMiLJJ5K8ftGpJHXxyLCXWrJPJ/nSwsd1KZlXJfnN8NRhZVFr/VVWnO/jlUqtdUGS05OcXkp5bpJDk7wgyYZD2Pa6JD9Ocmqt9fqhtwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6ZWS3C9C6Usr6Sc5OsmeSkqQuPLLw8xXJN5KclGTNhZ8v6reoc0ny/0opx9Ra53WhHzyu1VovSHJBKaUk2TXJ7kl2SPKkJJslGb/wGJvkkSTTkzyU5OYk/5fkmiS/qrX+ZdjLAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0xstsFaE0pZbMkFybZOklJUhddamGbutjjVta1rNY6q5TytSTHLWHuos/XTrJPkp92sgusymqtNckfFh4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAKqyn2wVorpSyWZILk2yTpCSpCz+WZSyrSziG25kNMi/ueAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID3dLkAzpZTVkvwoyTZJ6sKjLGPJokwW5hY/apIHk0xbLNsxtdY/JLlxKbMW3ccLO9kBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPi7nm4XoLEvJ5mUpC78vCwlVx+TmZfkV0nek+QFSZ6QZEytdd1a62Yda/vvzsq/d178881LKdsPYx8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWCWN7HYBlq+U8p9JDklSF51aSnTx67cn+WSSM2qt93e0YDM/SfLu5WSeleS6YegCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKusnm4XYNlKKWsm+WSSuujUEmJ14VGSPJrkbUmeWGv9RK31/uHo2cAlSR5c+LguJbPX8FQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgFVXT7cLsFzvTLLhwsdlCdfrYteuTjKp1vqxWuuc4SjXVK11QZLfZun3UJI8c1hLAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAqqKfbBVi6UspaSY5JUpcSqUnKwuMXSXavtU4dnnaDcslyrm9VSlljWJoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCqqp9sFWKYjk4xf+Lg85lpdeK4muSjJgbXWR4ax22BcsoRz5TGPdxqmLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwSurpdgGW6ZVJ6hLOL37ur0kOrrXOHp5KQ3J1g8z2HW8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKuwnm4XYMlKKU9O8pRFny4pkqQmOabWes+wFRuChT0fXPTpUmJbD08bAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFg19XS7AEv1gqWcr0nKwo8X1Fp/NHyV2uKG/L3/0mw1XEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYFXU0+0CLNXkBpkTO96i/aYt5/omw9ICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZRPd0uwFLtkaQ+5tzin99Za71gGPu0y13LuFaSrDdcRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgVdTT7QL8u1LKhCQbLPr0sZeT1CTnDmup9rlvKefrwo/rDFcRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgV9XS7AEu0dYPMRR1v0RmzlnN99WFpAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrqJ5uF2CJntAgc13HW3TG7OVcHzMsLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgFdXT7QIs0RoNMrd2vEVnzF/O9VHD0gIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVlE93S7AEq3eIDO94y06Y+xyrs8ZlhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsIrq6XYBlmh0g8zcjrfojHHLuT5rWFoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCqqp9sFWKJZDTKrdbxFZ2y0nOszh6UFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKyierpdgCWa2SAzoeMtOmOzpZwvCz8+OEw9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCVNLLbBViiGQ0yT0hyV6eLdMB2SepSrtUktw9jFwBaUEp5fZJj2rDV6m3YAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEEa2e0CLNGdDTITk/y+00XaqZSyVpItk9QkZSmxW4erDwAtWz/Jk7pdAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKHp6XYBlujmBpmndbxF++3RIHNLx1sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCqsp9sF+He11oeSPLjo0yVESpK9h61Q++zfIHNFx1sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCqsp9sFWKorkpTHnCtJ6sLHO5dSNh3eSoNXSulJclD+2X9pLhuGOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwyurpdgGWakqDzGGdLtFGL0qy8cLHZbHzdbHHN9ZaHxq+SgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACw6hnZ7QIs1ZRlXKtJSpKjSikn11rnDFOnoXjbMq6V/P2efjpMXQAYnHuSXNuGfbZP0tOGfQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiEkd0uwFL9Osn0JGskqUnKwvNl4edJskmS1yf5xLC3a0Ep5YVJ9sy/3seSDAxPIwAGo9b6uSSfG+o+pZSHk4wfeiMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGo6fbBViyWuvsJANJytIiC6+9v5Sy+bAVa1EpZfUkn8vf+z7W4ufuTfKbYSkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKuwnm4XYJm+tZTzZbHH45N8o5Qyahj6DMZnk2y58HFZwvWSpCY5vda6YLhKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCqqqfbBVi6WutPk1y36NPHXC6LnZuc5LTh6tVUKeUdSf4rf+9ZHnN58ftZkOTzw9ULAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZlPd0uwHKdnKQs5VpJUhd+fGUp5WullBHD1mwZSilvS3Ji/t5vqbGF179fa71tWIoBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwCqup9sFWK4zk0xd+Lgu4XpZeL4keWWSX5VSNhmmbv9eppQxpZQvJPnw4qcfE1v8PuYmeXfHiwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASZKebhdg2Wqt85K8PklZRqwkqQs/Tk5ybSnlmFLKsP77llKel+SKJK97TKclxhdeP6XWetPwNAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAerpdgOWrtZ6f5NtJSpK6lNji1yYk+UySG0spR5VSJnSyXynlRaWUnyf5eZIdFutSlhBfvP+tSd7byW4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwL/q6XYBGjsqydSFj+tSMmXhtbrw8VZJPpdkWinle6WU15Xy/9mx7zC76nJtwM+aVAIJQ3cC0qULUo50kRKaChkBFfBDQKqggorooCgiI6JgwaDSpKigcsiASIuASJNiBBEEQm8DJOBAQvpkfX9IPBFT1p7sPRPwvq9rXZnZ+3l/77N2phdrL2yRoihWKYpi76IofloUxfNJrkyy4xs7Z/cr5jI6u3eRpDvJ/yvLcuLC9gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAquvf1wWopizL14qi2CvJHUkWS1ImKeYSLd54rpzj/cWSjHzjSlEUryd5JMlTC9pbFMVFb8wvkWTFJCsnGfqmff+qOZfH5tXv62VZ3rag/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAffXv6wJUV5bl/UVR7J2kI8mAJGWSYi7R2Y+Vb1x5U26JJJsk2Xguz835fpFk/7k8/m+1FvD8nLnijX/PK8vylPlkAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAGaerrAtSmLMtrk3wkyczZD80nXrxxzc7NeWWO5+anSLVz5nfWnB2vSHJEhb0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAM09XUBaleW5ZVJPpTk1dkPvXHNS/Gmq8rMv9a96ZrXefObnz1zUZJ9yrKcVWEvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAATX1dgJ4py/L6JFsmeSxJMfvhiuPFHFct2aozs7uUc+S/VZblgWVZdlecBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaoKmvC9BzZVk+nGSTJGfP+fAbV1+avb9I8lKSD5RleUIf9gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3tDU1wVYOGVZTirL8ogkI5I8nKSY/dQcV69UmeMq3rguTbJhWZbX9lIHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGABmvq6APVRluWNSdZPclCSJ5MUb1xJUs5x1XXtm86dvfOOJFuVZblfWZYv1XknAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAQmvq6APVT/tOFSdZK0prkmiRlkuKNK2+8P7drvkfPZ2b22d1JfpVk67Isty7L8k91ui0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoI6a+roA9VeWZXdZlleUZfmBJO9McniSK5K8nqSYy5Uk5Xyu2d48NzXJVUk+maSlLMt9y7K8o7F3BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANVdcMEFKYpigdeBBx7Y11UBek3/vi5AY5Vl2ZnknCTnFEXRL8l6STZJsnGSNZKs9Ma1zHyOmZbkmSRPJXkiyV+S3JXkvrIsZzauPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQb/37ugC9pyzL7iT3v3FdOOdzRVEUSRab4+pOMjnJlLIsp/dyVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoNd3d3XnwwQfzt7/9LQ899FAeeeSRPPfcc3nhhRfyyiuvZMqUKZk6dWoGDhyYwYMHZ8iQIVl++eUzfPjwrLTSSll//fWz4YYb5j3veU+am5v7+nbgv9YLL7yQhx9+OP/4xz8yceLETJw4Mf369cvQoUMzdOjQLL/88ll33XUzbNiwvq4KANDn+vd1ARYNZVmWSSa/cQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA29bEiRNz66235g9/+ENuu+22/OUvf8nkyZMXODd16tRMnTo1XV1def7553Pvvff+2/NNTU3ZdNNNs+OOO2bvvffOpptu2qA7eOs58cQTc/LJJ1fKLr300rnxxhuz0UYbNbjV29P48eMzatSomudWXXXVHHjggfUv1CBlWebPf/5zrrnmmowZMyb3339/urq6Ks2uuOKK2XjjjbPrrrtm9913z2qrrdbYsgAAi6D+fV0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKDRHnzwwfzud7/LVVddldtvvz0zZ86s+45Zs2bl7rvvzt13351TTz016623Xg455JAceuihWWKJJeq+763i5JNPzsknn1w5/8orr2SnnXbKTTfdlA022KCBzd6ejj766Pz617+ueW677bbLgQceWP9Cdfbyyy/n7LPPzllnnZVnn322R2c899xzee6553LVVVclSTbbbLN85jOfyUc/+tEMHDiwnnUBABZZTX1dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgEe6///589atfzdprr531118/X/ziF/PHP/4xM2fO7JX9Dz74YD73uc9llVVWycknn5wpU6b0yt5FyamnnpoTTzyx5rkJEyZkxx13zIMPPtiAVm9fl19+eX7961/3dY2GmDhxYr7whS9kpZVWSltbW5599tm6nX3PPffkgAMOyMorr5xzzjknZVnW7WwAgEVVU18XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAColxdffDFnnHFGNtxww2y44Yb55je/mUceeaRPO73yyis58cQTs/766+d3v/tdn3bpTaeffnq+/OUv93j+pZdeyo477piHH364jq3evl555ZV86lOf6usaDfHrX/8666yzTk4//fRMnTq1YXtefPHFHHbYYdliiy1y7733NmwPAMCioKmvCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1MOYMWOy0kor5fOf/3zuv//+vq7zH5544ol88IMfzKc//elMnz69r+s01A9+8IN84QtfWOhzXnjhheywww4ZN25cHVq9vX3mM5/Jiy++2Nc16mrGjBk5+uij89GPfjTPP/98r+296667suWWW+bCCy/stZ0AAL2tqa8LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACyqpv79731doVf8t9wnb3+vvvpqZs6c2dc1FuhHP/pR3ve+9+Xll1/u6yoNcdZZZ+WYY46p23nPP/98dthhhzz++ON1O/Pt5re//W1+8Ytf9HWNuurq6sqOO+6YUaNG9cn+qVOn5sADD8wxxxyTsiz7pAMAQCM19XUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEXR+DN/lCc+vFe6Rnf0dZWG6hrdkSc+vFfGn/mjvq4C/1XuvPPOvO9978tzzz3X11Xq6uyzz87RRx9d93OfffbZbL/99nnyySfrfvZbXVdXV4444oi+rlFXEydOzK677ppbbrmlr6vkBz/4QT796U/3dQ0AgLpr6usCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIua8Wf+KBNGjUrKMp1tbeka3dHXlRqia3RHOtvakrLMhFGjMv7MH/V1Jfiv8uCDD2aXXXbJq6++2tdV6uL888/PEUcckbIsG3L+008/ne233z5PP/10Q85/qzr22GPz/PPP93WNupkyZUp233333HnnnX1d5V9GjRqV4447rq9rAADUVf++LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwKBl/5o8yYdSo/3ugLNPZ1pYkaW4d2TelGqBrdMc/76ss//XY7Pte7tNH91Ut6DNFUWSNNdbIZpttlk022SSrr756Vl111QwfPjyLL754Fl988cycOTOvv/56nn/++Tz22GMZO3ZsbrjhhvzpT39Kd3d3j/Y+8MAD2WuvvXLdddelX79+db6r3nPRRRfl0EMPTTnH15Qqll9++bz00kuV808++WR22GGH3HzzzVlxxRVrrfm2c+211+aCCy7o6xp1dfTRR+fWW2+teW6xxRbLHnvskR133DGbbrppVlpppTQ3N2fGjBnp6urKI488kj//+c+54oorctttt9X8sfrd734373nPe7L//vvX3A0AYFHUv68LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwqxp/5o0wYNeo/nyjLdLa1JUmaW0f2bqkG6Brd8c/7Kcv/eG72/S/36aN7uxb0umWXXTa77bZbdtlll+y8885Zbrnl5pvv169fBg0alKWXXjobbLBB9txzz5x00kl58cUXc/755+f73/9+XnrppZp73HDDDfnud7+b448/vqe30qd++ctf5qCDDsqsWbMqzxRFkdNPPz0HHXRQRo4cmZtvvrny7GOPPZbtt98+N998c1paWnpS+W3htddey2GHHdbXNerqoosuyvnnn1/TzBJLLJEvfOELOfbYYzNs2ELQlJEAAQAASURBVLD/eH7gwIFZfPHFs+KKK2b77bfPF77whTz66KM58cQTc+mll6acy/fCeTn88MOzySabZN11162pIwDAoqiprwvw1lUURUtRFFsXRTGyKIr9iqLYuyiKXYqiWKcoin593Q8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqMf7MH2XCqFHzDpRlOtva0jW6o9c6NULX6I50trUlZTnPzIRRozL+zB/1YivoPUsssUQOOOCAXH311ens7MxFF12U/fffP8stt1yPz1xhhRXy5S9/OY8//ni+/OUvp3///jWf8bWvfS0PPfRQjzv0lV//+tc54IADMmvWrMozAwcOzCWXXJJjjz02zc3Nue666/KRj3ykpr3jxo3LDjvskBdffLHWym8bxx13XJ555pn5Zj784Q/3UpuF99RTT+XII4+saWbLLbfM3//+93zta1/LsGHDKs+tueaa+eUvf5kbbrghK6ywQuW5119/Pfvuu2+6u7tr6gkAsChq6usCvHUURdGvKIoPF0Xxy6Ionk/ybJI/JvnfJBcn+VWSq5M8kOT1oihuLIric0VRLNN3rQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDBxp/5o0wYNWrBwbJMZ1tbukZ3NLxTI3SN7khnW1tSlgvMThg1KuPP/FEvtILesf766+fMM8/Mc889lwsvvDC77bZb+vfvX9cdiy++eNrb23PLLbekpaWlptlp06blhBNOqGufRrv88suz//77p7u7u/LMkksumeuuuy4f/ehH//XYoEGDcumll+aYY46paf9DDz2UHXbYIePHj69p7u3ghhtuyNlnnz3fzGqrrZaTTz65lxotvGOOOSaTJ0+unP/Yxz6Wm2++OSuttFKPd26//fYZO3Zs1l577coz9913X0ZV+ZkBAGAR19TXBXhrKIri4CSPJflNko8meUeSYj7XwCTbJflOkmeKohhVFMXSfVAdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5mv8mT/KhFGjqg+UZTrb2tI1uqNhnRqha3RHOtvakrKsPDNh1KiMP/NHDWwFjff+978/1113Xf72t7/l6KOPzrBhwxq+c4sttsif/vSnrL766jXNXX755bn33nsbU6rOrrjiinzsYx/LzJkzK8+suOKKueWWW/L+97//P54riiLf+9738p3vfCdFUVQ+88EHH8yOO+6YCRMmVJ55q5s0aVIOOeSQBebOPvvsDBkypBcaLbxrr702HR0dlfMjR47MxRdfnAEDBiz07uHDh+fGG2/MaqutVnnmxBNPzEsvvbTQuwEA+lJTXxdg/oqi6FcUxcoVroEN2r9CURR/SHJOkpWTFG9cZYVrdnZwkiOSjCuKorURPQFovKIojiqK4oGFvZIs3tf3AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw29S//z0Tzjqr9sGyTGdbW7pGd9S9UyN0je5IZ1tbUpY1z04466xM/fvfG9AKGmvXXXfNHXfckZtuuik777xzr+9feeWV8/vf/z7LLrtsTXM//elPG9Sofn73u9/lIx/5SGbMmFF5Zr311ssdd9yRd7/73fPNfeELX8jPf/7zDBw4sPLZ999/f0aMGJFXXnml8sxb2Ze+9KU8+eST880ceOCB2WmnnXqnUB188YtfrJxda621cvHFF6d///512z98+PD85je/qfxx9+qrr+aUU06p234AgL7Q1NcFWKCPJXliAdd9SQbVe3FRFO9KcleSbZMUSco5rrzx2LyuvClfJFkqyWVFUZxc764A9IrlkqxXh8vPHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAImPwuuumpb09KYrah8synW1t6RrdUfde9dQ1uiOdbW1JWdY+XBRpaW/P4HXXrX8xaJAtttgif/jDH3LNNddkiy226NMuq622Wn7+85/XNHPppZdm2rRpDWq08K677rrstddemT59euWZbbfdNrfeemve+c53Vsrvt99+ueaaazJs2LDKO+69996MGDEiXV1dlWfeim6++eacddZZ882ssMIKOf3003up0cK7+uqrc//991fKNjU15ZJLLskSSyxR9x6bbrppvvnNb1bOn3vuuXn55Zfr3gMAoLc09XUBFmifJMV8riT5SVmWE+u5tCiKdyS5Mck739gz+y9Kb949zyPelCvfuIokbUVRfLeefQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCnmltHpqW9PSmK2ofLMp1tbeka3VH3XvXQNbojnW1tSVnWPlwUaWlvT3PryLr3gkbZbbfdcscdd2S77bbr6yr/sssuu2S//farnO/q6srtt9/ewEY99/vf/z4jR47MtGnTKs/stddeuf7667PUUkvVtGuHHXbIH//4xwwfPrzyzNixY7Pzzjvntddeq2nXW8XkyZPzyU9+MuUCvqafeeaZWXrppXup1cI79dRTK2cPPfTQbLLJJg3rcswxx2TttdeulJ08eXJ++MMfNqwLAECjNfV1AeatKIqhSXZJUs7jSpLuJHX9ibQoiqYklyVZcY5dxRtXj46cY3b2WccWRfHphawKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAddHcOjIt7e1JUdQ+XJbpbGtL1+iOuvdaGF2jO9LZ1paUZe3DRZGW9vY0t46sey9opMUXX7yvK8zVSSedlKampsr5m266qYFteuamm27KHnvskalTp1ae+fSnP51f//rXGTx4cI92brTRRrnjjjuy7rrrVp65++67s+uuu2bixIk92rkoO+GEE/LYY4/NN7Pnnntmn3326aVGC+/ee+/NLbfcUim72GKL5eSTT25onwEDBuTUU0+tnP/xj3+cmTNnNrARAEDjVP8Nhb7woSSD3ni7mOOa/X6Z5HdlWXbWee+xSbZ64/zZu+ph9jnlG2+fXhTF5nU6GwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZKc+vItLS3J0VR+3BZprOtLV2jO+reqye6Rneks60tKcvah4siLe3taW4dWfde8N9qzTXXzA477FA5f/fddzewTe1uueWWfOhDH8qUKVMq5YuiyKmnnpof/vCHaWpqWqjdK6+8cm699dZsvfXWlWfuuOOO7L777pk0adJC7V6U3H777fnhD38438ywYcNy1lln9VKj+rjooosqZw888MAst9xyDWzzT3vuuWfWWmutStnx48fn2muvbXAjAIDGWLif1Gm0D1bI/KyeC4uiWD7J15LM/mtS1b+QlXNc810xR75/kvOLohhYa08AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABohObWkWlpb0+KovbhskxnW1u6RnfUvVctukZ3pLOtLSnL2oeLIi3t7WluHVn3XvDfrrW1tXJ23LhxDWxSm9tvvz277757Xn/99Ur5AQMG5KKLLsrxxx9ftw5LL710fv/732fkyJGVZ2699dZ88IMfzOTJk+vWo69MnTo1Bx98cGbNmjXf3GmnnZbhw4f3UquF193dnUsvvbRy/phjjmlcmTkURZHPfvazlfM///nPG9gGAKBx+vd1AeZriyRv/svOnO9PSnJtnXeekGSJN/Ys6C9j8/qr05yPz+2MYo7MOkmOSXJa9YoA9JHxSR6swznrJGmqwzkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3R3DoySdLZ1paUZW3DZfnPuTnO6U1dozt61jtJiiIt7e190hv+G2y77baVs08++WRmzZqVpqamBjZasDvvvDO77bZbJk2aVCk/dOjQ/O///m9GjBhR9y6DBw/O//7v/+bTn/50zjrrrEozN998cz70oQ/lqquuymKLLVb3Tr3lxBNPzMMPPzzfzPve974cdthhvdSoPm666aZ0dnZWym6++eZZa621Gtzo/3zsYx/LMccckxkzZiwwe+WVV2bSpElZYokleqHZ28s//vGPjBkzJvfdd18eeOCBjBs3Ll1dXXnttdcyZcqUDB48OEOGDMkKK6yQ1VZbLWuttVa22mqrbLPNNll++eX7un7dzJo1K88991yeeOKJjB8/Pq+//nomT56c7u7uLL744hkyZEiWWmqprLbaallllVUyYMCAvq5cVy+//HLGjBmTu+++O3//+98zbty4vPrqq5k4cWK6u7szdOjQDB06NMsss0zWWWedrL/++tl4443z/ve//y39tX1hdHV15fHHH89zzz2XSZMmZfLkyZkyZUoGDhyYxRdfPEsssURWXnnlrL766llyySX7um5ddHd35+mnn05nZ2fGjx+frq6uTJs2LdOmTUv//v0zZMiQf7uWWmqprLLKKllqqaX6ujos0vr3dQHmriiK5ZKsmqRMUrz56Tcev6Ysy+l13LlMkk++cfb8zH5+zl6Tk7yWZLkk/ebIza3/nOcUSb5YFMVPyrJ8rSe9AegdZVmOSjJqYc8piuK1JEMXvhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOM0t45MknS2tSVlWdtwWf5zbo5zekPX6I6e9U2SokhLe3uv9oX/Nu9617tSFEXKCp+j3d3def311zN06NBeaDZ399xzT3bZZZe89tprlfLveMc7cvXVV2fjjTduWKempqaMGjUqK664Yk444YRKMzfeeGP23HPPXHnllRk8eHDDujXKXXfdlTPOOGO+mcGDB+ecc85JURS91Ko+rr766srZfffdt4FN/tPSSy+dXXfdNb/97W8XmJ0yZUpuuummfOhDH+qFZr3vD3/4Q7bffvsF5rbbbrv84Q9/WGBu6tSpueiii3LppZfmlltuycyZM+eZff311/P6669n/Pjx+dvf/pYkOf3009PU1JRtttkm++23Xw444IAstthile9nUfDqq6/muuuuy6233ppbb701DzzwQKZPn15ptqmpKWussUa23nrrbLPNNtl5553zzne+s8GN62/KlCm59NJLc8455+TOO+/MrFmz5pl95ZVX8sorr+Spp57K2LFj//X4kCFDstNOO+XjH/94PvzhD6dfv369Ub3XTZ06NTfffHNuu+223HbbbRk7dmy6uroqzy+//PLZaqutsvXWW2fXXXfNBhts0LiydTRu3LjccMMNuf322/PnP/85jz76aOXPkzkNGzYsq6yySlZdddWstdZa2XzzzbPFFlu8JT9voBH693UB5mmLCpnr67zzkCRDkpRJ5vWbxezfZosktyf5SZJryrJ8OUmKomhKsmaST7xx3nLzOK+Y46ylkhya5PS63AUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUQXPryCRJZ1tbUpa1DZflP+fmOKeRukZ39KxnkhRFWtrbe6Un/DcbPHhwllpqqbzyyiuV8pMmTcrQoUMb3Gru/vKXv2TnnXfOq6++Wim/9tpr59prr82qq67a2GJvaGtry0orrZRDDjkkM2bMWGB+zJgx+fCHP5zRo0dn0KBBvdCwPqZNm5aDDjoo3d3d882deOKJWWuttXqpVf2MGTOmcnbPPfdsYJO522OPPfLb3/62UnbMmDH50Ic+1OBGb22TJ0/O9773vfzwhz/MSy+9tFBnzZo1K3/84x/zxz/+MSeeeGKOP/74fOYzn0n//v3r1Lb+Zs2alY6Ojlx88cW55pprMm3atB6fM27cuIwbNy4XXHBBiqLINttsk/322y//7//9vyy++OJ1bl5f06ZNyw9/+MOceuqplb8fzsvkyZNz5ZVX5sorr8waa6yR4447Loceemiamprq1LbvlGWZa665JpdcckmuuOKKTJw4scdnvfTSS+no6EhHR0eOO+64bLDBBtl///1z+OGHZ6mllqpj64X34osv5txzz80ll1ySBx54oC5nvvbaa7n//vtz//33/9vjLS0t2WKLLbLrrrumtbU1yy23XF32wVvNW/8r5tvX5hUyv6/zzoOTzOuvSuUbV5FkVpIjy7LcpizLn5dl+fK/QmU5qyzLR8qyPCHJu5Pc+MbM/M4tkhxep3sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAumluHZmW9vakKGofLst0trWla3RH3XvNqWt0Rzrb2pKyrH24KNLS3p7m1pF17wX8pyFDhlTOlj35nK6Dv/71rxkxYkT+8Y9/VMpvueWWue2227Lqqqs2ttibHHDAAfntb3+bJZZYolL+mmuuyd57753p06c3uFn9fOMb38iDDz4438xGG22U4447rpca1U9nZ2f+9re/VcquscYavf7xlSQ77bRT5ez111/fwCZvfddff3022GCDfOUrX8lLL71U17NfeumlfP7zn89mm22Wv/71r3U9ux5mzpyZn/3sZ1l33XWz1157paOjI9OmTavb+WVZ5pZbbsmRRx6ZVVddNaecckpee+21up1fTzfccEPWW2+9fPGLX8wrr7xS17Mfe+yxHHHEEdlqq63ywAMP1PXs3jRjxoz87Gc/y3rrrZcPfOAD+fnPf56JEyfWdcff/va3fPnLX84qq6ySL33pS+nq6qrr+T3x3HPP5bDDDss73/nOfOUrX+mV/8POzs6MHj06hx9+eFpaWrLTTjvlpz/9aSZNmtTw3bAoaerrAszTunN5bM7fEF8sy/Lpei0rimLzJO+a/e68Ym90OKgsy58u6MyyLF9KskuSm+eYffN5s61RFMWWNZUGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAXtDcOjIt7e1JUdQ+XJbpbGtL1+iOuvdKkq7RHelsa0vKsvbhokhLe3uaW0fWvRcwdxMnTqycXWKJJRrYZO4eeOCB7LTTTnn55Zcr5ffYY4/ccMMNWWaZZRrcbO522WWX/OEPf8gKK6xQKX/VVVflox/9aGbMmNHgZgtv7NixOe200+ab6devX84777z079+/l1rVz0033VQ5u9NOOzWwybytuuqqWWONNSplH3744XR2dja40VtPd3d3PvvZz2aXXXbJE0880dBd9913X7baaquMHj26oXtqcffdd+d//ud/cvDBB+eRRx5p+L4JEybkK1/5StZdd9387//+b8P3VdXd3Z0TTjghO++8cx5//PGG7rrzzjuzySab5MILL2zonkYYM2ZM1l9//Rx88MF56KGHGr5v4sSJ+fa3v5111lknl156acP3zU1ZlvnBD36QtdZaK+ecc06ffX/u7u7ODTfckCOOOCL33HNPn3SAvtLU1wWYp1Xn8XiRpExS769We8/nuXKOvZeUZfnzqoeWZdmdZJ8kz89x1rzsWfVcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6E3NrSPT0t6eFEXtw2WZzra2dI3uqGunrtEd6WxrS8qy9uGiSEt7e5pbR9a1EzBvM2bMyGuvvVYp269fvyyxxBINbvTv/v73v2fHHXfM+PHjK+UPP/zwXH755VlsscUa3Gz+Nt1009x+++1517veVSnf0dGR/fbbLzNnzmxws56bMWNGDjrooAV2/NznPpdNN920l1rV1z333FM5u8UWWzSwSf12//nPf25gk7eeV199NR/4wAfywx/+sNd2vv7669l7771z6aWX9trOuZk1a1ZOOOGEbLHFFrn33nt7ff/zzz+fvffeO3vttVcmTpzY6/vnNGXKlLS2tqa9vT2zZs3qlZ3Tp0/PgQcemG9+85u9sm9hvfrqq9lvv/2y8847Z9y4cb2+/8UXX8y+++6b/fbbL5MnT+61va+++mp22223HHPMMb26F/h3TX1dgHlaNcn8/trzQJ33jZzHvjkf605yQq0Hl2U5IUl7kvn9Ra1IslutZwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBvaW4dmZb29qQoah8uy3S2taVrdEddunSN7khnW1tSlrUPF0Va2tvT3DqyLl2Aah544IGUFT9nV1111TQ1NTW40f955JFHsuOOO+bFF1+slP/GN76Rn/zkJ+nXr1+Dm1Wz+uqr5/bbb8/mm29eKX/ZZZfl4x//eLq7uxvcrGdOOeWU/PWvf51vZo011shJJ53US43qb+zYsZWzm266aQObzN9mm21WOVvLPb3dTZw4MSNGjMh1113X67tnzZqVAw44IL///e97fXeSvPrqq/ngBz+Y9vb2zJo1q086zHb55Zdniy22yLhx4/pk/6RJk7Lrrrvmt7/9bZ/s/+pXv5pTTjmlT3ZXdf/99+d//ud/cskll/R1lVxyySXZaqut8swzzzR81/jx47P11lv3ydcI4N/13m8cVFYUxRJJlpr97jxij9Rx3+pJ1pjPviJJmeSKsiyf6uGac5M8/8bbb/6tePb76xdFMbSH5wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDDNbeOTEt7e1IUtQ+XZTrb2tI1umOhOnSN7khnW1tSlrUPF0Va2tvT3DpyoToAtbvnnnsqZ9daa60GNvl3jz32WHbYYYd0dnYuMNu/f/+cf/75+epXv9oLzWqz7LLL5sYbb8wHP/jBSvlf/epX+cQnPpFZs2Y1uFlt/vrXv6a9vX2BubPPPjuLLbZYLzSqv7Isc++991bKDh48OOutt15jC83HZpttVjk7duzYBjZ565g6dWr22GOP3H333X3WYcaMGdl///3zwgsv9OreV155Jdttt12uueaaXt07Pw8++GC22mqr3H///b26d+bMmdlnn33yxz/+sVf3vtlXv/rVXHrppX3aYV6uvfbabLHFFhk3blxfV/mX++67L+9///vzzDPPNGzHpEmTsuuuu+aBBx5o2A6guv59XYC5WrVC5ok67htRMXdeTxeUZTm9KIrfJPlskjn/mlXM8X6RZPMkv+/pHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGi05taRSZLOtrakLGsbLst/zs1xTi26Rnf0bG+SFEVa2tt7tBdYeFdeeWXl7Hvf+94GNvk/TzzxRLbffvs899xzC8wuvvji+c1vfpPddtutF5r1zJAhQ9LR0ZEjjjgi55577gLzv/jFL9K/f/+cf/75aWpq6oWG8zdz5swcdNBBmTFjxnxzn/zkJ7PDDjv0Uqv6e+qpp/Lqq69Wyr7rXe9Kv379Gtxo3tZZZ53K2fvuu6+BTd46DjnkkPzhD3+olB02bFg22WSTrLHGGhk+fHgWX3zx9OvXL6+//nqee+65PPzww7n77rszZcqUmnu89NJLOeKII9LR0VHzbE90dXVlxIgRi+THwYQJE7Ljjjvmpptuyvrrr98rOz/1qU/l2muv7fH8O97xjmy88cZZe+21s/TSS2fIkCGZPHlyurq68sgjj+Tee+/Ns88+u8BzyrLMQQcdlA033LDHXRrhyiuvzD777JPp06f3dZX/8Pjjj+f9739/br/99qywwgp1P//oo4/O2LFj634u0DP9+7oAc7VMhcxLddy37Twen/MvT68kuX4h91yV5LMLyGyQ5PcLuQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaqrl1ZJKks60tKcvahsvyn3NznFNF1+iOnu1LkqJIS3t7TfuA+nn11Vdz/fXXV86///3vb1yZNzz11FPZfvvt88wzzywwu/zyy+eqq67K//zP/zS818Lq169fzjnnnKy44oo56aSTFpi/8MIL079//5xzzjkpiqIXGs7baaedlrFjx84309LSku9+97u91KgxHn/88crZNddcs4FNFmzZZZdNc3Nzurq6Fph95plnMnPmzPTv37/xxRZR5557bn7xi1/MN9PS0pL/9//+Xz7ykY9k4403TlNT03zz06dPzzXXXJNRo0ZlzJgxNfW54oorcsMNN2THHXesaa5W3d3d2WuvvRb4+TsvK6ywQnbddddsv/32WW+99bLqqqtm6NCh6devXyZOnJgXXnghf//733Pbbbfl6quvzsMPP1zzjvHjx2e33XbLn//85yy33HI96lnVxRdfnHPOOafmuaWXXjoHH3xwPv7xj2ejjTZaYP6BBx7IJZdcknPPPTcvvvjiPHNTp07NQQcdlMMOO6zmTo1w/fXXZ++9986MGTN6NP+e97wn2223XTbbbLOsueaaWXnllTNs2LAstthimTFjRiZOnJinnnoqDz30UG699dZcddVVee6552ra8fjjj2fvvffOjTfemAEDBvSo59xce+21ufDCC3s0u/baa2fHHXfMOuuskzXWWCOrr756hg4dmsUXXzyLL754iqLItGnTMnny5EyYMCHjx4/PE088kXHjxuXBBx/M3XffnWeffbZu9wJvF/+9P7Us2oZUyIyv476tk8zrL03FG8/9tizLWQu5549JZibp98aZc/vta62F3AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9orl1ZJKks60tKcvahsvyn3NznDM/XaM7erYnSYoiLe3tlfYAjXH22Wdn2rRplbLNzc3ZcsstG9rn2WefzQ477JCnnnpqgdk11lgj1113XdZYY42Gdqq3r3/961lppZVyxBFHpLu7e77Z8847L/3798+Pf/zjFEXRSw3/3YMPPphvfOMbC8ydeeaZaW5ubnyhBnriiScqZ9/1rnc1sEk1a665Zu65554F5rq7u/P0009n9dVX74VWi54nn3wyn/nMZ+b5/DLLLJOTTz45Bx98cAYNGlT53IEDB2bPPffMnnvumeuvvz6HHHJInnnmmcrzbW1tufPOOyvne6KtrS033nhjzXMbb7xxvvzlL6e1tTX9+/efa2bppZfO0ksvnfXWWy977bVXzjjjjNx66635zne+kyuvvLKmfc8880w+9rGP5frrr0+/fv1q7lvF448/nqOOOqqmmQEDBuTYY4/NV77ylQwdOrTy3Prrr59vfvOb+cpXvpLTTjstp556aqZMmTLX7F133VX5+3AjPfzww/noRz+aGTNm1DQ3fPjwHH744TnooIPyzne+c565fv36ZfDgwVluueWy2Wab5eMf/3jKsswNN9yQb33rWzV9nN5666059thj86Mf/aimrvNSlmWOP/74mmaWW265fPazn83HP/7xrLLKKgvM9+/fP4svvniWW265rLvuunnf+973b893dnbmhhtuyO9///tcddVVefnll2vqA29HTX1dgLkaUiHzej0WFUUxPMnsr7Dz+03omoXdVZbljCSPLSC26sLuAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgN7S3DoyLe3tSVHUPlyW6WxrS9fojvnGukZ3pLOtLSnL2ncURVra29PcOrL2WaAupk+fnh/+8IeV8/vss08GDRrUwEbJSiutlMceeyxlWS7wevTRR7PGGms0tE+jHHLIIZk5c2al+/zJT36Soidfy+ugu7s7Bx10UKZNmzbfXGtra/baa69eatU4TzzxROXsyiuv3MAm9e9Qy7293Tz11FOZMmXKXJ/bc88989BDD+XII49cqK9vO++8c+6+++5ssskmlWfuuuuu3H777T3euSBjxozJaaedVtPMkCFD8pOf/CT33HNP9tlnn/Tv37+m+W222SZXXHFFxowZk5VWWqmm2RtvvDHt7e01zdTiiCOOyMSJEyvnV1555dxyyy359re/naFDh/Zo5+DBg3PiiSfmrrvuytprrz3P3H333dej8+tl4sSJ+dCHPpSurq7KM0sssUS+853v5LHHHsuJJ56Yd77znTXvLYoiO+20U2644YZ0dHRk+PDhlWdHjRqVm266qeadc3PjjTfmr3/9a+X8F7/4xTz11FM54YQTssoqq9SlQ0tLSz7+8Y/nggsuyAsvvJDrr78+++23X8N/7oJFWVNfF2CuhlTIzP83h+q2msfjc/4FalaS6+u07+Ek8/qtq0iyQp32AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQK9obh2Zlvb2pChqHy7LdLa1pWt0x1yf7hrdkc62tqQsaz+7KNLS3p7m1pG1zwJ18/3vfz/PPvts5fxBBx3UwDYsis4444zcdddd8800Nzdn1KhRvdSosZ544onK2Xe84x0NbFL/DrXc23+LL3/5yxk9enSWXXbZupy3wgor5Lrrrssaa6xReeanP/1pXXa/2ZQpU3LkkUfWNLP66qvnnnvuyeGHH56mpqaF2r/TTjvl3nvvzfbbb1/T3CmnnJJHHnlkoXbPzZVXXpkxY8ZUzq+zzjq54447svnmm9dl/wYbbJA77rgjm222WV3Oq7fjjjsu48aNq5zfaqutcv/99+cLX/hCBg8eXJcOe+65Z8aOHZutt9668sxhhx2WqVOnLvTuCy+8sFKuqakpv/nNb/Ltb387iy222ELvnZf+/ftnxIgR+cUvfpHnnnsu7e3tWX755Ru2DxZVC/ediEYZUiHTg78SzdWW83lu9l+5/lqW5at12vfUPB6ffT/L1WkPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9Jrm1pFpaW9PiqL24bJMZ1tbukZ3/NvDXaM70tnWlpRl7WcWRVra29PcOrL2WaBuXnzxxZxyyimV8+973/uy5ZZbNrARi5qHH344J5544gJz3/nOd9LS0tILjRrvxRdfrJx9xzve0cAm9e/w0ksvNbDJW88JJ5yQ9vb2FD35+Wg+ll122fzyl79Mv379KuWvuOKKTJ8+va4dkqS9vT2PPfZY5fzaa6+dW265Jeuuu27dOiyzzDK5+uqrs+uuu1aemTZtWo488si6dUiS7u7ufOELX6icX2mllXLTTTdl+PDhde2x1FJL5fe//31dX+N6uPHGG3P22WdXzu+333658cYbs+qqq9a9yworrJAxY8Zkxx13rJR/9NFHc9ZZZy303uuvv75S7mtf+1r23nvvhd5Xi2WWWSZf/vKX89RTT2XjjTfu1d3Q15r6ugBzNaBCZvE67VrQb59lkj/UaVeSTFrA80PruAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6TXPryLS0tydFUftwWaazrS1dozuSJF2jO9LZ1paUZe1nFUVa2tvT3Dqy9lmgro444oi89tprlfNf/epXG9iGRc2sWbNy8MEHZ+rUqfPNvf/9788nP/nJXmrVeK+88krl7AorrNDAJvXv8PLLLzewyVvLPvvsk29+85sNO/+9731vDjrooErZV199NTfeeGNd97/88sv5/ve/Xzm/7LLL5pprrsnw4cPr2iNJBg8enMsuuyzvec97Ks/ceOONuemmm+rW4fLLL8+4ceMqZQcOHJiOjo684x3vqNv+OS255JK58sors+SSSzbk/FrNmjUrRx99dMqKP9fvt99+ufjiizNo0KCGdVpsscXS0dGRDTbYoFL+tNNOy+TJk3u879FHH82LL764wNxKK62UE044ocd7FtbgwYMXmY8b6C39+7oAczW9QmZIkokLs6QoikFJNkmyoO9QdyzMnjd5fQHPN+67HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwH+RV37xi/zjkkv6ukave+eoURm4yioN3zP9qafyzFFHzfW5fsstm+6Xxtd+aFmm88tfzgvfOCnllKk97tZvuWXz8nnn5uXzzu3xGfOy1L77Zun996/7uXPzzJGfyvRnnu6VXfXUm68Ri7YLL7wwHR0dlfO77757dtppp8YVYpHzwx/+MLfffvt8M4sttljOOeecFEXRS60a7+WXX66cXXLJJRvYpP4darm3t7MVV1wx555b/59D3uyEE07I+eefn1mzZi0we/PNN2fXXXet2+7vf//7mTRpUqVsURS55JJLstpqq9Vt/5stvvji6ejoyIYbbpjXXnut0szJJ5+c7bffvi77v/vd71bOfu1rX8umm25al73zsuaaa+b000/PIYcc0tA9VVx88cX5+9//Xim75ZZb5oILLkhTU1ODWyVLLLFELr/88my00UaZMmXKfLMvvvhifvazn+Woefz+syAPPfRQpdwnPvGJ9OvXr0c7gJ7p39cFmKtpFTJLJHlxIff8T5KBScok8/tt47aF3DOn+X/H+WcfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFlL3K//I9Ecf6+sava6cPr3X9jTq9S2nTF2o+e6Xxqf7pfF1avOms1/5R0POnZvpzzz9lvwY7s3XiEXXo48+ms985jOV84MGDcoPfvCDBjZiUfPYY4/lhBNOWGDu61//etZcc81eaNR7Xn755crZoUOHNrBJ/Tu88sorDWzy1vH9738/w4YNa/ieVVddNSNGjMh11123wOwtt9xSt73Tpk3LqFGjKuePOOKI7LTTTnXbPy+rrLJKTj/99Bx66KGV8jfddFPGjh2bTTbZZKH2jh07NnfddVel7LrrrpsvfvGLC7Wvqk9+8pO58MIL6/p/X6uZM2fmpJNOqpQdOnRofvWrX2XAgAENbvV/3vWud+Ub3/hGjjvuuAVmzz333Bx11FE92vP0009Xym255ZY9Oh/ouaa+LsBcvVYhs2od9mw/j8fLOd5+qizLzjrsmm3gAp6fVsddAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCrJk+enA9/+MN57bXXKs+0tbVlzTXXbGArFiVlWeaTn/xkJk+ePN/cJptsks9//vO91Kp3zJw5M6+//nql7IABAzJ48OAGN1qwYcOGVc52dXU1rshbxHve857stddevbav6q777rsvZVnWZecVV1yRf/zjH5Wyzc3NOeWUU+qyt4pPfvKT2XTTTSvnL7jggoXe+ctf/rJy9hvf+Eb69++/0Duram9v77Vdc/O73/0uTzzxRKXsKaeckne+850NbvSfPv3pT1fae++992bs2LE92jFx4sRKuZVWWqlH5wM919TXBZirlypk6vHb447zea5IUia5tQ575rSgn+4n1XkfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSaww8/PPfff3/l/Hvf+960tbU1sBGLmrPOOis333zzfDP9+/fPueeem379+vVSq94xbdq0ytnFF1+8gU2qq6VHLff3dnXsscemKIpe2zdixIhKuUmTJuXZZ5+ty84LL7ywcvaLX/xillpqqbrsraIoinzrW9+qnL/kkksyY8aMHu8ryzK/+tWvKmXXXHPN7LXXXj3e1RPbbLNNttlmm17dOaezzz67Um7VVVfNkUce2eA2czdo0KAcc8wxlbKjR4/u0Y7p06dXyvXv379H5wM919TXBZirFytk3rUwC4qiGJZkqyTlAqK3LcyeuRi2gOcn1XkfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSKU089NT//+c8r54cMGZKLL744/fv3b2ArFiVPPvlkvvSlLy0w9/nPfz4bb7xxLzTqXTNmzKicXVQ+L2rpMX369AY2WfQNHTo0e++9d6/uXHXVVbP88stXyj788MMLvW/SpEkZM2ZMpexiiy2Www8/fKF31mrEiBHZYIMNKmUnTJiQm2++uce77rvvvjz77LOVsocffniKoujxrp468sgje31nkjz//PO59tprK2W/8IUv9OnXvE984hMZMGDAAnNV7+fNBg8eXCn3zDPP9Oh8oOea+roAc/VkkplvvF3O5fkiyfYLueMDSWZ/55nfd+dbF3LPmw2fx+OzO0ys8z4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaLjLLrssbW1tNc386Ec/ylprrdWgRiyKDjnkkEyaNGm+mXe96135+te/3juFetn06dMrZ/v379/AJtUNGDCgcraW+3s72nHHHTNkyJBe37veeutVyj3//PMLvesPf/hDZsyYUSn7kY98JEsvvfRC7+yJI488snJ2zJgxPd5z0003VcoVRZH99tuvx3sWRmtra598XF511VWZNWvWAnODBw/O/vvv3wuN5m2ZZZbJ1ltvvcDc2LFj8/LLL9d8/rLLLlspd/XVV9d8NrBwmvq6AP+pLMuZSZ6Y19Nv/LtRURTLLcSajyzg/CR5tSzLBxZix9wMn89zZZKJdd4HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1155135oADDkhZlpVnDj300Bx00EENbMWi5uyzz84NN9ww30xRFDnnnHMyePDgXmrVu6ZPn145279//wY2qa6WHrXc39vRzjvv3Cd73/Wud1XKvfTSSwu9a8yYMZWz++yzz0Lv66m99947TU1NlbK13NOb3XTTTZVym222WYYPH97jPQtjscUWyy677NLre6+++upKuV133TXNzc2NLVPBiBEjFpiZNWtW7rnnnprPXm211SrlLr744rzwwgs1nw/0XLXvFPSFvyQp3vRY8aa3e/STRlEUyybZPcm8fnst3nju1p6cvwBrzWdvkjzTgJ0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0BAPP/xwPvjBD2bKlCmVZzbddNOceeaZDWzFouaZZ57Jcccdt8DcIYccku22264XGvWNWbNmVc7269evgU2qq6VHLff3drTpppv2yd7ll1++Um7ChAkLvev222+vlFt88cWz0047LfS+nlp++eWz9dZbV8red999ef3113u055577qmU68vXIkl23nnnXt03c+bM3HDDDZWyu+66a4PbVFP18/fee++t+eyNNtooRVEsMNfV1ZUDDjggU6dOrXkH0DNNfV2AebpjPs+VSYokXyiKoif/h0cmGfDG2/P76nx9D86ep6IolkqywgL2PlbPnQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQKE8//XRGjBiRCRMmVJ5ZeeWVc8UVV2TQoEENbMai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uxvYhNlGjBiRyy67rHL+nnvuyeuvv97ARrBoaOrrAgDAW8ZySdarw+XnDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgLadrdEc629qSsqx9uCjS0t6e5taRde3U3DoyLe3tSVHUPlyW6WxrS9fojrp2greCsixz5JFH5rzzzqtp7uCDD86Pf/zjFD35nAP+zcCBA7PddttVyr7++uu57bbbGtzoP11//fWVsyNGjGhgExYlG2+8caXcgw8+mGeffbbBbebv2muvrZRbcskls9pqq/Vox7bbblspd91112XGjBk92lEPV155Za/u22ijjbLYYotVyo4ZM6bBbZhtt912y7777lsp293dnXvvvbexhWAR0NTXBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWZV2jO9LZ1paUZe3DRZGW9vY0t46se68kaW4dmZb29qQoah8uy3S2taVrdEfde8Gi7Oijj85Pf/rTmmb+3//7fznnnHNS9ORzjf8qHR0dKctykbmeeOKJyt232267ms4eOXLkQr1WI0aMqJz99a9/vVC7eqKWnTvvvHMDm7Ao2WGHHSpnOzo6GldkAe65554888wzlbLbb799j7+/VX09Xn311dxwww092rGw/vrXv2bcuHG9unPAgAHZcccdK2V/+9vfZtasWQ1uxGxHHnlk5ezjjz/ewCawaGjq6wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi6qu0R3pbGtLyrL24aJIS3t7mltH1r3XnJpbR6alvT0pitqHyzKdbW3pGt1R916wKPrsZz+bs846q6aZfffdNz/72c/S1NTUoFbw36m1tTVFxe9dv/nNbzJz5swGN/o/d999d8aNG1cpu8Yaa2SjjTZqcCMWFSNGjKicvfjiixvYZP4uuOCCytla7unNtttuuwwYMKBS9pxzzunxnoVx9tln98ne1tbWSrkXX3wxv/vd7xrchtm22mqrDBs2rFJ2/PjxDW4Dfc9vOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABz0TW6I51tbUlZ1j5cFGlpb09z68i695qb5taRaWlvT4qi9uGyTGdbW7pGd9S9FyxKPv/5z+eHP/xhTTP77LNPLr744vTr169BreC/16qrrpptttmmUnbC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oqGprwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9JWpf/97OtvakrKsfbgo0tLenubWkXXvVU/NrSPT0t6eFEXtw2WZzra2TP373+tfDBrgnHPOyac//emaZrbddttcddVVGTJkSINaAQuy/PLL5+STT66cf+WVV7LTTjvlj3/840Lv/t73vpfDDjssZcWfBfr165cf/ehHC72Xt77tttsuBx10UOV8d3d3DjrooLS1taW7u7suHX72s59lxIgRee211yrPvPvd787nP//5uuyf01JLLZVvfetbNc18+9vfzi677JKnn356oXa/8MILaW1tzfHHHz/PzODBgxdqx8JYYYUVcsEFF6So4efxCy+8MO9+97tz9dVXN7DZf7rnnntyzDHHZMUVV8yhhx6av/3tb3U7+8UXX8xJJ52UVVZZJR/5yEfyu9/9LjNnzqzb+fPy+uuv52Mf+1guvPDCyjOHHXZYAxvBoqOprwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9JXB666bZT/1qdoHiyIt7e1pbh1Z906N0Nw6Mi3t7UlR1Dy77Kc+lcHrrtuAVlB/p5xySsqyrGnmlltuyRJLLJGiKBap68ADD2zMiwSLqE996lPZcsstK+cnTJiQHXbYIV//+tczZcqUmvc988wz+fCHP5zPfe5zmTVrVuW5z3/+89loo41q3sfb03e/+928853vrJwvyzLf+ta3svnmm+fWW2/t8d7HHnssI0eOzMEHH1zTx//AgQNz/vnnp3///j3ePT+HHnpo9thjj5pmfv/732edddbJ8ccfn2eeeaam2RdffDEnnXRS1lprrXR0dMwzt/jii+e4446r6ex622233fKlL32pppknn3wyH/jAB7LtttvmyiuvTHd3d917dXd357bbbssJJ5yQtdZaK//zP/+TH/zgB+nq6qr7rtlmzJiR3/zmN/ngBz+Y4cOH51Of+lSuvvrqHn0tn59Zs2bll7/8ZTbeeOP86le/qjy3yy67ZMMNN6xrF1hUNea7AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBbxHKfPjpJMmHUqGoDRZGW9vY0t45sXKkGmN23s60tKctKM8seddS/Xh8AaKR+/frl0ksvzcYbb5xXXnml0kx3d3dOOumknHvuuTnmmGOy3377Zfjw4fOdGTt2bC644IKcc845mTp1ak0dt95665xyyik1zfD2tvTSS+eyyy7L+973vkybNq3y3J///Odsu+222W677XL44Ydnt912S3Nz83xnpk2blptvvjnnnXdeRo8enRkzZtTc98wzz8xmm21W81wtzjvvvGy88cZ59tlnK89MmTIlp512Wk4//fRst9122XnnnbPppptmrbXWytJLL50hQ4ZkypQp+cc//pFx48blL3/5S66//vrceOONlV6H9vb2DBs2bGFuqy5OOeWUPPfcc7noootqmrv11ltz6623pqWlJa2trdl9992z1VZbZamllqq5w0svvZS//e1v+dOf/pQ//elPueWWW9LV1VXzOfUyfvz4/PjHP86Pf/zjLLbYYtlqq62yzTbbZOutt86GG26YFVZYoabzuru7c+edd+a3v/1tLrvssjz66KM1zQ8YMCDf+973apqBt7L+fV0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoK8t9+mjkyQTRo2af7Ao0tLenubWkY0v1QCze3e2tSVlOd/sskcd9a/XBQB6w8orr5yLL744H/rQhzJr1qzKc88991yOO+64HH/88Vl33XWz2WabZcUVV0xzc3NmzJiRrq6ujBs3Lvfcc0+effbZHnVbbrnlcumll6Z///49muft673vfW9+/OMf5+CDD6559uabb87NN9+cfv36ZaONNsp6662XVVZZJUOHDk2/fv0yadKkdHZ25qGHHso999yTyZMn97jnEUcckcMOO6zH81Utu+yyueqqq7Lttttm4sSJNc12d3fnxhtvzI033li3PrvvvnuOPvroXHTRRXU7s6eKosh5552XV199NVdccUXN852dnTnrrLNy1llnJUlWXXXVrL322llppZXyjne8I0OGDMngwYPT3d2dadOmZcqUKXn55ZfzwgsvpLOzM4888ki6urrqfFf1M2XKlNxwww254YYb/vXY0ksvnbXXXjvDhw/P8OHDs9RSS2Xw4MEZNGhQpk2blkmTJuX111/Ps88+m4cffjjjxo3LtGnTetzhW9/6VtZdd9163A68JfipBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDJcp8+OkkyYdSouQeKIi3t7WluHdl7pRpgdv/OtrakLOeaWfaoo/71egBAb9p9993z05/+NIcddljKeXyfmpdZs2blgQceyAMPPFDXTs3Nzbnuuuuy0kor1fVc3j4OOuigTJw4MZ/97Gd7NN/d3Z2xY8dm7NixdW72TwcccEBGzetn3AbYaKONctlll+VDH/pQpk+f3mt759bjV7/6VZqamvqsw5v1798/l112WY444oicd955C3XWk08+mSeffLI+xRZRr7zySu64445e2bXffvvl85//fK/sgkXFovPVEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCPLffpo7PsUUf95xNFkZb29jS3juz1To3Q3DoyLe3tSVH8x3PLHnVUlvv00X3QCgD+6ZBDDsmZZ57Z1zWSJEOHDs21116bjTfeuK+rsIj7zGc+kx/84Adpamrq6yr/5qCDDsrPfvazXu+1884756qrrsoSSyzRq3tnW3PNNft0//z0798/5557br7xjW8sch8v/6322muvXHjhhX1dA3qdr0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc1ju00dn2aOO+r8HiiIt7e1pbh3ZZ50aobl1ZFra25Oi+Ndjyx51VJb79NF92AoA/umoo47KJZdckiFDhvRZh9VWWy233nprNt988z7rwFvLZz7zmVx11VVZcskl+7pK+vXrl9NPPz3nn39+mpqa+qTDiBEjcsMNN2TFFVfs1b2bb755br/99qy00kq9urdWX/3qV/OHP/whq6yySl9X+a923HHH5de//nX69+/f11Wg1/XNdwcAAAAAAAAA4P+zY+dxXhX0/sff58sou4oCKm64i5obVrgmIm5p5lWrq2bZNZdfy617M3Npdcm6eW/ZetMstdQ2Q7NcCHA3BQlFUEEwFJTFBRj2Zc7vj6BLxvKdYeb7BXw+H4/zmC/nfM75vL4wwMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAO6/GpT6b7Jz6RFEW2vuqqbHby++ud1CY2O/n92fqqq5KiSPdPfCI9PvXJeicBwN996EMfyqOPPpqddtqp5ruPPvrojBgxIvvss0/Nd7N+O+644/Lkk0/mPe95T90adt111wwdOjT/8R//UbeG5d71rndl1KhROeGEE9p8V1EUOe+88zJ06ND06NGjzfe1hsMOOyxPPfVUPv3pT2ejjTaqd85K7brrrjn33HPrndHqevXqlTvvvDPf/OY3U6lU6p0DdeEzHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAlenzqk9nx9t9ms5PfX++UNrXZye/Pjrf/Nj0+9cl6pwDAP9l3330zevToXHrppWnfvn2b79tqq61y00035d57783mm2/e5vvYMO28884ZNmxYrrvuumy55ZY129uxY8dceumlefrpp3P44YfXbO+adO/ePb///e9z6623pnfv3m2yY/fdd8/QoUPzox/9KJ06dWqTHW1l0003zXe+852MGTMmp556aiqVSr2T0q1bt3zsYx/LsGHDMm7cuJx77rktftYtt9yS8847L9ttt10rFrZcx44dc+GFF2bs2LE58cQT650DdVX/f20AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1lEd+vSpd0JNvF3eJwDrp06dOuWKK67IM888k3POOScdO3Zs9R1bbbVVvvKVr+T555/Phz/84VZ/Pm8/RVHknHPOyYsvvphrr702O+ywQ5vt2nTTTfOFL3whkyZNyhVXXJEOHTq02a618aEPfSjPPfdcfvjDH+Yd73hHqzzzXe96V379619n7NixOeKII1rlmfWy66675te//nUmTJiQCy+8MN27d6/p/u222y7nnntu7rrrrkydOjU/+clPWuX39Pjjj8+PfvSjvPTSSxk1alSuvPLKHHLIIdloo43WProZtt5661x22WWZMGFCvvnNb2bTTTet6X5YFxVlWda7AQB4GymKYnaSrqu63rVr18yePbuGRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwj5YuXZpx48ZVPb/bbrulXbt2bVgEAMCKXn/99dxwww0ZNGhQHn/88SxdurRFz+ncuXP69++fD37wg/nABz6QjTfeuJVL4f80NTXlwQcfzC233JLf//73mTp16lo9b5NNNslRRx2Vf/3Xf80JJ5yQDh06tFJp7Tz++OO56667cu+992bUqFFZvHjxGu/p3r179ttvvxx//PE58cQTs8suu9SgtD6WLFmSBx98MHfccUfuvvvujB8/vtWeXRRFdtxxx/Tr1y+HHXZYDj/88Oy5556t9vxqLFiwICNGjMif//znvx9Tpkxp1R277LJLjjnmmJx00knp379/GhoaWvX5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N988e++9d0466aR89atfzbRp03LDDTfk29/+dqZPn97sjiFDhuRb3/pWLrroopa+lbq65ZZbcvbZZ6epqanqe4qiyDXXXJOzzz4773//+/PAAw9Ufe+ECRPSv3//PPDAA9l6661bkgwAAG97lXoHsFI7JimWvS5WMVP9d0/rlnlruN61JhUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwFpqayoz600u57YonMnXirHrnrNarE2bltiueyKg/vZSmprLeOVB3Xbp0yVlnnZU//vGPefXVV3PTTTfljDPOSI8ePVr8zC233DIXX3xxJk6cmIsvvjgNDQ3NfsaXv/zlPPfccy1uqJdf/epXOeuss9LU1FT1PRtvvHFuvfXWfPazn81mm22We++9Nx/4wAeatXf8+PE58sgjM23atOYmr7cqlUr69OmTM888M/379693Ts19+ctfTlmWdT2uuOKKev82AAC0mkq9A1ip3lXMjG7riDaycA3X29ekAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFpo5rR5+d23RuaR37yQpYub6p1TlaWLm/LIb17IoGtGZua0efXOgbrYa6+98t3vfjdTpkzJjTfemOOOOy4NDQ2tuqNz58656qqr8tBDD2Xrrbdu1r0LFy7MpZde2qo9be3222/PGWeckaVLl1Z9z6abbpp77703H/zgB/9+rn379rntttvymc98pln7n3vuuRx55JGZMWNGs+5bH1Qqleyxxx4588wz8z//8z958MEHM2vWrIwdOzY333xzDj/88HonAgCwnmvd74ZoLZtWMTOxzSvaxqI1XN+4JhUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAuNHTMvQG5/NksVN9U5pkVcnzMovr3giR36kT3Y9cMt650BNHHHEEbn44otz9NFH12xnv3798uc//zn9+/fPxIkTq77v9ttvz6hRo7Lffvu1XVwrueOOO/KhD30oS5YsqfqebbbZJnfffXfe8Y53/NO1oijyP//zP9lmm23y+c9/PmVZVvXMsWPHZsCAARk6dGi6d+9edcu6pFKpZLfddkvfvn1z4IEHpm/fvtl///3TpUuXeqcBALABa6h3ACvVuYqZmW0d0Ubar+H60ppUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDONvn9yHvzluKSsd8naWbK4Kff9ZEwWzl2cvd+zbb1zoM0ce+yx+fKXv5x+/frVZf/222+fP/3pT3nXu96V1157rer7/vd//zc//OEP27Bs7f3hD3/IBz7wgSxevLjqe/bcc8/cc8892W677VY797nPfS69evXK2WefnUWLFlX17NGjR2fgwIEZMmRINt9886qb6qFSqWS33XZL375907dv3xx44IHZf//906VLl3qnAQDwNlOpdwAr1WlNA2VZzq9FSBvouIbr6+v7AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAP25D1/zYO3jUvKepe0kjJ54NZxefKev9a7BFpdv379cv/99+fuu+9Ov3796tqy44475uc//3mz7rntttuycOHCNipae/fee29OOeWULFq0qOp7DjvssDz88MPZbrvtqpo//fTTc/fdd2eTTTapeseoUaMycODAzJw5s+p7au2ee+7JrFmz8uyzz+bnP/95PvvZz+awww5Lly5d6p0GAMDbUKXeAazUGr8bLIqiQy1C2kD3NVyfX5MKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqNKT9/w1fx40sd4ZbeLPgybmyXv+Wu8MaDXHHXdcHnvssbznPe+pd8rfHXPMMTn99NOrnp85c2YeffTRNixquT/96U95//vfn4ULF1Z9zymnnJL77rsv3bp1a9auI488Mg8++GB69epV9T0jR47M0UcfndmzZzdrV63069cvXbp0qXcGAAAkSSr1DmCl5lUx07nNK9rGtmu43liTCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKjCMw9Mzp8HTax3Rpv686CJeebBKfXOgFbRuXPneies1Fe/+tVUKpWq54cNG9aGNS0zbNiwvO9978uCBQuqvudTn/pUfvWrX6VDhw4t2rnvvvvmscceS58+faq+Z/jw4Tn22GPT2NjYop0AAPB2Uf13KNTS3Cpmtmnziraxc5JyJeeLZecn1zYHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVm78iGl54LZx9c6oiQdufT7jR0yrdwZssHbZZZcceeSRVc8PHz68DWua76GHHsqJJ56Y+fPnVzVfFEWuvvrqXHvttalU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A97qvvvuy957753LLrss06dPb9VnT58+Pf/5n/+ZAw88ME8//XSrPrs1LFmyJD/96U/Tp0+fnHLKKRk0aFAWLlzYas8vyzIPPfRQLrjggvTu3TtXXnllZs+e3WrPb01DhgzJnnvumc9//vN54403WvXZEyZMyPnnn5+DDz44Y8aMadVn19LixYvz05/+NHvuuWfe+9735uc//3kaGxtbdcczzzyTiy++ODvssEO+8IUvZObMma36/JaYMmVKzj333Gy33Xa57LLLavJn+Oqrr+Z3v/tdzjvvvGy99dY56qij8r//+7+ZM2dOm++GdUml3gGs0iNruF4k+UQtQlrJp1dzrUhSJhlSoxYAWqAoik8URTFmbY8knev9XgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmb0sMmZOnFWvTPWCa9OmJXRwybXOwM2OI2NjVXPdunSpQ1LVm7MmDE56qij8vrrr1c1/773vS9DhgzJFlts0cZlK3fMMcfk/vvvz5ZbblnV/F133ZUPfvCDWbx4cRuXAUmydOnS/Pu//3uOOeaYvPjii22666mnnsrBBx+c3/3ud226pzmGDx+ed77znfnYxz6WcePGtfm+1157LZdddln69OmT3/72t22+r1pLly7NpZdemqOPPjoTJ05s012PP/54DjjggNx4441tuqctDB48OHvttVc+9rGP5bnnnmvzfY2NjfnGN76RPfbYI7fddlub71uZsizzne98J7vttluuu+66uv3/vHTp0gwZMiTnn39+RowYUZcGqJdKvQNYpaFJlix7Xa5wvljh1/sXRXFSTataoCiKPklOzz++j5W5owY5ALRcjyR7tsLh6w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYJ2zcN7iPHHXi/XOWKc8cdeLWThvcb0zYIOxePHizJ49u6rZdu3apUuXLm1c9I+effbZDBgwIDNmzKhq/rzzzsvtt9+ejh07tnHZ6vXt2zePPvpodt1116rmBw0alNNPPz1Llixp4zJ4e5s1a1be+9735tprr63Zzrlz5+bUU0/NbbfdVrOdK9PU1JRLL700/fr1y6hRo2q+/5VXXsmpp56aU045JY2NjTXfv6L58+fn5JNPzlVXXZWmpqaa7Fy0aFE++tGP5oorrqjJvrU1a9asnH766Tn66KMzfvz4mu+fNm1a/vVf/zWnn3565s2bV7O9s2bNynHHHZfPfOYzNd0L/KNKvQNYubIsX08yNEmxqpFl175VFEV9vyNbs+/n/z7XVnw/5QqvFya5u2ZFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsILnHpuaRfOX1DtjnbJo/pI899jUemfABmPMmDEpy7Kq2d69e6dSqbRx0f8ZN25cBgwYkGnTplU1/7WvfS0/+tGP0q5duzYuq85OO+2URx99NO9+97urmv/Nb36TM888M0uXLm3jMnh7amxszMCBA3PvvffWfHdTU1POOuus/OlPf6r57iSZNWtWTjjhhFx11VVpamqqS8Nyt99+e/r165fx48fXZf+cOXNy7LHH5ve//31d9n/xi1/MlVdeWZfd1Ro9enTe+c535tZbb613Sm699dYcfPDBefnll9t814wZM3LIIYfU5d8I4B/V7jsOWuJXqzhfrPB6pyT/XYOWFimK4tNJjkhS5h+7/z6y7Npvy7KcW8M0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASJKUTWVGPzC53hnrpGcenJKyLOudARuEESNGVD272267tWHJP5owYUKOPPLIvPrqq2ucbWhoyA033JAvfvGLNShrnu7du2fo0KE54YQTqpr/5S9/mY985CNpampq4zJ4e1mwYEHe9773Zfjw4XVrWLx4cc4444xMnTq1pnvfeOONvOc978ndd99d072rM3bs2Bx88MEZPXp0TfcuWbIkp512Wh588MGa7n2rL37xi7ntttvq2rAq99xzT/r165fx48fXO+XvnnrqqRxxxBF5+eWX22zHnDlzcuyxx2bMmDFttgOoXkO9A1it25J8I8nmScokxQrXihXOnVsUxTNlWX6/9omrVhTFgCTfyt861+R7bZwDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKzX5+Tcza/r8emesk2ZOm5fJz7+Z7fbYvN4psN678847q55917ve1YYl/+fFF19M//79M2XKlDXOdu7cOb/+9a9z3HHH1aCsZTp16pRBgwbl/PPPz/XXX7/G+V/84hdpaGjIDTfckEqlUoNC2PCdc845uf/++6ua3WSTTXLAAQdk5513Tq9evdK5c+e0a9cuc+fOzZQpU/L8889n+PDhmT+/+V+nTZ8+Peeff34GDRrU7HtbYubMmRk4cGCeeuqpmuxrjtdeey0DBgzIsGHDstdee9Vk5//7f/8v99xzT4vv32qrrbL//vtn9913z+abb55OnTpl3rx5mTlzZsaNG5dRo0Zl8uTJa3xOWZY5++yzs88++7S4pS3ceeedOe2007Jo0aJ6p/yTiRMn5ogjjsijjz6aLbfcstWf/8lPfjIjR45s9ecCLdNQ7wBWrSzLeUVRfC/Jl5OUqxpLUiT5TlEUi8qyvK5mgatRFMXhSW7P3z7HljeuaPm5MskTZVk+XttCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+JtnHphS74R12jMPTMl2e2xe7wxYr82aNSv33Xdf1fNHHHFE28UsM2nSpPTv3z8vv/zyGmd79uyZu+66K+985zvbvGtttWvXLtddd1222WabfPWrX13j/I033piGhoZcd911KYqiBoWsrYULF2bkyJEZPnx4Ro0alRdffDF//etfM2vWrMydOzdNTU3p2LFjOnbsmK5du2abbbbJtttum969e2ffffdN3759s9NOO/nzbgPXX399fvGLX6x2Zuutt86HP/zhfOADH8j++++fSqWy2vlFixbl7rvvzve///0MHjy4WT133HFHhgwZkgEDBjTrvuZaunRpTjnllIwcObJF92+55ZY59thj079//+y5557p3bt3unbtmnbt2qWxsTFTp07Ns88+m0ceeSR//OMf8/zzzzd7x4wZM3LcccflySefTI8ePVrUWa2bb7451113XbPv23zzzfOxj30sZ555Zvbdd981zo8ZMya33nprrr/++kybNm2VcwsWLMjZZ5+dc889t9lNbeG+++7LqaeemsWLF7fo/v322y/vec97cuCBB2aXXXbJ9ttvn0022SQdO3bM4sWL09jYmEmTJuW5557Lww8/nLvuuitTpjTv+52JEyfm1FNPzdChQ7PRRhu1qHNl7rnnntx4440tunf33XfPgAEDsscee2TnnXfOTjvtlK5du6Zz587p3LlziqLIwoULM2/evLz22muZMWNGXnzxxYwfPz5jx47N8OHDM3ny5FZ7L7ChaKh3AGt0bZLPJNkkSZlkxa9gl78uk1SS/Kgoil2SXFyWZVMtI1dUFMWHklyfpFP+uXllLmnzKABaw4wkY1vhOXvkb/9vAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADU3Zw3F+TFp2bUO2Od9uJTr2XOmwvSpVuHeqfAeuvHP/5xFi5cWNXsZpttloMOOqhNeyZPnpwjjzwykyZNWuPszjvvnHvvvTc777xzmza1tq985SvZdtttc/7552fp0qWrnf3JT36ShoaG/PCHP0xRFDUqpLkeeuihvO9978vQoUMzd+7c1c42NjamsbEx06dPz4QJE/7p+hZbbJFjjjkm733ve3P88cdns802a6Pqt4+//vWv+fSnP73K61tssUUuv/zyfOxjH0v79u2rfu7GG2+ck046KSeddFLuu+++nHPOOXn55Zervv+SSy7J448/XvV8S1xyySUZOnRos+/bf//9c/HFF+fkk09OQ0PDSmc233zzbL755tlzzz1zyimn5L//+7/z8MMP57/+679y5513Nmvfyy+/nA996EO577770q5du2b3VmPixIn5xCc+0ax7Ntpoo3z2s5/NZZddlq5du1Z931577ZUrrrgil112Wb75zW/m6quvzvz581c6+8QTT1T9/3Bbev755/PBD34wixcvbtZ9vXr1ynnnnZezzz4722233Srn2rVrlw4dOqRHjx458MADc+aZZ6YsywwZMiRf//rXm/V5+vDDD+ezn/1svve97zWrdVXKssxFF13UrHt69OiRf//3f8+ZZ56ZHXbYYY3zDQ0N6dy5c3r06JE+ffrk8MMP/4frr776aoYMGZI//elPueuuu/L66683qwc2RJV6B7B6ZVm+meSyJKv7LqVIUi77+LkkjxRFsU8N8v4xoii2KIrihiS/SNJpWdPKLG8tk/yxLMthNUoEYC2UZfn9siz3Wtsjyep/ogMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUENjHn4lZVnvinVb2VRm7MOv1DsD1luLFi3KtddeW/X8aaedlvbt27dhUbLttttmwoQJKctyjccLL7yQnXfeuU172so555yTJUuWVPU+f/SjH6UoinonsxpDhw7N73//+8ydO3etn/X666/nlltuyRlnnJFevXrlox/9aB577LFWqHz7mjRpUubPn7/SayeddFKee+65XHDBBWv179vRRx+d4cOH54ADDqj6nieeeCKPPvpoi3euyeDBg/PNb36zWfd06tQpP/rRjzJixIicdtppaWho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58+vavaQQw5Zq12toTkNTz31VLOfP2bMmKpnDzzwwGY/vzXtvffead++fc32jRw5sqq5zp07Z/fdd2/jmupsvfXWqVTW/D3SpEmTWvT80047rerZhx9+OHvssUf+8z//s8X7gOr4ycjbRPk3T5Rl+d2yLM8uy3K/siw3SdItyTuSDEhyQpLTkpyV5IwkJyc5NslBSbZN0qEsy93KsvxgWZbXlGX5SFmWS+vzjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKDl2jVU6p2wXioqRb0TYJ3w2muv5aijjsoLL7xQ9T3dunXLfffdl912260Ny4CW+vrXv54jjzyyWfd8//vfb6Oa9c/WW29dt93t27evam7hwoVrtee5556renafffZZq12tYd999616tjnvbbmJEydWNbfppptmq622avbzW1O7du2yyy671GzfX/7yl6rmdtttt1Qq68b3JQ0NDdl0003XODdlypQWPf+cc87JxhtvXPX8vHnz8t///d/ZaaedMnDgwFx//fWZMWNGi3YDq7Zu/AtE3ZRlOassyzFlWQ4ry/KPZVn+tizLn5dleWtZlneUZXlfWZaPl2X5SlmWZb17AQAAAAAA4P+zY9/hcpZ1/sc/z+SkN0pCSKihJPRQlKYQioBUYbFQVhSVpiyiwqKUn+KKCIiCKKwgIOiiYtYFDCLSEqlKCEhbCEgNCb0kIf2c5/fHJhqQJHOSM/OcmNfruuY6c2a+932/n8nkNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgI7Q0rVWdcIyqVYrqk6Ayr355pvZfffd88gjj9S9pm/fvrnhhhsyYsSIBpYBS6NLly75yU9+kp49e9a95tprr83s2bMbWLXs6NWrV2VnF0V9P5+UZblU57zwwgt1z26wwQZLdVZHWHXVVbPCCivUNduea5tv8uTJdc2tt9567d67EYYNG9a0s/7617/WNbfWWms1uKR96vn6N2nSpCXae9CgQTn22GPbva6trS0333xzjjjiiAwaNChbb711Tj755Nx0002ZNm3aErUAf+cvIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMByp0efrlUnLJNautWqToBKTZ06NR/+8Idz//33172mV69eGT16dLbZZpsGlgEdYejQofnyl79c9/xbb72V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lO985zsNqgI6g+eee67u2d69ezewhM5irbXWqnv2sccea2BJfZ588snMnTu3rtn2XNt8G264YV1zbW1tefTRR9u9f0d6+eWX88orrzTtvKFDh9Y1156vM9SvKIrsuOOO+elPf5pnn302xx57bGq1Wt3r33777Vx22WUNLITOo/7/GXR6RVF0K4riiKIoxid5NMkpSbZM0iVJscCtXIpb8a7bKkk+kWRUkpeKorioKIrhzbheAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6AhFrcgmO65WdUantMmOq6UoiqozoCHa2try2c9+Nj/72c/ate7YY4/N9773vQZVAZ3Fk08+Wffs6quv3sASOotNN9207tk///nPDSzp+Ib2XNt86623Xnr06FHX7F133dXu/TvS3Xff3dTztthii7rmpk6dmqeffrrBNcu3QYMG5YILLsjvf//79OrVq+51o0aNamAVdB61qgNYekVRdC+K4mtJnkvyn0k2T1LMuyVJ+a7b35a28/Zee5ULPN8/yZFJHimK4tqiKDbr+KsFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAjrfBdqumW8+WqjM6lW49W7LBdqtWnQENUZZljjzyyPz0pz9t17qjjjoqP/jBDxoTBXQab7zxRp544om654cOHdrAGjqLlVdeOUOGDKlr9s4772xwTcc2jBgxot3712q1bLzxxnXN3n777e3evyM1+/ytt9667tl77723gSXMt9tuu2XUqFF1z48bNy5vv/12A4ugc6hVHcDSKYriE0keT/KtJKskKeY9VS5wy7zH331r93EL2WPBs4r83/tqnyT3FUXx46IoBi7BWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANA03Xt1zdb7DK06o1PZep+h6d6ra9UZ0OHKsswxxxyTSy+9tF3rPvOZz+Siiy5KURQNKgM6i7Fjx6Ysy7pmW1passYaazS4iM5iiy22qGvu0UcfzcSJExtcs2i///3v65rr379/hg5dsp+Dd9hhh7rmbrzxxsyZM2eJzugI1113XVPPGzFiRHr27FnX7E033dTgGubbc889c/DBB9c129ramgceeKCxQdAJ1KoOYMkURbFyURTXJLkqyZpJiiTlArfiXbeGpbzrjAXP75Lkc0keKYpi3wY2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwFLbdOfVM3jd/lVndAqD1+2fTXdeveoMaIhjjz02P/7xj9u15pOf/GQuueSSFEXRoCqgM7n66qvrnh0xYkS6du3awBo6k1122aXu2WuuuaZxIYsxbty4PP/883XN7rzzzkv8/a3e1+Ott97KLbfcskRnLK0HH3wwTzzxRFPP7Nq1a3bddde6Zn/729+mra2twUXMd8wxx9Q9+9RTTzWwBDqHWtUBtF9RFDsmeTDJvkmKJOW8W+Z9XtVvrQuePb+pSDIgyTVFUfywKIouFbUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAItVqRXY5bMN06VqrOqVSXbrWssthG6ZWK6pOgQ73xS9+MRdeeGG71hx88MG5/PLLU6st318bYHnx2muv5dprr617fvvtt29gDZ3NbrvtVvfsz372swaWLNpPf/rTumfbc03vNnLkyHTt2rWu2UsuuWSJz1kaF198cSXnHnDAAXXNvfTSS7n++usbXMN822+/ffr161fX7CuvvNLgGqie33CWMUVRHJzkxiSDkxRJyvlPzbt1Bgu2lPNuRZJjklxfFEWfqsIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgUVYY1CvbfmSdqjMqte1H1skKg3pVnQEd7itf+Up+8IMftGvNxz72sfzsZz9Lly5dGlQFdDbnn39+pk+fXvf8jjvu2MAaOptNN900q622Wl2zf/7znzNu3LgGF/2jadOm5Wc/+1nd83vssccSn9WvX7/svvvudc1ed911efbZZ5f4rCXx5ptvtuu16Ej77bdfWlpa6po9//zzG1zDfF26dMnqq69e12x7vhfAsqpWdQD1K4riuCQ/T9I9STnvVsy71aPswFtdyQu0zW/dLcnYoij617kHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANNVmu6yRwev2rzqjEoPX7Z/Ndlmj6gzocF/96lfzve99r11rDjjggFx11VXp0qVLg6qAzubZZ5/NueeeW/d8r169sueeezawiM7okEMOqXv2jDPOaGDJezv//PMzZcqUuma32267rLvuukt13sEHH1zX3Ny5c/PNb35zqc5qr7PPPrvu16KjDRgwIAceeGBds7fccktuuummBhcxX79+/eqa69atW4NLoHq1qgOoT1EUn0zy/SRFknL+w3UsLRe4zV+ztLf32neR+Qt0F0k2TzK6KIoedawFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACApqrViuxy2IZp6VqrOqWpWrrWssthG6ZWK6pOgQ512mmn5ayzzmrXmn333Te/+tWv0tLS0qAqoLNpa2vLEUcckenTp9e9Zu+9907v3r0bWEVn9KlPfaru2WuuuSZ33313A2ve6dVXX80555xT93x7rmVhPvKRj6Rfv351zV5xxRUZP378Up9Zj6effjrnn39+U85amOOOO65dszNmzGhgDfNNnjy5rrm+ffs2uASqt3z91WMZVRTFTkkunfdpOf/hxSwr3zVbJGlLcn+SS5KckGS/JFsnGZpkxSS9knRJ0j1JvySrJtk0yS5JPpvk7CS/S/L6AnsWC5w1/7yFXsq8mSLJ9kl+vph5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqMQKg3pll09tmBRVlzRJkezyqQ2zwqBeVZdAh/rmN7+Zb33rW+1as9dee2XUqFHp2rVrg6qAzuiUU07JTTfd1K41RxxxRINq6Mw23njjbLfddnXPH3nkkZk9e3YDi/7uC1/4Qt566626Zvv165eDDjpoqc/s06dPjjrqqLpmW1tbc/jhhzf89SjLMp/97Gczffr0hp6zONtvv33d75XHHnssX/ziFxtcxLRp0/LCCy/UNbvWWms1uAaqV6s6gEUrimLlJD9P0jL/oSz6T1XlvNv8uTeS/CTJPkn6l2W5VVmWR5Vl+b2yLEeXZTmuLMtny7J8qyzLmeX/mVOW5bSyLF8uy/KRsizHlGV5eVmWXy3Lcp+yLAcm2TjJ15Lc+66mcnGXtEDfAUVRfL69rwkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0w/rvG5SRBw2rOqMpRh48POu/b1DVGdChzjrrrHz9619v15rdd989v/nNb9KtW7cGVQFJ8uKLL1ad8A5nn312vvOd77RrzZZbbpnddtutQUV0dqecckrdsw8//HBOOumkBtb8nyuvvDJXX3113fPHHnts+vfv3yFnf/GLX0zXrl3rmn3wwQfzhS98oUPOXZhTTz01t912W0PPqNe5555b9+wll1ySs88+u4E11Zg7d27VCX/zi1/8ou6ejTfeuME1UL1a1QEs1kVJhiQp65idP1MkeSTJp5KsVpblkWVZ/q4sy+kdFVWW5f+WZXlWWZbbJNk8yWVJWuedXdbRW86b/W5RFOt1VBcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0pE1Grp5t91+n6oyG2nb/dbLJjqtVnQEd6vvf/36++tWvtmvNrrvummuuuSbdu3dvUBUw3+abb55/+7d/y6RJkyrtaG1tzYknnpiTTjqp3WtPPfXUBhSxrNh7772z5ZZb1j1/3nnn5bLLLmtYz1133ZUjjzyy7vnevXvnS1/6Uoedv9pqq+WYY46pe/4nP/lJzjjjjA47f0E//vGP8+1vf7shey+J7bbbLgcddFDd8yeddFK+853vNLCofcqyzLXXXtuuf99323LLLXPBBRdk5syZHVjWftOnT8/3vve9umbXXnvtrLXWWg0ugurVqg5g4Yqi2CHJR5OU8x9ayGg571YkeTnJYUk2K8vyZ2VZzmp0Z1mWD5Zl+bkkGyW5boHOciFLFryO7knObmAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALJWtPrx2tt1/naozGmLb/dfJVh9eu+oM6FA/+tGP8uUvf7lda3baaadcd9116dmzZ4OqgAXNnDkzP/zhDzN06NB86lOfyvjx45ve8NRTT+VDH/pQvvvd77Z77R577JEDDjigAVUsS773ve+1a/7II4/MFVdc0eEdd955Z/bcc8/MmjWr7jWnnXZaBgwY0KEd3/jGN7LyyivXPX/qqafmq1/9atra2jqs4eyzz87RRx/dYft1lPPOOy+rrLJK3fNf+9rX8ulPfzrTpk1rYNWiTZ8+PT/5yU+y2WabZf/998+99967xHs999xzOe6447L22mvnG9/4RiZPntyBpfX7/Oc/n8cee6yu2b333rvBNdA51KoOYJHOWeB+sZCZcoHnRyXZuCzLn5dlWS5kvmHKsnyyLMv9kxySZP53sIV1FPOeK5J8pCiK7RpfCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEtmqw+vnZEHD0uKqks6SJGMPGR4tvrw2lWXQIe65JJL8m//9m/tWrPDDjtk9OjR6dWrV4OqgIWZPXt2rrzyymy11VZ53/vel/POOy8vvvhiQ8984403cuqpp2bTTTfNmDFj2r2+Z8+e+dGPftTxYSxzRo4cmcMPP7zu+dbW1hx++OE5+eST09ra2iENl19+eXbbbbdMmTKl7jWbbrppvvKVr3TI+QtaccUVc+aZZ7ZrzVlnnZU99tgjzz333FKd/eKLL+aAAw7ISSedtNCZHj16LNUZS2PQoEH56U9/mqKo/5eJK664Iptuuml+97vfNbDsH40bNy7HH398VltttRxxxBF5+OGHO2zvl156KaeffnrWWmutfPzjH8/111+fuXPndtj+C/P222/noIMOyhVXXFH3miOPPLKBRdB51KoO4L0VRbFNkq2TlFn4n6LmP1ckOa0sy4+XZfl6kxIXqizLXybZLskz8x+qY9lxDQsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACADrDJyNWz+2c3TkvXWtUpS6Wlay27f3bjbLLjalWnQIc744wzUpZlu9bcfvvt6dOnT4qi6FS3T3/60415kajUT3/60w55f5x++ul1n3n44Yd3yJljxoxp3AuT5L777suXvvSlrLbaatlmm21y+umn54477siMGTOWeu+2trbceeedOfLII7PWWmvljDPOyPTp05dor4svvjjrrrvuUjfxz+G73/1u1lhjjbrny7LMmWeemW222SZ33HHHEp/717/+Nfvvv38+85nPtOv/SLdu3XLZZZelpaVlic9elCOOOCL77bdfu9bcfPPN2WCDDXLSSSfl+eefb9fal156KaeffnqGDRuWa665ZqFzvXv3zoknntiuvTvannvuma9+9avtWvPMM89k7733zg477JDrrrsura2tHd7V2tqaO++8M6ecckqGDRuW97///Tn//PPz5ptvdvhZ882ZMye//vWvs88++2TIkCH5/Oc/n9/97ncd8vV+QW1tbbnqqquyxRZb5Fe/+lXd6/bYY49sttlmHdoCnVVjvhvQEY5ZzPNlkmLexxPKsvx+45PqV5blo0VR7JxkbJI18/fefxid9/gBRVGsUpbly03MBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgHZZ/32DMnCNvrnliv/Ni0+9VXVOuw1et392OWzDrDCoV9UpAPCe2tra8uc//zl//vOf841vfCMtLS3ZbLPNsskmm2T48OFZf/31s+qqq2bQ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s+qkv5k9e3YOPfTQjBo1qpLz29racvLJJ2f8+PH5r//6r3Tr1q2SDgCARmmpOoBFOmCB+8UC98sFPv6kIw8siqJbkh8u5NwOOSJ/7x+Q5MdJ9u3gMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAyZVtbnnv4wTzwh9H567g/pyzbGnbWaxOfy2sTn8uf/udXWXerbbL57ntnzU02S1GrNexMoGP86U9/yo477pg//OEPWW211arO6TAXX3xxjj322A7fd+LEidl5550zduzYrL322h2+//Ju9OjR2WOPPTJ69Oj069ev6pzMmTMnH/vYx3LddddVnZJRo0Zlzpw5GTVqVFpaWqrOAQDoMP5y0Llt/x6PlQvcb03y3x185heSrD3vnGIxs+VibgtTLLD/XkVRHLh0yQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC9mW9Py33XX5vLv3xMRp1xap68956UZVtTzi7b2vLkvXdn1Bmn5vIvH5P7rr82M9+e1pSzgSX36KOPZo899shbb71VdUqHuOyyy3L00UenLMuG7P/cc89l5513znPPPdeQ/Zd3t99+e/bff//MmTOn0o62trYceuihue666yrtWNC1116bQw89tGHvbQCAKrRUHcB7K4qid5KNk7zXT5/FvMfHlmX5egee2TXJVxZy5rvNnymWYqac99y3iqL4TeknbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJZBbW2tuf+G0bl71FWZNf3tqnPyxuQXMubKS3L3qKuy3UcPyRZ77pNarUvVWdDpFUWRddddN+973/uy5ZZbZp111snaa6+dIUOGpHfv3undu3fmzp2bt99+O5MmTcpf//rXjB8/PrfcckvuueeetLa2LtG5jzzySA488MDceOON6dJl2f2/euWVV+aII45IWZbtWrfKKqvk5Zdfrnv+mWeeyS677JKxY8dmtdVWa2/mMqNWq2WDDTbI+973vmyxxRYZOnRo1l577QwaNCi9e/dOr169MmfOnEybNi0TJ07ME088kXHjxuXmm2/O/fff3+5/h/luu+22HHnkkbn88ss7+Irqd8YZZ+TXv/51u9e1tLRkjz32yJ577pn3ve99WXPNNbPiiiumLMu88cYbeeaZZ3Lffffl+uuvz80339zu/7NXX311Nt1005x66qntbgMA6IyKJf2hkcYqimJkktuSlEmKBZ6a/3mZ5N/Lsjy3A8/8ZJIr3uPMBc1/wxRJ3kry30luSPJskilJBicZnuSwJNu/a/699pp/LYeUZfmrpb8KADq7oiimJOm7sOf79u2bKVOmNLEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6ptbU1EyZMqHt+2LBh6dKlSwOL6Mxen/RCbrzovEya8L9VpyzUkOEbZY+jv5iVhqxWdQo03KhRo/Kxj32s7vkBAwZkzz33zB577JHdd989AwcOXKJzX3rppVx22WU577zz8vLLLy/RHt/5zndy0kknLdHaql111VX55Cc/mba2trrXFEWRc889N4cffnj233//jB07tl1nrr/++hk7dmwGDx7c3tym+e53v5sTTzyx7vnVV189e+21V/bYY4/suuuu6d+//xKd+/TTT+fiiy/Oj370o0ydOnWJ9vjlL3+ZT3ziE0u0dmncdttt+dCHPtSu91K3bt1y9NFH5+STT86gQYPqWjN58uScccYZufjiizNnzpy6z+rSpUtuvvnm7LTTTnWvATqHMWPGZOedd17s3MiRIzNmzJjGB0EDLA9/z+jXr9/ifr6ZWpZlv2b1LOtqVQewUNvWMXNTB5/5ucU8XyYp5t1+mWRYWZafK8vyv8uyHFeW5YSyLMeWZXlxWZYfTLJrkpcWWLsoX1iqcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiitrbWjBv9P/nZv/9bJk3436pzFmnS44/mZ//+b7nv+mvS1tZadQ5Urk+fPjnssMPyu9/9LpMnT86VV16ZQw89NAMHDlziPQcNGpSvfe1reeqpp/K1r30tLS0t7d7j61//eh577LElbqjK1VdfncMOOyxtbW11r+nWrVt+8Ytf5Etf+lJWWGGF3Hjjjfn4xz/ernOfeOKJ7LLLLnnppZfam9yprLzyyjnmmGPyxz/+Mc8991x+/OMf51/+5V/Sv3//Jd5z6NChOfPMM/P000/niCOOWKI9vvCFL+TVV19d4oYlMWXKlBx66KHtei9tsMEGGT9+fM4///wMGjSo7nWDBw/OD3/4w4wbNy7rr79+3etaW1tzyCGHZMqUKXWvAQDorGpVB7BQI97jsXKB+9PKsnywow4rimKdJDvMO6NYyNnFvI8XlWV5SFmWryxqz7Isb0uyVZKJC+zxjmMX2PcDRVGst+RXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM3x+qQX8quvfzVjf3Zp5s6ZXXVOXebOmZ0xV/4kv/rG1/L6pBeqzoFKbLzxxrngggvywgsv5Iorrsiee+6ZlpaWDj2jd+/e+fa3v53bb789gwcPbtfaWbNm5ZRTTunQnkb7zW9+k0MPPTStra11r+nfv39uvPHGfOITn/jbY927d88vf/nLHH/88e06/7HHHssuu+ySV155pV3rOoNtttkmV1xxRSZOnJgLL7wwO+ywQ4qi6NAzVl555Vx88cW57rrr0q9fv3atfe2113LmmWd2aM/ifP3rX8/kyZPrnh85cmTuvffebLzxxkt85mabbZZx48blAx/4QN1rJk+enG984xtLfCYAQGdRqzqAhVprIY8XScok93fweR9dxHPlAufem+TYejcty3JykgOSzFpgr4XZv959AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAqP3fXH/Oyk4zJpwv9WnbJEJj3+aH520nF57K4/Vp0CTbPTTjvlxhtvzMMPP5xjjz02/fr1a/iZ2267be65556ss8467Vr3m9/8Jg888EBjojrYtddem4MOOihz586te81qq62W22+/PTvttNM/PFcURb7//e/nnHPOSVEUde/56KOPZtddd82rr75a95qqFEWRj3zkI7nnnntyzz335LDDDkuPHj0afu6+++6bP/7xj1l55ZXbte7CCy/Miy++2KCqd3r44Yfzwx/+sO75bbfdNqNHj06fPn2W+ux+/frlhhtuyPvf//6611xwwQV55JFHlvpsAIAq1aoOYKHWTlIu4vkHOvi8f6lz7itlWS6q6x+UZTk+yQ+TLO63vH3asy8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA00wM3Xp/rf3BO5s6eVXXKUpk7e1au/8E5eeAPv6s6BRrqwx/+cO6+++7cdttt2X333Zt+/pprrpmbb745AwYMaNe6H//4xw0q6jjXX399Pv7xj2fOnDl1r9loo41y9913Z9NNN13k3AknnJCf//zn6datW917P/TQQ9ltt93y+uuv172mmYqiyEEHHZSHHnoo11xzTbbZZpumN4wY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Opa6CnzrtGvXLqZPn54pO2HChFhvvfVybrR077zzTuyzzz4xY8aMTPlu3brFM888ExtttFG+xZZw5513xqmnnhpVVVWZ8vvtt188+uij0aRJk5ybrRpmz54drVu3zpRt3LhxVFZWFr1Dv379YtCgQZmyL7/8cuy1115F77A8L7zwQvTu3TtTtl+/fvH444/n3Kg0Pv300+jcufMKc506dYpPP/10mderq6tj4MCB8X//93/LzRWqdevWcfbZZ8eFF14YzZs3L9q+eXj++efjjjvuiL/+9a8xZ86cou277bbbRv/+/eOUU06Jtm3bFm3fPNTW1sbtt98ev/jFL2L8+PFF23fdddeNc889N84999xlvs4PHjw49t577xXuteeee8bgwYOL1q2uXn311fjLX/4SDz/8cEydOrVo+2688cbRv3//OOOMM6JDhw5F27cYZs6cGXfccUfcfffdMWLEiEjTNLdZ7dq1i5122il69+4dhx9+eGywwQa5zWpIq8PfM1q3bh2zZ89eXmR2mqbZ3uQQZaUuwFJl+YTTor5DkiRJImLniFjRq+1r9Z21hLkruO7TGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVRW1sTz/7xD1FdtbDUVUqqumphPHvTNVFbW1PqKvCt07x588zZNE1zbLJsf//736N3794xY8aMTPlddtklXnvttdhoo43yLfYNxx9/fDzxxBPRsmXLTPmnn346jjjiiFi4cPV+jV+s1M/FqqqqGDx4cKZs8+bNY9dddy16hxXZfffdo2nTppmygwcPjqqqqpwbrbpGjBgR3/nOd+Kss86KTz/9tKh7z5o1Ky6//PLYaqutMj+nGtojjzwS22+/ffTp0yf+8pe/xJw5c4q6/zvvvBM//vGPo1OnTvE///M/MWnSpKLuXyzvvPNObLfddnHqqafG+PHji7r3xIkT46c//Wn06NEjXnvttaLu3ZBqa2vjkUceiR133DG++93vxsCBA2Pq1KlFnfHJJ5/E5ZdfHhtvvHEMGDCg6P8XdTFjxoz4yU9+Eh07doxzzjknhg8fnvv7oGnTpsVTTz0V5513XnTq1Cl23XXX+P3vf1/07zes7MpKXYClqsyQyf5uftm2iojWix4ny8kV8zfr3BVcb1LEWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJDZO08PigmjR5W6xkphwkcfxDtPDyp1DfjWmT17duZsy5Ytc2yydO+//3706tUrpk2blil/0EEHxYsvvhjt2rXLudnS9e3bNwYPHhzrrLNOpvygQYPiqKOOiqqqqpybrfxK/VwcPnx4zJkzJ1N2jz32iMaNGxe9w4o0bdo0dtttt0zZ2bNnx4gRI3JutGq68sorY+edd45333031znjxo2L3r17x4033pjrnEJ8/PHH0bNnzzj88MPj7bffzn3enDlz4v/+7/+iW7duMXDgwEjTNPeZWV177bWxyy67xMiRI3Od8+GHH8Yee+wRV1xxRa5z8vDWW2/FTjvtFIcffngMHz4893mVlZUxcODA2GKLLeL666+P2tra3GcuzT333BObbLJJ/Pa3v425c+eWpEOapjF06NA4//zzY9Agn4FYvZSVugBLNS9DpmMR5uy1jPNLvoOYnqbpR0WYtdiKnnM1RZwFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmSyYOyeGPnRPqWusVIY+dE8smDun1DXgW6OqqipmzZqVKVteXh4tW7bMudF/GjVqVOyzzz4xZcqUTPnTTjstHnnkkWjWrFnOzZZv++23j9dffz023XTTTPnHHnssjjnmmKiurs652cpt2rRpmbNrrrlm0eePGDEic3bnnXcu+vw8Zr/11ls5Nln1LFy4ME488cT46U9/GjU1NQ0ys7q6Os4888z47W9/2yDzluf666+PrbfeOl5++eUGnz1z5swYMGBA7LnnnjFx4sQGn7+k2traGDBgQJxzzjlRWVnZIDPTNI2f//znMWDAgAZ77tXHwoUL49xzz40dd9yxoNfGYpk1a1acffbZ0bt374J+N9TXwoUL44QTTojvf//7MX369AabC/ynslIXYKmyfCLbpAhzei7nWhIRaUS8XoQ5S1rRp0d/hQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKDBvT/4xaicN7fUNVYqlfPmxgevvFjqGvCt8f7770eappmyG220UZSVleXc6N9Gjx4d++yzT0yaNClT/tJLL42bbropysvLc26WzcYbbxyvv/567LTTTpnyDz30UBx77LFRU1OTc7OV1z/+8Y/M2Y033rjo899+++3M2e23377o87PaYYcdMmcLuadvu+rq6jj88MPjjjvuKMn8n/zkJ/HnP/+5JLMrKyvj5JNPjrPPPjsqKytL0mGxV199NXbYYYd48803SzK/uro6jj766Bg4cGBJ5g8cODAGDBhQktlZff7557H77rvHNddcE7W1tSXt8tJLL8UOO+xQ0O+Hupo3b1707ds37rzzztxnAcvXcJ84KMTkDJku9RmQJElFRPSMiBV9Qn2tPnOWosUKrs8p8jwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYrrS2NkY+/2Spa6yU3n3uqUjTtNQ14FthxIgRmbNdu3bNscl/Gjt2bPTs2TO++uqrFWYrKiritttui4svvrgBmhWmffv28dJLL8WBBx6YKX///ffHCSecELW1tTk3WzmV+vn49ttvZ85ut912RZ+f1Q477JA5W8g9fZulaRonnHBCDBo0qKQ9zjjjjHj//fcbdOaCBQuiX79+cfvttzfo3OUZP3587LXXXvHSSy81+OzTTz89HnzwwQafu6RbbrklrrzyypJ2WJa33347tt9++xg+fHipq/zLp59+GnvvvXf8/e9/z21GTU1NHHHEETF48ODcZgDZVZS6AEs1LkNm13rO2CsiWkVEGhHJcnJD6jnnm9ZbxvnFHWYXeR4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAs1+fv/T1mfDWh1DVWSjO+Gh+fvzcyOm3do9RVYJX3+OOPZ87uuOOOOTb5t3HjxsXee+8d48ePX2G2RYsW8eCDD8Z+++3XAM3qpnnz5vHYY4/FgAED4pZbbllh/i9/+UtUVFTEbbfdFmVlZQ3QcOVRyudjdXV1jBo1KlO2VatW0bFjx6LOL8T6668fLVu2jDlz5qww+8EHH0R1dXVUVFQ0QLOV18UXXxz33HNPpmyzZs1iu+22iy5dusQGG2wQLVq0iMaNG8e8efNi4sSJ8fHHH8ewYcNi1qxZBfeYP39+HH/88TF8+PAG+fmurKyMQw89NJ5//vncZxVq/vz50a9fv3jqqadizz33bJCZV1xxRabX4WVp27ZtbLfddrHZZptF+/bto2XLlrFgwYKYOXNmjBkzJv7+97/H2LFjM+31s5/9LLbffvuV6mdz2LBhse+++8bXX39d6ir/Zdq0adGzZ8949dVXY/PNNy/6/r/+9a/j6aefLvq+QN2sPK+M/EuapvOSJBkfER0iIo2IZMnLi77ePUmSZmmazq/jmCOWNX6JxwsjYngd91+WDsu5lkbE7CLPAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgOV697knS11hpTbyuaei09Y9Sl0DVmkzZ86M5557LnN+r732yq/MIp999lnsvffe8cUXX6wwu/baa8egQYPiO9/5Tu696qu8vDxuvvnm6NixY/zqV79aYf6OO+6IioqKuPnmmyNJkgZoWHofffRR/OMf/8icL/bz8fPPP4/q6upM2U022aSos+uiS5cuMXLkyBXmqqqq4osvvojOnTs3QKuV0/PPPx9XXHHFcjNrrrlmHHvssfG9730vdt5552jUqNFy8zU1NfHyyy/HwIED4+GHH440TTP3efvtt+O2226LU089NfOaujrttNPimWeeqdPaNddcM/r06RP77LNPbLXVVrHxxhtH69ato3HjxjF79uyYMmVKfPjhhzFs2LB4+umn45133il4xrx58+Kggw6K4cOHR9euXevUM6tXXnklLr744oLXtWjRIr7//e/HiSeeGDvttFOUlZUtN//JJ5/EQw89FDfddFOMGzdumbk0TeMHP/hBXHfddQV3ysPf//736N27d8yePbtO67t27Rr77LNP7LDDDtG1a9fYcMMNo02bNtGsWbOoqamJOXPmxBdffBGjR4+O1157LZ5++un4+OOPC5oxbdq0OOSQQ+LNN9+MNdZYo049l+a9996Lyy67rE5rO3XqFL169YotttgiNtlkk+jSpUusscYa0aJFi2jevHlUVFREZWVlzJ8/P6ZOnRpTpkyJzz//PD7++OMYNWpUjBgxIsaOHVu0e4Fvi6SQX6w0nCRJnoqIfSMijYglP6Us/jqNiMPTNH2sDns3joivImLNxaeWsf/raZruUej+K5g9JiIWv1tePHfJmY+naXpoMWcCsHJJkmRWRLRa1vVWrVrFrFmzGrARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPynmpqaGD16dOZ8165do7y8PMdG5Gn2tKlx85knR5rWlrrKSispK4sfXH9btGrXvtRVYJV11VVXxY9//ONM2TXXXDMmTpwYTZo0ya3Pl19+GXvuuWd88sknK8x26dIlnn322ejSpUtuffJyyy23xIABA6KmpmaF2dNOOy3++Mc/RpIkDdCstM4888y48cYbM2U322yzGDVqVFHnv/jii9GrV69M2e9973tx//33F3V+oY488sh46KGHMmVffPHF6NmzZ86NGtann34anTt3XmGubdu2UVFREZMnT17q9RYtWsSFF14YZ599drRq1apOXUaMGBEnnXRSvPfee5nXdOzYMcaNGxeNGjWq08ws/vjHP8YZZ5xR8LouXbrEhRdeGP37949mzZplXvf3v/89fve738Vdd90VtbWFvYfdcsst44033oiWLVsWWjeTGTNmRPfu3eOLL77IvCZJkjjllFPiiiuuiLXWWqvgmTU1NXHTTTfFxRdfHDNmzFhmrnv37jFy5MgV7rfnnnvG4MGDC+6RxeTJk2PHHXeMzz77rKB1bdq0iVNOOSVOPfXU6NatW8Fzhw0bFr/97W/j0UcfjTRNM6874IADYtCgQQXPW5aDDjoonnjiicz5Vq1axWmnnVbn+/6m6dOnx8svvxwvvPBCPPHEEzF+/Pj/ytx+++1x4okn1ntWqawOf89o3bp1zJ49e3mR2Wmatm6oPqu6slIXYJmGZsj8vzru3T8i2ix6vLxPP8/Xcf+lSpKkaURstILYmGLOBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgOX5+4vPRprWlrrGSi2trY1/vPRsqWvAKmvhwoVx7bXXZs4feeSR0aRJkxwbRay//voxduzYSNN0hceYMWOiS5cuufbJy6mnnhrV1dWZ7vOmm26KJElKXTl3U6dOjT//+c+Z88cdd1zRO4wbNy5zdsMNNyz6/EIV0qGQe/u2mT59ekyePHmp13bdddd4//3348ILL4xWrVrVecYOO+wQQ4cOjX333TfzmvHjx8eDDz5Y55kr8v7778e5555b0JqKior49a9/HR988EGcfPLJ0axZs4LWb7PNNvHnP/853nzzzdhyyy0LWvv+++/HOeecU9CaQvzkJz+JL774InO+bdu2MWjQoLj55ptjrbXWqtPM8vLyOPPMM2PkyJGxyy67LDM3cuTIOu1fLDU1NXH44YfHZ599lnlNo0aN4mc/+1mMGzcurrrqqujWrVudZu+0007x8MMPx9/+9reC9njyyScL+p2xPGPGjIlBgwZlzh9//PHx2Wef1eu+v6lt27Zx+OGHxx//+Mf44osvYsiQIXHaaafV63UJVnVlpS7AMr26jPNJRKSL/t0lSZI+hWyaJEl5RPxs0R4r8lQhe2ewefz7ObesT15jizwTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlunjYa+VusIqYfQbvk9QV3/4wx/iyy+/zJw/6aSTcmzD6u6SSy6JefPmZcpWVFTEscceW/QO48aNy5xdd911iz6/UIV0KOTeVhfHH398DB48ODp16lSU/Vq2bBmPPPJI7LzzzpnXDBw4sCizvylN0zjttNNi4cKFmde0b98+Bg8eHBdddFE0bty4XvO33377ePPNN+Poo48uaN1tt90WgwcPrtfspXn33Xfj1ltvzZxfd91149VXX43999+/KPM32GCDeOmll4q2X7FdddVVMWTIkMz5zTffPIYPHx5XXHFFrLHGGkXpsPvuu8eIESPi0EMPzbzmggsuiMmTJ9d79p133hlpmmbKXn311XHHHXdEmzZt6j13WZIkid122y1uuummmDBhQtxwww3RuXPn3ObByqqs1AVYplcjYsaix0t79UwjIomIO5IkKeQd888iouuix8lS9lzsizRNRxSwbxZZ3r2NLfJMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWKrKeXNj2pefl7rGKmHal59H5by5pa4Bq5xJkybF5Zdfnjn/3e9+N3bZZZccG7E6e++99+JPf/pT5vwxxxwTG264YdF7TJo0KXN23XXXLfr8QhXSYfLkyTk2WfUcd9xxcfvtt0ejRo2Kum+zZs3i3nvvjVatWmXKDxkyJL766quidoiIuO222+K1117LnF9nnXVi8ODBsdtuuxWtQ/PmzeMvf/lLnHzyyQWtGzBgQFRXVxetR0TEBRdcELW1tZmyrVu3jhdffDG22GKLonZo2rRpPProo7HnnnsWdd/6GjVqVPzyl7/MnN9nn31i6NCh0b1796J3admyZTz44INx7LHHZspPnz49LrvssnrPffbZZzPlTjrppDj//PPrPa8QLVu2jDPOOCM+/vjjOPDAAxt0NpRaWakLsHRpmtZExOMRkSzl8uJzaUSsExHPJ0nSdUV7JklyckT8atG6ZcYWXX+goMLZZHkHNDaHuQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPBfJn0yttQVVimTx/l+QaEGDBgQs2bNypy/+OKLc2zD6qy6ujpOOumkqKmpyZQvKyuLCy+8MJcu06dPz5xdZ511culQiEI6TJs2Lccmq5Zdd901brnlligrK8tl/4022ih+8pOfZMrW1tbGX//616LOr6qqil//+teZ802bNo3HH388ttxyy6L2iPjnz+uf/vSn2HfffTOv+eijj+Kuu+4qWofhw4fHSy+9lDn/l7/8JbbYYouizV9S48aN4+GHH45OnTrlsn9dnHvuuVFZWZkpu9dee8UTTzwRa6yxRm59ysvL4/bbb4999tknU/7mm2+OCRMm1HneggUL4q233lphrlmzZvH73/++znPqq7y8PNq3b1+y+VAKFaUuwHINjIgTlnEtiYh00bFlRIxIkuSaiPhzmqb/8debJEl6RMSPI+KoJdYlK5h9S91rL9N3F81e0pJfz4uIcTnMBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWO288+ygGPncU6Wu0eAO/p+Los26HTJlJ40bk3Obb5dB1/w2dj786Ni274ENMu/R314aMydNbJBZxdS9z/4N9j1i5XbHHXfEY489ljm///77R69evfIrxGrt8ssvjxEjRmTODxgwILp165ZLl2nTpmXOrrHGGrl0KEQhHQq5t2+zFi1axD333BONGzfOdc4555wTv/3tb2PWrFkrzL7yyisxYMCAos2+884747PPPsucv/7662PHHXcs2vxvKi8vj/vuuy+22Wab+PzzzzOtueKKK+L444+P8vLyes+/6qqrMmd/8IMfxIEH5vteqV27dnHLLbdE7969c52Txd/+9rd47rnnMmW7dOkSjz32WDRr1iznVhEVFRVx//33x5ZbbhmTJk1abnbBggXx+9//vqD/5yWNGTMmampqVpg77LDDVorXfVidVJS6AMuWpukbSZKMiIjtIyKNiOQbkWTR+YiIlhFxYURcmCTJ1Ij4MiKqI2KDiFjnG/lv7hNLnE8j4oU0TUcX8VYiSZKtI2L9ZcxfPPetNE3Tb64FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgcPNnzYxpX35e6hoNrqaqKnN20idjcmzy7TNv5tcxf9bMBps3c9LEVfI53JDfI1ZeY8aMiR/96EeZ802aNIlrrrkmx0aszl5//fW47LLLMufbt29fUL5Q06ZNy5xt1apVbj3y6DB9+vQcm6w6fvnLX0anTp1yn9OyZcvo379/DBw4cIXZV199taizr7766szZ/fbbL0455ZSizl+aNdZYI2655Zbo06dPpvyYMWPir3/9axx22GH1mjt58uR45JFHMmXbtWsXV111Vb3mZdWrV6849thj4+67726Qecty0UUXZcqVl5fHAw88EGussUbOjf6tXbt2cf3118eRRx65wuydd94ZV1xxRTRq1KjgOZ9/nu09/S677FLw3kD9lJW6ACt0YUQky7meRES66EgWHWtFxLYR8Z2IWHeJ82nGmZfXtexyHJghMzSHuQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBUkz75uNQVgG+hefPmxWGHHRazZs3KvObCCy+MTTbZJMdWrK4mTZoURx55ZFRXV2dec/XVV0ebNm1y6/T1119nzrZu3Tq3Hnl0KOTevq3WW2+9OPPMMxts3uGHH54pN378+JgyZUpRZr755psxatSoTNmKioq45pprijI3i969e8dhhx2WOf/nP/+53jMfeOCBqKmpyZT96U9/GmussUa9Z2Z16aWXRqNGjRps3jeNHDkyXn311UzZc845J7bbbrucG/23I444InbccccV5iZPnhxPPPFEnWbMnj07U2799dev0/5A3ZWVugDLl6bpCxHxeEQkEZEuI5Ysji9xxFLOJUtk4xuZxfs/nabp3+rf/L9keXfyRg5zAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4L9UzpsbX0/8qtQ1VjnVVQtLXQFWeqeddlr84x//yJzfcccd48ILL8yxEaur6urqOProo2PChAmZ1xx66KFx/PHH59gqorKyMnO2RYsWOTYpfodC7u3basCAAdGsWbMGm/fd7343GjdunCn74YcfFmXmHXfckTl78sknx6abblqUuVldfvnlUVZWlin79NNPx+TJk+s17957782Ua926dZx++un1mlWozp07x1FHHdWgM5f0pz/9KVOuVatW8fOf/zznNsv2k5/8JFPu0UcfrdP+Cxdm+wxRUVFRp/2Busv224JS+2FETF30OF1GJlniWJxLv3FtaZbcb25E/KjuNZdRLEm6RcT2i2Ytq0dExNBizwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIClmfblF6WusEqaP2tWqSvASu03v/lN3H333Znz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+8EPfhA33HBDTq1Kr7y8PM4///zM+YsvvjhmzpyZW58ZM2bEJZdckjl/wQUXRFlZWW59WDm1bds2Dj/88Mz58847L6ZPn55jo3+75JJL4pNPPsmULS8vj1NOOaXeM5MkifPOOy9z/vTTT48ZM2bUe+6KnHvuufHVV1/lPmd5Nthgg/je976XKTtlypQ4/vjjI03TnFut3tI0jdGjR2fKdurUKec2UHrexawCkiTpEhG3RMTi3xDL+ktVuuhIFh3/iIgfRcRGaZp2S9P0mDRNL0vT9M9pmj6RpunzeXdfwhNLObfkfZRFxJ4N1AUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWaLNdvxv7nHx6qWs0iF6nnB7ddtmj1DWgqK688sr4xS9+UdCaPn36xCOPPBKNGzfOqRWrqzPOOCNuvfXWgtacdNJJMXDgwEiSJKdWK4dTTz012rVrlyk7efLk+H//7//l1uW8886LadOmZcq2b98+TjnllNy6sHL72c9+lvlnc+LEiXHqqadGmqa5dnr55Zfj6quvzpw/6qijYpNNNinK7JNOOinat2+fKTthwoTo379/1NTUFGX20tx8881xxx135LZ/Ia644opo0qRJpuyzzz4bZ511Vs6NGl51dXWpK/zLCy+8EF999VWm7JZbbplzGyi9slIXIJObIqLZosfLeveRLnH93YjYP03T7mmaXp+m6ec598viuYhY/Jt/We+I/FUKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAlUqPPvvH7v1PKHWNXO3e/4To3nv/UteAovr9738fP/3pTwtas88++8Rjjz0WTZo0yakVq6tzzjknbrrppoLWHHfccXHLLbdEkiQ5tVp5NG/ePM4///zM+VtuuSXuueeeove444474o477sicP//886N58+ZF78GqYeutt45DDjkkc/7RRx+NX/ziF7n1+fjjj+OII46ImpqaTPkkSeLnP/950eY3a9YsLrzwwsz5Z599Nk4//fRI07RoHRYbNGhQnHnmmUXft6422mijOO+88zLnb7zxxjjrrLMy/182hMGDB8fRRx9d5/X77rtvXHbZZTFz5switipcbW1t/O///m+mbLNmzWLHHXfMuRGUXlmpC7B8SZJ8LyL2iYg0Ipb2ySBd4lptRFwUEd9J0/SZBiuZ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AAAAAAAAABSobYeOcdSvfhPvPP1EDLn3zqiuWljqSitU0ahx7N7/+Nh2v35RVlZe6joAsFStW7eOBx98MHbddddYsGBB5nUzZsyISy+9NC699NLYdNNNY4cddohOnTrFmmuuGWmaxtdffx3jxo2LESNGxCeffFKnbs2aNYsHHnggWrduXaf1fHt17tw57rvvvjjggAOiqqqqoLVvv/12/OAHP4gkSWLLLbeMLbfcMjbeeONo1apVNG7cOObMmRNTpkyJDz/8MN566634+uuv69zzgAMOiMsuu6zO67Nq0qRJPPHEE7HzzjvHhAkTClqbpmm88cYb8cYbbxStz3bbbReXX355DBs2rGh71sell14a06ZNixtvvLHgtTNmzIjbb789br/99oiI6NChQ2y++eax/vrrR4cOHaJFixbRtGnTSNM0KisrY8GCBTFt2rSYNGlSTJw4MT7++OOYMmVKsW+paKqqqmLIkCExZMiQf51r3bp1dOvWLTp27BgdOnSIdu3aRdOmTaNp06axcOHCmDt3bsyZMycmTpwYH330UYwePTrmzp1b5w5nnXVW9OrVqxi3A6uEilIXYJkOiIjGEZFGRLLE+XSJx+Mj4hcNWao+0jStSZJkTERstpxY54bqAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVVVlYe2x9wSHTe9jvx7B//EBNGjyp1pWXq0G2L2Pf0c6LNeh1LXQUAVmjbbbeNRx55JA455JBYuHBhwes//vjj+Pjjj4vaqXHjxvHII49Ejx49irov3x69e/eO++67L4466qiorq4ueH2apvHee+/Fe++9l0O7iF69esVDDz0UZWVluez/TRtssEE89dRTseeee8bMmTMbZObSrL/++vHEE09Es2bNStZhaW644YZo3759XHrppfXaZ8KECTFhwoQitVo5zZo1K4YPHx7Dhw/Pfdaee+4ZV199de5zYGXSML8VqIs9lnMtiYg0Iq5K03R+A/Upli/in/2XZYOGKgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD11bZDxzjqV7+JvY7/QTRp3qLUdf5Dk+YtYq/jfxBH/fJ/o816HUtdBwAy22+//eKBBx6IioqKUleJioqKePDBB2PfffctdRVWcocddljce++90bRp01JX+Q99+/aNxx9/vMF7de/ePQYPHhzrrLNOg85dbO21144nn3wyOnToUJL5K/KrX/0qbr311pXu+bK62n333WPQoEHRuHHjUleBBlVW6gIs0+4RkX7j3JJfV0bEnxusTfFMXM61JCLWaqgiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAxlZeWx/QEHx6nX3xp7n/CDaLNex5L2abNex9j7hB/EqdffGtsfcHCUlZWXtA8A1MXBBx8czz77bLRv375kHdq3bx/PPfdcHHTQQSXrwKrliCOOiL/97W/RsWNp3w8udsEFF8STTz4ZzZo1K8n8Hj16xJAhQ2LzzTdv0LmbbrppDB06NLbZZpsGnVuok08+OYYPH77S9/y2O/bYY+P555+Pli1blroKNLiKUhfgvyVJUhER3ZZ1OSLSiHguTdPZDdeqaCYv43wa/7y30r3zB2BFpkTEB0XYZ7OIKCvCPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK5WmLVrGdvsfHNvud1B8/t7IePfZJ2PsiGGRprW5z07KymKTHXaO7n32jw236h5JkuQ+EwDy1rNnzxgxYkQcdthh8fbbbzfo7O233z4efvjh6NSpU4POZdX3ne98J956660444wz4pFHHilJh3XXXTduuOGGOOyww0oyf0mbbLJJjBgxIs4+++y47bbbcp932GGHxZ/+9Kdo165d7rOKYauttoo333wzfvOb38RVV10Vc+fOLXWl/9KxY8cYMGBAqWsU3ZprrhlXX311nHzyyaWuAiVTVuoCLFWniChf9HhZf90Z3DBVim7OCq63bpAWABQsTdMb0jTdsr5HRKx8n3gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIooSZLotHWPOPj//Tx+cMNtscsR/aPd+hvmMqvd+hvGLkf0jx9cf1scdMGF0WnrHpEkSS6zAKAUOnXqFMOGDYvf/e530bp169zntW7dOn7/+9/HsGHDolOnTrnP49tpnXXWiYcffjgee+yx6Ny5c4PNraioiAEDBsSoUaPisMMOa7C5K9K8efO49dZb47nnnoutt946lxkdOnSIBx98MB5++OFo165dLjPy0qRJk/jFL34RH3/8cZx66qnRuHHjUleKFi1axFFHHRVPPPFEfPbZZ3HRRRfVea/rr78+zj333Nh0002L2LDuKioq4tRTT40PPvggTj755FLXgZKqKHUBlirLO4e3c2+Rj8oVXG/SIC0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAbRq1z52PfL7seuR34/KeXNj8rixMemTMTHxkzExedyYmPHVhMx7tVmvQ6zdeZNYd+NNYp2NN4m1O3eJJs1b5NgeAFYOFRUVcd5550X//v3jqquuiltvvTVmzpxZ1BlrrLFGnHLKKfE///M/se666xZ1b1ZfBx98cBxwwAFxzz33xG9/+9t4//33c5nTrFmzOPHEE+MnP/lJdOrUKZcZxdC7d+94991347777ovrr78+hg4dWu89N99887jgggviuOOOi8aNGxehZemst956cfPNN8fll18ef/rTn2LgwIHx5ZdfNtj8tddeO/r27Rv9+vWLAw44IJo3b16UfXfffffYfffd4/e//318/PHHMWjQoHjyySfj9ddfj/nz5xdlRhZt2rSJ448/Ps4+++zo0qVLg82FlVmSpmmpO/ANSZJ8LyLui4g0IpIlLi3+Oo2ITmma1vs3RJIktcubk6ZpeX1nfGPeuRHxu2/MXPwkTCKiJk3TRsWcCcDKJUmSWRHRalnXW7VqFbNmzWrARgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwn2pqamL06NGZ8127do3y8vIcG/FtVjlvbkz78otYMGd2VFctjJqFC6O6uioqKhpFeePGUdGocTRt2Srarb9BNGneotR1AWClMGfOnLjzzjvjkUceiVdffTUWLlxYp30aN24ce+yxRxx++OFx3HHHRcuWLYvcFP7T8OHD4957741HH300Pv3003rt1axZs9hzzz3j6KOPjsMOOyxatWpVnJIN6L333ovHH388nn322XjzzTdjwYIFK1zTunXr2GabbWLfffeNfv36xTbbbNMATUsjTdMYNmxY/PWvf40nn3wy3n///aitrS3a/h07doyddtop9thjj/jud78b2267bSRJUrT9V6SqqirefffdeOONN+KNN96IoUOHxrhx44o6Y4MNNohevXrFwQcfHH379o2mTZsWdf+Vzerw94zWrVvH7NmzlxeZnaZp64bqs6pL0jQtdQe+IUmSkyLi1ohII2LJV+XFX6cR0SpN03lFmFW7vDlpmhb1FSJJkh9HxG++MXPxkzCJ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rCTzT0mu74IuneG0lVwv89Y9t9fGK9l7cgf2BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAN09TUlNGjR2fUqFG555578pe//CVz585d6bp58+Zl3rx5mTFjRl5//fWMHTv27643NDRkr732ypAhQ3L88cdnr732qtEdrH7OO++8nH/++ZWy6667bu68887stttuNW5VX/Pnz8+jjz6asWPHZuzYsRk3blweffTRNDU1Vd5j0aJFWbhwYZqamjJlypQ888wz/5BZf/31c+CBB+boo4/Ohz70oay77rqdeRt1U5ZlHnnkkdx8880ZMWJEHnvsscyYMaPS2k033TR77LFHhg0blqOOOipbbbVVbcsCAKyCGutdgGV6cgXXyiRFkiOLotitLMtxXdSpXYqi2C3JsLzVe0VWdM8rs+1Krr/Ugb0BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAM8+eST+eMf/5ibbrop9957b1paWjp9Rmtrax566KE89NBDueiii7LTTjvltNNOy+mnn55+/fp1+rzVxfnnn5/zzz+/cn769Ok5/PDDM3LkyOyyyy41bNa15s6dm3vvvTd//vOfc9ddd+WBBx7I/Pnzaz536tSpGT58eIYPH56zzjorRx11VD7/+c/nsMMOq/nsWpg2bVp+/vOf58c//nFee+21du0xYcKETJgwITfddFOSZO+9987nP//5fPSjH02PHj06sy4AwCqrod4FWKZRyzlfLPW4Icl/1b5Kh/1n/ta7WEFuVHs2L4qiIcl2ScoVxF5qz94AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQa63zWjL/lVlpfmpa5j42JXP+MjlzHnojc/4yOXMfm5Lmp6Zl/iuz0jqvpd5VYbX02GOP5etf/3q233777LzzzvnSl76UP//5z2lp6Zp/U08++WT+9V//NVtssUXOP//8NDc3d8ncVclFF12U8847r83rpk6dmiFDhuTJJ5+sQauu9corr2T//ffP2muvnaFDh+b888/Pn//858yfP7/LuyxcuDA33HBDhgwZkj333DN33HFHl3dor6ampnzhC1/IoEGD8rWvfS2vvfZap+398MMP5+STT87mm2+eX/ziFynLstP2BgBYVTXWuwDL9HCSGUnWSlImKZa6Vix1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snytPTMAqI2iKGYl6b+86/3798+sWave/2wBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4J1j0aJFefbZZyvnBw8enG7dutWwEauisrXM7HsmZOatLyctrfWus3KNDVnryC3T74BNUjQU9W4DNXPdddflhBNOqJxff/318773vS9HHnlkjjjiiGywwQbtmjtp0qRcdtllufjiizN58uR27XHRRRfly1/+crvW1tuvf/3rfPKTn0xra/X3w6Io8oMf/CCnnnpqPvjBD+auu+5q08ztttsud911VzbeeOO21u1yY8eOzR577LHc6zvvvHMOPfTQ7Lvvvtlnn32y7bbbdnjm7Nmzc9111+XKK6/MqFGjUpZlm/fYeuut88QTT6RXr14d7lPVlVdemVNOOaVNa/r165cvfOELOeecczJgwIBKa5577rmcd955ufbaa9v03PTt2zcPPfRQdtxxxzZ1BOrv8ssvz6mnnrrS3CmnnJLLL7+89oWgBt4Jf88YMGBAmpqaVhRpKsuy2gcCUrTnQyJdqyiKI5PclKRhyakVxMtlZJacW5hkbJInkjyT5JUkU5JMTTIvyYLF2Z6Lj/WTDEwyKMn2SXZOskeSHiuYsbxuS19flOSYsixvWcF9rFBRFP+c5L8X7/v2Hku+f6Qsy3e3dwYAtVEUxawk/Zd3vX///pk1a1YXNgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAv7do0aI8++yzlfODBw9Ot27datiIVc3CKXPz5nXjs+DlWfWu0mY9thiQdY7fLt036FPvKlAT1113XU444YQVZvr165cPf/jD+djHPpahQ4emsbGx0+bPmTMnF1xwQb7//e+npaWlTWt79uyZsWPHZocddui0Pl3hN7/5TU466aQsWrSo8poePXrkyiuvzEc/+tEkyfz583PyySfnN7/5TZtm77DDDhk1alQ23HDDNq3ramPHjs0ee+zx1+/XW2+9DBs2LO9///szZMiQDBw4sKbz77nnnpx11ll57LHH2rz2O9/5Tr7yla/UoNU/evnll7PTTjtl7ty5ldfst99++c1vfpNBgwa1a+bIkSNz4oknZtKkSZXX7LbbbnnkkUd8/oPVzOWXX55TTz11pblTTjkll19+ee0LQQ28E/6eMWDAgDQ1Na0o0lSW5YCu6rO6a6h3AVau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HyplR4wYkWOOOabGjVZvc+fOzX/913/lRz/6USZPntyhvVpbW/PnP/85f/7zn3Peeefly1/+cj7/+c+36TXd1VpbWzN8+PBcddVVufnmmzN//vx27zN+/PiMHz8+l19+eYqiyIEHHpiTTjopn/zkJ9O3b99Obt655s+fnx/96Ee56KKLKv88XJ65c+fmxhtvzI033phtttkmX/ziF3P66aenoaGhk9rWT1mWufnmm3PNNdfkhhtuSFNTU7v3mjx5coYPH57hw4fni1/8YnbZZZd8/OMfzxlnnJF11lmnE1t33KRJk3LppZfmmmuuyRNPPNEpe86aNSuPPfZYHnvssb87v/HGG2fffffNsGHD8qEPfSgbbLBBp8yD1c3q/45Jh5Rl2VqW5ZyyLKeVZTlh8TG1LMvZZVm+w/86BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwDvJ7Htfz4KXZ9W7xiphwcuzMvve1+tdA9Y4ffr0qZwty7KGTZbv0UcfzdChQ/Pmm29Wyu+333655557suWWW9a22NucfPLJ+cMf/pB+/fpVyt988805/vjjs2DBgho3W33Mnj27cna99dbr1NkTJ07M448/Xim7zTbbdPnrK0kOP/zwytnbbruthk1Wf7fddlt22WWX/Nu//VsmT57cqXtPnjw5/+///b/svffeefTRRzt1787Q0tKSX/7yl9lxxx1z3HHHZfjw4Zk/f36n7V+WZe6+++6cddZZ2XLLLXPBBRdk1qxV8/PsHXfckZ122ilf+tKXMn369E7d+/nnn8+ZZ56Z/fffP0888USn7t2VFi5cmF/+8pfZaaed8v73vz9XX311mpqaOnXG448/nq9+9avZYost8pWvfCUzZszo1P3bY8KECfnMZz6TzTbbLP/2b//WJf8NJ06cmN///vc544wzsvHGG+fwww/Pz372szb9bIQ1QUO9CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADUW2tzS2bd/nK9a6xSZt3+clqbW+pdA9YoTU1NlbP9+vWrYZNle+KJJ3L44Ydn2rRplfLHHnts7rjjjqy33no1brZsRx55ZEaNGpUNN9ywUv6mm27KRz/60SxcuLDGzVYPL79c/efelltu2amzR44cWTl7+OGHd+rsqrbccstss802lbLPPPNMJk6cWONGq59FixblX/7lX3LkkUfmxRdfrOmscePGZf/998/vf//7ms5pi4ceeijvfve78+lPfzrPPvtszedNnTo1//Zv/5Ydd9wxv/vd72o+r6pFixbl3HPPzRFHHJEXXnihprMeeOCB7LnnnrniiitqOqcWRowYkZ133jmf/vSn8/TTT9d8XlNTU7773e9mhx12yLXXXlvzectSlmV++MMfZvDgwfnFL35Rt5/PixYtyh133JEzzzwzDz/8cF06QL001LsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQL3NeWRSynmL6l1jlVLOW5Q5j0yqdw1YYyxcuDCzZs2qlO3WrVv69etX40Z/76mnnsqQIUMyZcqUSvkzzjgj119/fXr37l3jZiu211575d577812221XKT98+PCcdNJJaWlpqXGzVd+4ceMqZw866KBOnf3www9Xzu67776dOrst2jL7kUceqWGT1c/MmTPz/ve/Pz/60Y+6bOacOXNy/PHH59prr+2ymcvS2tqac889N/vuu2/Gjh3b5fNff/31HH/88TnuuOPS1NTU5fOX1tzcnA996EO58MIL09ra2iUzFyxYkE996lP59re/3SXzOmrmzJk56aSTcsQRR2T8+PFdPn/SpEk58cQTc9JJJ2Xu3LldNnfmzJl53/vel7PPPrtL5wJ/r6HeBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADqqWwtM+f+ifWusUqac//ElGVZ7xqwRnjiiScq/3vacsst09DQUONGf/Pss89myJAhmTRpUqX8t771rfz0pz9Nt27datysmq233jr33ntv9tlnn0r56667Lp/4xCeyaNGiGjdbtY0YMaJSbsCAAdl99907dfaYMWMqZ/faa69Ond0We++9d+VsW+5pTdfU1JShQ4fm1ltv7fLZra2tOfnkk3P77bd3+ewkmTlzZo4++uhceOGFaW1trUuHJa6//vrsu+++GT9+fF3mz549O8OGDcsf/vCHusz/+te/ngsuuKAus6t67LHH8u53vzvXXHNNvavkmmuuyf77759XX3215rOmTJmSAw44oC7vEcDf67rfOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWQfOfn5GWqc31rrFKapnanPnPz6h3DVgjPPzww5WzgwcPrmGTv/f888/nsMMOy8SJE1eabWxszGWXXZavf/3rXdCsbdZff/3ceeedOfrooyvl/+///i+nnHJKWltba9xs1fTcc8/lnnvuqZQ9+uij09DQ0Gmzy7LM2LFjK2V79eqVnXbaqdNmt9Xee+9dOTtmzJgaNll9zJs3L8cee2weeuihunVYuHBhPv7xj+eNN97o0rnTp0/PwQcfnJtvvrlL567Ik08+mf333z+PPfZYl85taWnJCSeckD//+c9dOvftvv71r+faa6+ta4flueWWW7Lvvvtm/Pjx9a7yV+PGjcshhxySV199tWYzZs+enWHDhuWJJ56o2QygusZ6FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACop9n3T6x3hVXanPsmpte269S7Bqz2brzxxsrZ97znPTVs8jcvvvhiDj300EyYMGGl2b59++a3v/1t3ve+93VBs/bp06dPhg8fnjPPPDOXXnrpSvO/+tWv0tjYmMsuuywNDQ1d0HDV8a1vfStlWVbKnnPOOZ06++WXX87MmTMrZbfbbrt069atU+e3xQ477FA5O27cuBo2WX2cdtppGTVqVKXsgAEDsueee2abbbbJJptskr59+6Zbt26ZM2dOJkyYkGeeeSYPPfRQmpub29xj8uTJOfPMMzN8+PA2r22PGTNmZOjQoavk62Dq1KkZMmRIRo4cmZ133rlLZv5//9//l1tuuaXd6zfaaKPsscce2X777bPuuuumT58+mTt3bmbMmJFnn302Y8eOzWuvvbbSfcqyzKmnnppdd9213V1q4cYbb8wJJ5yQBQsW1LvKP3jhhRdyyCGH5N57782GG27Y6ft/9rOfzZgxYzp9X6B9GutdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKBeWmbOz7wnp9W7xiqt+alpaZk5P41r9ax3FVhtzZw5M7fddlvl/CGHHFK7Mou9/PLLOfTQQ/Pqq6+uNDtw4MDcdNNNefe7313zXh3VrVu3/OIXv8imm26ab37zmyvNX3HFFWlsbMwvfvGLFEXRBQ3r79Zbb83VV19dKXvQQQdl77337tT5L7zwQuXstttu26mz22r99dfP2muvnRkzZqw0++qrr6alpSWNjY21L7aKuvTSS/OrX/1qhZmNN944n/zkJ/ORj3wke+yxRxoaGlaYX7BgQW6++eZccsklGTFiRJv63HDDDbnjjjsyZMiQNq1rq0WLFuW4447LmDFj2rV+ww03zLBhw3LooYdmp512ypZbbpn+/funW7duaWpqyhtvvJGnnnoq99xzT/70pz/lmWeeafOMKVOm5H3ve18eeeSRbLDBBu3qWdVVV12VX/ziF21et+666+bTn/50PvGJT2S33XZbaf6JJ57INddck0svvTSTJk1abm7evHk59dRT85nPfKbNnWrhtttuy/HHH5+FCxe2a/3uu++egw8+OHvvvXe23XbbbL755hkwYEB69+6dhQsXpqmpKS+//HKefvrpjB49OjfddFMmTJjQphkvvPBCjj/++Nx5553p3r17u3ouyy233JIrrriiXWu33377DBkyJDvssEO22WabbL311unfv3/69u2bvn37piiKzJ8/P3Pnzs3UqVMzZcqUvPjiixk/fnyefPLJPPTQQ3nttdc67V5gTVGUZVnvDgDAO0hRFLOS9F/e9f79+2fWrFld2AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/t6iRYvy7LPPVs4PHjw43bp1q2EjamnmiJfTdMcr9a6xyus/ZPOsNXSLeteA1db3v//9fOlLX6qUXXvttfPGG2+kZ8+eNevz2muv5eCDD84LL7yw0uw222yTW2+9Ndtss03N+tTKpZdemjPPPDOLFi1aafaMM87IT37ykxRF0QXN6ufxxx/Pe9/73rz55psrzXbv3j0PPPBA9thjj07t8L//+7857bTTKmW/9KUv5bvf/W6nzm+rd7/73Xn44YcrZZ9//vlsvfXWNW7UtUaNGpVDDz10pbktttgikydPTnNz8zKvr7feejn//PPz6U9/ut3vb7fddltOO+20vPrqq5XXvOc978kDDzzQrnlVffnLX873vve9Nq/bY4898tWvfjUf+tCH0tjYWHnd6NGj8/3vfz833nhjm2cedthhue2222r2+8sLL7yQ3XffPU1NTZXXdO/ePeecc07+7d/+Lf3792/zzHnz5uV73/teLrroouW+/pJkt912y7hx41a63ymnnJLLL7+8zT2qeOaZZ7LvvvtmxowZbVq3ySab5Iwzzsipp56azTbbrE1ry7LMHXfcke985zu5884727T2n//5n/M///M/bVqzoh677757Hn300cprNthgg/zLv/xLPvGJT2SLLTr+u8jEiRNzxx135Pbbb89NN92UadOm/UNm5MiROeSQQzo8q17eCX/PGDBgwMreY5rKshzQVX1Wdw31LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQL82PT613hdWC5wnab8GCBfnRj35UOX/CCSekZ8+eNWyUDBo0KM8//3zKslzp8dxzz2WbbbapaZ9aOe2009LS0lLpPn/605+mKIp6V66pO+64IwcffHDefPPNSvlvfOMb2WOPPTq9x4svvlg5u/nmm3f6/LZqS4e23Nua5uWXX05zc/Myr33gAx/I008/nbPOOqtD729HHHFEHnrooey5556V1zz44IO599572z1zZUaMGJHvfe97bVrTp0+f/PSnP83DDz+cE044IY2NjW1af+CBB+aGG27IiBEjMmjQoDatvfPOO3PhhRe2aU1bnHnmmWlqaqqc33zzzXP33Xfnu9/9bvr379+umb169cp5552XBx98MNtvv/1yc+PGjWvX/p2lqakpxxxzTGbMmFF5Tb9+/fL9738/zz//fM4777xsttlmbZ5bFEUOP/zw3HHHHRk+fHg22WSTymsvueSSjBw5ss0zl+XOO+/Mo48+Wjn/pS99KS+//HLOPffcbLHFFp3SYeONN84nPvGJXH755XnjjTdy22235aSTTqr55y5YlTXUuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAPbTOa0nLpLn1rrFaaJk0N63zWupdA1ZLF198cV577bXK+VNPPbWGbXgnmjx5ck4++eQcfvjhmT59eqU1w4YNy1e+8pWa9HnxxRcrZzfaaKOadGiLtnRoy729U3z1q1/N73//+6y//vqdst+GG26YW2+9Ndtss03lNT/72c86ZfbbNTc356yzzmrTmq233joPP/xwzjjjjDQ0NHRo/uGHH56xY8fm0EMPbdO6Cy64IM8++2yHZi/LjTfemBEjRlTO77DDDrnvvvuyzz77dMr8XXbZJffdd1/23nvvTtmvs33xi1/M+PHjK+f333//PPbYY/nCF76QXr16dUqHD3zgAxkzZkwOOOCAyms+85nPZN68eR2efcUVV1TKNTQ05Le//W2++93vpnfv3h2euzyNjY0ZOnRofvWrX2XChAm58MILM3DgwJrNg1VVx34SAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKymFkyYXe8KqxXPF7TdpEmTcsEFF1TOv/e9781+++1Xw0a8U5RlmdGjR+fMM8/Mdtttl6uuuqry2iOPPDK///3v061bt5p0mzRpUuXsRhttVJMObdGWDpMnT65hk9XPueeemwsvvDBFUXTqvuuvv35+/etfV36N3nDDDVmwYEGndkiSCy+8MM8//3zl/Pbbb5+77747O+64Y6d1WG+99fKnP/0pw4YNq7xm/vz5OeusszqtQ5IsWrQoX/jCFyrnBw0alJEjR2aTTTbp1B7rrLNObr/99k59jjvDnXfemZ///OeV8yeddFLuvPPObLnllp3eZcMNN8yIESMyZMiQSvnnnnsuP/7xjzs897bbbquU+8Y3vpHjjz++w/PaYr311stXv/rVvPzyy9ljjz26dDbUW2O9CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdb/Z9r2f2fRPrXaPLrX/yTmlcv3el7MIJs2vcZs0y/ZqnM2DI5um33yZdMm/qFU+kZdq8LpnVmfrtt3GXPUes+s4888zMmjWrcv7rX/96Dduwplm0aFFmzZqVpqamzJo1K6+88krGjRuXsWPH5v77788rr7zS5j2PP/74XHXVVenVq1cNGr9l+vTplbMbbrhhzXrUosO0adNq2GT1csIJJ+Tb3/52zfZ/z3vek1NPPTWXXnrpSrMzZ87MnXfemWHDhnXa/GnTpuXiiy+unF9//fVz8803Z5NNOv8zQq9evXLdddflwAMPzNixYyutufPOOzNy5MgceuihndLh+uuvz/jx4ytle/TokeHDh2ejjTbqlNlvt9Zaa+XGG2/M3nvvnZkzZ9ZkRlu0trbms5/9bMqyrJQ/6aSTctVVV6WhoaFmnXr37p3hw4dnv/32y+OPP77S/Pe+972ceeaZ6dOnT7vmPffcc5k0adJKc4MGDcq5557brhmdoVevXjX9+QerosZ6FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA636LZC9MyeW69a3S5clFr5eyCCbNr2GTN0zp7YRbNXthl81qmzVstX8Nd+RyxarviiisyfPjwyvmjjjoqhx9+eO0Ksdr4xCc+kV/96lddOrN///65+OKL8+lPf7rms6ZNm1Y5u9Zaa9WwSed3aMu9rck23XTTXHrppTWfc+655+ayyy5La+vKP//dddddGTZsWKfNvvjiizN7drXPkkVR5JprrslWW23VafPfrm/fvhk+fHh23XXXzJo1q9Ka888/P4ceeminzP+P//iPytlvfOMb2WuvvTpl7vJsu+22+cEPfpDTTjutpnOquOqqq/LUU09Vyu633365/PLL09DQUONWSb9+/XL99ddnt912S3Nz8wqzkyZNyi9/+cv88z//c7tmPf3005Vyp5xySrp169auGUD71P7dBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAVtPC1pnpXANZQzz33XD7/+c9Xzvfs2TM//OEPa9gIlq2xsTEnn3xyxo0bl09/+tNdMnPatGmVs/37969hk87vMH369Bo2WX1cfPHFGTBgQM3nbLnllhk6dGil7N13391pc+fPn59LLrmkcv7MM8/M4Ycf3mnzl2eLLbbID37wg8r5kSNHZsyYMR2eO2bMmDz44IOVsjvuuGO+9KUvdXhmFf/0T/+Ugw46qEtmLU9LS0u++c1vVsr2798///d//5fu3bvXuNXfbLfddvnWt75VKXvppZe2e84rr7xSKbfffvu1ewbQPg31LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ1VrntaRl2rx611jtlC2t9a4Aq7y5c+fmwx/+cGbNmlV5zde+9rVsu+22NWwFf2+dddbJWWedlWeffTZXXHFFttpqqy6Z29LSkjlz5lTKdu/ePb169apxo5UbMGBA5eyMGTNqV2Q1sfvuu+e4447rsnlVZ40bNy5lWXbKzBtuuCFvvvlmpezaa6+dCy64oFPmVvFP//RP2WuvvSrnL7/88g7P/PWvf105+61vfSuNjY0dnlnVhRde2GWzluWPf/xjXnzxxUrZCy64IJtttlmNG/2jz33uc5Xmjh07NmPGjGnXjKampkq5QYMGtWt/oP267h15DVQUxWX17rAGKcuy/Kd6lwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOCdYeHkufWusFpqnbOw3hVglXfGGWfkscceq5x/z3vek6997Ws1bAR/c8IJJ+T000/PoYcemsbGxi6fP3/+/MrZvn371rBJdW3p0Zb7W1Odc845KYqiy+YNHTq0Um727Nl57bXXstlmm3V45hVXXFE5+6UvfSnrrLNOh2dWVRRFvvOd7+SII46olL/mmmvygx/8IN27d2/XvLIs83//93+Vsttuu22OO+64ds1prwMPPDAHHnhgRo8e3aVzl/j5z39eKbflllvmrLPOqnGbZevZs2fOPvvs/L//9/9Wmv3973+fPffcs80zFixYUClXj59L8E7nX13HfCpJWe8Sa4Aibz2P/1TvIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwztM5ZWO8Kq6VyYWu9K8Aq7aKLLsrVV19dOd+nT59cddVVaWxsrGEr+Jvf/e53efXVV3PUUUflmGOOye67796l8xcurP7zd1X5d9GWHgsWLKhhk1Vf//79c/zxx3fpzC233DIDBw7M5MmTV5p95plnstlmm3Vo3uzZszNixIhK2d69e+eMM87o0Lz2GDp0aHbZZZc8/vjjK81OnTo1d911Vw4//PB2zRo3blxee+21StkzzjgjRVG0a05HnHXWWRk9enSXz3399ddzyy23VMp+4QtfqOt73imnnJKvfOUrK32PvuWWW3L++ee3ef9evXpVyr366qvZeeed27w/0H4N9S6whigcHToAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgS5UtrfWusFoqW8t6V4BV1nXXXZevfe1rbVrzP//zPxk8eHCNGsE/am1tzf3335/zzjsve+yxRw466KDcdNNNKcuueX9fsGBB5WxjY2MNm1TXvXv3ytm23N+aaMiQIenTp0+Xz91pp50q5V5//fUOzxo1alQWLlxYKfuRj3wk6667bodntsdZZ51VOTtixIh2zxk5cmSlXFEUOemkk9o9pyM+9KEP1eV1edNNN6W1deW/c/Tq1Ssf//jHu6DR8q233no54IADVpobM2ZMpk2b1ub9119//Uq5P/3pT23eG+iYhnoXWEOUjg4dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0KXKlrLeFVZPrZ43WJYHHnggJ598csqy+r+R008/PaeeemoNW8HKjR49Osccc0ze9a535a677qr5vAULFlTONjY21rBJdW3p0Zb7WxMdccQRdZm73XbbVcpNnjy5w7NGjBhROXvCCSd0eF57HX/88WloaKiUbcs9vd3IkSMr5fbee+9ssskm7Z7TEb17986RRx7Z5XP/9Kc/VcoNGzYsa6+9dm3LVDB06NCVZlpbW/Pwww+3ee+tttqqUu6qq67KG2+80eb9gfar9pOClSkc7T4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACg67W01rvB6qm1rHcDWOU888wzOfroo9Pc3Fx5zV577ZX//u//rmEraJsnnngihx12WL74xS9m/vz5NZvT2lr952+3bt1q1qMt2tKjLfe3Jtprr73qMnfgwIGVclOnTu3wrHvvvbdSrm/fvjn88MM7PK+9Bg4cmAMOOKBSdty4cZkzZ0675jz88MOVcvV8LpLkiCOO6NJ5LS0tueOOOyplhw0bVuM21VT99zt27Ng2773bbrulKIqV5mbMmJGTTz458+bNa/MMoH0a610AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoMs1NtS7weqpoah3A1ilvPLKKxk6dGimTp1aec3mm2+eG264IT179qxhM1Znn/zkJ7P33nuvNLdgwYLMnz8/b775Zt544428+OKLefLJJzNr1qx2zW1tbc1//Md/5Lbbbsutt96ajTbaqF37rEhjY2PlbEtLS6fPb4+FCxdWznbv3r2GTVZ9u+yyS13mrr/++pVyzc3NHZqzaNGiPPHEE5Wy++67b93f5w855JDcfffdK821trbm8ccfzz777NOm/adNm5aJEydWyu6///5t2ruz7bfffl0678knn8zs2bMrZd/73vfWuE01O+20U6Xco48+2ua911lnney6664ZN27cSrMjRozI0KFD8+tf/zqbbbZZm2cBbVP9kxkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAGqJoLOpdYfXU4HmDJd54440MGTIkr776auU1AwcOzIgRI7LpppvWsBmruyOPPDJHHnlku9c/88wzGTVqVK6//vrceeedaWlpadP6Rx99NIceemhGjhyZjTbaqN09lqVHjx6VswsXLuzU2e3Vlueve/fuNWyyaltvvfXSp0+fuszu1atXpdz8+fM7NGf8+PFpbm6ulD3ggAM6NKsztKXDuHHjss8++7Rp/yeeeKJydu+9927T3p1tl112Sc+ePTv8GqhqzJgxlXJ9+/bN9ttvX+M21Wy88cZpaGhIa2vrCnMvv/xyu/Y/4YQTMm7cuErZ0aNHZ4cddsiZZ56Zz3/+89liiy3aNRNYuYZ6FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoakVjQ70rrJaKhqLeFWCVMHXq1Bx++OF57rnnKq9ZZ511ctttt2Xw4ME1bAbJ9ttvnzPOOCO33nprXnnllXz1q19N//7927TH008/nUMPPTSTJ0/u1G49evSonG1paenU2e21cOHCytm23N+aZuONN67b7J49e1bKzZ8/v0Nznn766crZXXfdtUOzOsNuu+1WOduWe1vihRdeqJRba621stFGG7V5/87UrVu3bLvttl027y9/+Uul3ODBg9PQsGr8XtLY2Ji11lprpbkJEya0a//TTjutTe+Rc+fOzX/+539m6623ztChQ3PppZdmypQp7ZoNLN+q8Q60+ivreHR1386eBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF2uoW/3eldYLRXdG+pdAepuxowZOeKII/LEE09UXtO/f//cfPPN2W233WrYDP7RxhtvnAsvvDDPPvtsTjrppDatffrpp/PRj340ixYt6rQ+3btX//m7YMGCTpvbEW3p0aNHjxo2WbX16dOnbrOLoqiUK8uyQ3MmTJhQObvDDjt0aFZn2GijjbL22mtXyrbl3paYOHFipdy2227b5r1rYfDgwV026/nnn6+U22KLLWrcpG169+690szrr7/err033HDDfPazn23zutbW1tx+++05/fTTs+GGG+Y973lPvva1r2XEiBGZPXt2u7oAf+M3/I4r6nxUUb7taG/3Fe21Ip1xDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBpug/sU+8Kq6WGvt3rXQHqqqmpKcOGDctf/vKXymv69OmTm266Kfvss08Nm8GKbbTRRvnVr36VK664Ij169Ki8btSoUfnBD37QaT169eqVhoaGStk5c+akLMtOm91eTU1NlbN9+rxzP1/06tWr3hVq7vXXX6+c3XrrrWvYpLptttmmUq4t97bExIkTK+U23njjNu9dCxtttFGXzXrttdcq5YYPH56iKFaZo8rrYMGCBZk3b167npd///d/r/yaXJayLPPQQw/lO9/5To444oisvfba2WOPPfLP//zPufrqq/PCCy+0e294p2qsd4HV3Kl1nN0tyeeS7Jak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uYi3DR48uKa5Pn36NLkEqvfu+qnHwmPQPK4v0ZKKxqule17PDpCiKM4qiqKjB70ervpjAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAY/Ue1j9DP7paUlRd0iJFMvRjq6X3sP5Vl0DDfeMb38j3vve9us7svPPO+eUvf5n29vYmVUH1vv3tb+fFF1+seX7nnXdueMPHP/7xDBw4sKbZ22+/PX/84x8b3vCvvv/972fmzJk1zW622WZZddVVm1xET/PpT3+65tlLL700t956axNr/tnLL7+c448/vub5ep5lbnbZZZcMHjy4ptnzzjsvd9555wLvrMVjjz2WE088sSW75ubggw+ua3bGjBlNrOFtzz33XE1zgwYNanIJVK+t6gDeUec8rq/ekorGW62GmXk9O0CS9OphLz89BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYBPUfPSyL7/KeqjNaYvFdVkn/dYZVnQEN93//93/59re/XdeZsWPH5pJLLknv3r2bVAXVu+6663L88cfXPL/kkktmp512anjH4osvnv3226/m+cMOOywdHR0N73jbww8/nBNPPLHm+a9+9atNa6HnWnvttbPJJpvUPL///vvnzTffbGLR//f5z38+r732Wk2zgwcPzu67777AOwcOHJgDDjigptnOzs7svffeTf94lGWZz3zmM5k+fXpT98zLpptuWvPnygMPPJAvfvGLTS5i2rRpeeaZZ2qaHTVqVJNroHptVQfwjqbO5f1lkiLJei1saaQNapiZ1vQKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqNHAjUdk8A4rVp3RVIN3WDEDN1626gxouO9973v55je/WdeZ7bbbLr/5zW/Sp0+fJlXxbnL//fenq6ur6ox/c/fdd2e33Xarq23PPfds2t+Lww47LL17965p9r777sv3vve9pnR0dXXlgAMOyJtvvlnT/Hvf+97stNNOTWmh5/v6179e8+y9996bww8/vIk1f3f++efn4osvrnn+oIMOypAhQxqy+4tf/GLNf4//8pe/5POf/3xD9s7N//7v/+a6665r6o5anXDCCTXPnnHGGTnuuOOaWFONjo6OqhP+4Re/+EXNPWuvvXaTa6B6bVUH8I5ee4f3FXO8vUxRFO9rVUwDbVfDzJRmRwA0wV+qDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoHkGb7F8Bu+wYtUZTTF4hxUzeIvlq86AhvvhD3+Yr33ta3Wd2XrrrXPppZdmscUWa1IV7zbHHXdc1ltvvfz+97+vOuUfrrnmmmy++eZ57bXXaj7Tv3//fPWrX21a03LLLZe99tqr5vlvfvObueGGGxrecfTRR+faa6+tef5//ud/UhRFwztYOHzoQx/K+uuvX/P8j370o5x99tlN67nllluy//771zw/YMCAHHrooQ3bP3LkyHz2s5+tef7MM8/MMccc07D9czr99NPzne98pyn3nh+bbLJJdt9995rnDz/88Bx77LFNLKpPWZa57LLL6vrz/Vfrr79+Tj755MycObOBZfWbPn16fvCDH9Q0u+KKK2bUqFFNLoLqtVUdwDt6KMm8/pX5qVaENEpRFMsl2TxJOY/Rh1uQA9BozfufHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPcLgLZbP4ru+JymqLmmQIll811UyeIvlqy6BhjvllFNy2GGH1XVmiy22yOWXX55+/fo1qYp3q7/85S8ZO3Zs1l133VxwwQV58803K+mYOXNmvvrVr2b77bfPa6+9VtfZL3zhC1lmmWWaVPZ33/72tzNkyJCaZjs7O7Pbbrvl7rvvbtj+s846K0cddVTN85tttln22GOPhu1n4fSDH/ygrvn9998/5513XsM7br755uy4446ZNWtWzWe+8Y1vZKmllmpox7e+9a0sueSSNc//7//+b772ta+lq6urYQ3HHXdcDjzwwIbdr1F+9KMfZemll655/ogjjshee+2VadOmNbGqe9OnT8+ZZ56ZddZZJ7vuumsmTpw43/d68sknc/DBB2fFFVfMt771rTz33HMNLK3d5z73uTzwwAM1zX7oQx9qcg30DG1VB/CO/trNtTJ//9HUZ4qiGNCinkY4KEmvt96e80dr5Rxvz07ycMuKABrjhSRXVB0BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDzDdx4RJbYY40UvduqTlkgRe+2LLHHGhm48bJVp0DDnXHGGfnCF75Q15kxY8bkiiuuSP/+/ZtUBcndd9+dPffcMyNGjMhBBx2U22+/PWVZNn3vjBkzcvrpp2eVVVbJ8ccfn66urrrOr7rqqjnyyCObVPf/Lb300jn66KNrnp88eXK22Wab3HDDDQu8+4c//GH233//mv88evXqlR//+McLvJeF3+abb56999675vnOzs7svffe+Z//+Z90dnY2pOGcc87Jtttum9dff73mM+973/vypS99qSH75zR06NB897vfrevM9773vWy//fZ58sknF2j3888/n9122y2HH374XGf69u27QDsWxPDhw3PuueemKIqaz5x33nl53/vel6uuuqqJZf9u0qRJOeSQQzJy5Mjst99+uffeext27xdeeCFHHXVURo0alY9//OO58sor09HR0bD7z80bb7yR3XffPeedd17NZ/bff/8mFkHPsXD/dGPRNXEu75/zu8gSSb7egpYFVhTF8km+kGRu/9p++7nuKsuyvv+tAO9KZVnuVZZl0YpXkh/MI+f8siyb/y9aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6hP7rDMvSB6+XPqMGV50yX/qMGpylv7h++q8zrOoUaIpjjjkmZVnWdebGG2/MwIEDUxRFj3rttddezfkgUalXXnklp5xySjbeeOOMGDEi++yzTy666KI8+eSTDdsxe/bsjB8/Pl/4whcycuTIHHjggXnmmWfqvk97e3vOO++89O/fv2Ft3fnc5z6XTTbZpOb5l19+OVtttVW+9a1vZcaMGXXve+qpp/Kf//mfOeyww9LV1VXzuS996UsZPXp03ftYNH3/+9/P8ssvX/N8WZb57ne/m4022ig33XTTfO995JFHsuuuu2afffap6/O/T58+Ofvss9Pe3j7fu7uz33775cMf/nBdZ6655pqsscYaOfzww/PUU0/VdfaFF17IUUcdldVWWy2XXnrpXOcGDBiQr3zlK3Xdu9F23HHHfO1rX6vrzOOPP54PfehDGTNmTC6//PJ0dnY2vKuzszM333xzvv71r2e11VbLf/zHf+TEE0/MlClTGr7rbbNnz86vfvWr7LTTThkxYkQ+97nP5aqrrpqvr+Xd6erqyoUXXpj11lsvv/zlL2s+t/3222edddZpaAv0VM35bsCCujpJV5IiSfnWr3N6+32HFUXxm7IsJ7W4r2ZFURRJzkrSL+/8LG8rk4xrVRdALYqi6J3kv+cxdnYrWgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6Dl6D+ufYQesk2k3P5vXxj2edHRVnTRv7W0Zsv2KGfiBESnaiqprAEjy/PPP55xzzsk555yTJFl22WWz3nrrZY011sjqq6+e5ZdfPsOHD8/SSy+dgQMHpm/fvunTp086Ozvz5ptv5o033siLL76YF154IY888kgefPDBTJo0KRMnTsz06dMXuO+0007LJptsssD3qVWvXr1y0UUXZb311svkyZNrOtPZ2ZmjjjoqZ555Zg455JB88pOfzIgRI7o9c+edd+bcc8/NGWeckZkzZ9bV+IEPfCDHHHNMXWdYtC2xxBK55JJL8sEPfjCzZs2q+dwdd9yRMWPGZPPNN88BBxyQHXfcMYsvvni3Z2bNmpUJEybkrLPOym9/+9vMnj277t6TTz45G264Yd3n6nHWWWdlvfXWy9NPP13zmRkzZuS4447LCSeckM033zzbbbddNthgg6y22mpZYokl0r9//8yYMSOvvvpqHnroofz5z3/OH//4x1x77bU1fRy+853vZPDgwQvyWA1xzDHH5Jlnnsn5559f17mbbropN910U5ZddtnstttuGTt2bDbddNMMHTq07oYXX3wx9957b2677bbcdtttufHGGzNlypS679MoL730Uk477bScdtpp6devXzbddNNsttlm+cAHPpB11lknw4cPr+t+nZ2duf322/O73/0ul1xySR5++OG6zvfu3Ts//OEP6zoDC7P2qgP4d2VZTi6K4vYkmyQp/+Vy8db7yiR9klxcFMUmZVm+0OLMWn0nyTb5e++8fhp1RfNzAOqyc5Jh3Vy/pSzLB1oVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAz1G0FRk0ZmT6rjE0r17yUN584vWqk+aqz6jBGfqx1dJ7qX5VpwDQjeeeey7PPfdcrrrqqqpTctRRR2Xfffdt+d4VVlghF1xwQXbeeed0dXXVfO6ZZ57JV77ylRx++OFZc801s+GGG2bkyJFZfPHFM3v27EyZMiUPPfRQJk2alKeffnq+2oYNG5aLLroo7e3t83WeRdf73//+nHbaadlnn33qPjthwoRMmDAhvXr1yujRo7PWWmtl1KhRGTRoUHr16pVp06blueeeywMPPJBJkyZl+vTp89154IEHZv/995/v87VaaqmlcsUVV2TMmDGZOnVqXWc7Oztz7bXX5tprr21Yz9ixY3PQQQfl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X79++cpXvpL7778/O++8c9U5UKn2qgPoXlmW44ui+F6SI5KU3YwWb10v33q7SLJqku8nOb4oiklJrklyS5JJZVm+WG9LURR9kqyVZNMkY5Jsn2TIHPszR2ORdzbnMzyTZO96OwBaYJ95XD+7JRUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACxS2vq2p+97Fk/f9yz+j/d1zezI7Benp2t6R8rZXUlHV8qOrhTtbUl7W4rebWnr357eS/dPW9/26uIBqNvIkSPz+c9/Pp///OczderUjBs3Lr/73e8yfvz4PPPMMy3v6devX3bYYYf813/9V3bZZZf06tWr5Q3zq3///vn2t7+dvfbaK9/73vfy85//PDNmzGjojmWWWSYHHnhgDj300AwePLih9+bdqSiK7LvvvvnUpz6VM888MyeccEKeeOKJpuwaMmRIPvvZz+awww7LsGHDmrKjEXbffffstttuOeecc3LqqafmnnvuWeB7vv/9789XvvKV/Od//mfa2toaUFmdVVddNb/61a/y+OOP59RTT80555yTl19+uWX7l19++ey444758Ic/nG233TZ9+vRpyH3Hjh2bsWPHJknuvvvuXHnllbnqqqvypz/9KbNnz27Ijlosu+yy+cxnPpPPfe5zWXbZZVu2F3qyoizLqhuYh6Io2pJcmmSnJGWSYh5H5vxDLeby/teSPJzkuSQvJZmSZFaSN5P0SrJYkv5Jhr31WjHJCknm/E47t3vPra+c4/rUJFuXZTlpHs8C0FJFUQzK3782DpjLSEeS5cqyfKF1VYuWoiheTzJobtcHDRqU119/vYVFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDPOjs78+CDD9Y8v9pqq6VXr15NLAIAFjVPPPFEbr311tx666255ZZbcvfdd2f27NkN3dHW1pb3vve9GTNmTLbccsvssMMOGTBgQEN3VOWVV17J2WefnUsvvTS33357Ojs75+s+AwYMyJZbbplPfOIT+fjHP54+ffo0uBT+v66urtxwww258MIL87vf/S7PP//8At1v8ODB2WabbbLHHntkp512St++fRtU2jq33357rrjiiowbNy533XVXTV8Hl1pqqay77roZO3Zsdt5556yyyiotKK1GR0dHbrjhhlx22WX5/e9/n4ceeqhh9y6KIiuttFI23njjjBkzJh/84Aez1lprNez+tZg5c2YmTZqU22677R+vZ555pqE7VllllWy//fbZZZddsuWWW6a9vb2h9+9p3g0/zxg8eHCmTp3a3cjUsiwHt6pnYVeUZVl1AzUoiqJvknFJxiQpkxQ1HJvzD3du87V+ArzT+X89211TOcfMrCQ7lWU5vsbdAC1TFMW+Sc7oZuTSsix3a1XPoqgoiteTDJrb9UGDBuX1119vYREAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/LPOzs48+OCDNc+vttpq6dWrVxOLAIBF3ZtvvplHH300jzzySB5++OE88sgjeeSRR/LSSy9l2rRp//Tq6urKYostlsUWWyx9+/bNkksumeHDh2fppZfOCiuskDXWWCNrrLFG1lprrQwePLjqR2u6V199Nddee23uueee3H///XnwwQczefLkTJ06NdOmTUuvXr0yaNCgDBw4MMOHD8+aa66ZNddcM+uvv37GjBmTxRZbrOpH4F3qkUceyc0335y//OUvefTRR/PYY4/lxRdfzPTp0/PGG2+kq6sr/fv3T//+/TN06NCstNJKWXnllbPmmmtm0003zejRo9PW1lb1YzRMR0dHHn744Tz88MOZMmVKpk2bls7OzgwaNCiDBg3KkksumTXWWCNLL7101amVefXVVzNx4sTceeedeeyxx/LEE0/kqaeeypQpUzJ9+vTMmDEjb775Znr37p3FFlssAwYMyBJLLJGllloqI0aM+Mfn0BprrJF11lmnR36PePHFF//p++AjjzySJ554Iq+99to/vg9OnTo1M2fO/KfnHDZsWIYPH54VVlghq6++etZcc81stNFG77rPl3fDzzMGDx6cqVOndjcytSzLnvfJ3UMVZVlW3UCNiqIYkOSSJNsnefsPrqjh6Nz+kGs524h7zNk6NclHy7K8uo7dAC1TFMWtSTbuZuTDZVn+rlU9i6KiKF5PMmhu1wcNGpTXX3+9hUUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8M86Ozvz4IMP1jy/2mqrpVevXk0sAgAAAOjeu+HnGYMHD87UqVO7G5laluXgVvUs7NqrDqB2ZVm+URTFTklOS7JvkvKtVzGPo+90/e2z9ZrXrnfa8/a5p5PsVJblX+ZjL9BARVEslmS1JMsnGfTWq2+SaUmmJnk9ySNJHi/LsquqzlYrimLNJBt3M/JckqtalAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABN0V51APUpy7Izyf5FUdyY5MdJBiUp37pc1HGrembnRznH20WSy5N8pizLV5q8F/6hKIrhSTZMsk6SxWo8dn1Zltc3LaoiRVEskWS7JGOTbJxk5SS9ajg6syiKB5JMSHJVkgllWc5qWmj19pnH9fPe+joMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC632qgOYP2VZXlAUxc1JfpJkmyTlW68kKSoL+/8Nyd87XklyRFmWZ1bUw7tEURRLJ9kgyYZz/DpyPm93fYOyKlcUxVZJDk6yU5Je83GLvknWfev1xSTTiqI4L8nJZVn+rUGZPUJRFO1J/nseY2e3ogUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACaqb3qAOZfWZaPJtmuKIoPJzk+yapvX5pjrGhFyr/8vkgyO8lpSb5VluWUFjTwLlIUxVJJNkyywRy/Ll9pVA9TFMUWSX6UZHSDbz0wyeeTfK4oisuSHFaW5WMN3lGVnZIM7+b6jWVZPtSqGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiW9qoDWHBlWV5eFMUVST6S5EtJ3v/2pbdecyoasfId3vf2fV9PcnqSE8uyfLYBu3iXK4piySQbJNlwjl9XqDSqByuKYukkP0qyR7NXJdk1yfZFURyb5DtlWXY0eWez7TOP62e1pAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACarL3qABqjLMuuJL9K8quiKNZL8qkkH0+y3Jxjb70aoZjj7dlJ/pjkF0kuK8vyjQbt4F2sKIofJtk1yYrVliw8iqL4jyS/yT//vW+2fkmOSrJVURQfL8vyxRbubpiiKJZJsmM3I6/n719jAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYKHXXnUAjVeW5Z+T/DnJl4uiGJ1ky7deGyZZtgErZia5L8mNSa5NMqEsy6kNuC/MacskK1YdsbAoiuKTSc5OslhFCZsnuaMoig+VZfmXihoWxKfT/ffEX5ZlOb1VMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBM7VUH0FxlWd6d5O4kP0qSoiiWSLJ2kpWTLPvWa6kk/ZL0TdInSWeSWUlmJnk9yXNvvZ5O8tckD5dlWbbyOYC5K4pijyQXJGmrOGW5JNcURbFFWZb3V9xSr73ncf2sllQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAC7RXHUBrlWU5OcmNb72AhVxRFLsmOT9JW8UpbxuWZHxRFJuVZflI1TG1KIriA0lW72bkvrIsb29VDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRbe9UBAMyfoijWTPKzzN/X8geSXJzkT0nuSzI5yfQkQ5IMT7JukjFJPpZkyTrvvUyS3xZFsVFZljPmo63VPjOP62e3pAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABapK3qAADqVxRF/yS/SjKgzqM3JxlTluWaZVl+syzLK8uyfLwsy9fLsuwoy/KVsizvL8vywrIsP5tk2SR7J3mqzj3vS3JKnWdariiKgUk+1s3I7CQXtCgHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWqKt6gCAJno0ya+SXFZ1SBMcn2TtOubfTPL5siw3K8vyploPlWU5uyzLc5OsnuTcugqTvYui+GidZ1rt40kGdnP98rIsX2pVDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALRCe9UBAA3yaJI73npNSnJnWZavJklRFHsl2aW6tMYqimL9JAfWcWRqkh3KsrxlfneWZTkjyd5FUdyT5IQ6jv6gKIrfl2X5xvzubrLPzOP6WS2pAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBZqrzoAYD48muSOOV9lWb5abVJrFEVRJDklSVuNR2YmGVuW5S2N2F+W5Q+KouiT5Ls1Hlk+yf8mOaIR+xupKIrVk2zazcgzSca1KAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABapr3qAIB5eDTJHXO+yrJ8tdqkSu2WZOM65r9YluVNjQwoy/LYoig2TPKRGo8cWhTFiWVZPt/IjgbYZx7Xzy3LsqslJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBC7VUHAMzFZ5I8Wpblq1WH9DBfq2P20rIsf9qkjs8k2TTJsjXMLpbk0CSHN6mlbkVRtCfZs5uRMsnZLcoBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAlmqrOgDgnZRleUdZlq9W3dGTFEWxVZL/qHF8ZpJDm9VSluVrSQ6v48iBRVEMaVbPfBibZJlurk8oy/LRVsUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAK7VVHQBAzQ6uY/bHZVk+3qyQt/wsyV01zg5OslfTSuq3zzyun9WSCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKhAW9UBAMxbURRLJhlb4/jsJD9qXs3flWVZJvl+HUf+u1kt9SiKYniSD3Uz8lqSX7coBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFqureoAAGryiSS9a5y9pCzLZ5oZM4dfJnm2xtkNiqJYo5kxNdozSXs3139RluWMVsUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAq7VVHcC7Q1EUg+f1qroRerhP1jF7ftMq/kVZlh1JLqrjyKea1VKHvedx/ayWVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBF2qsOWFQURbHCvGbKsnyyFS091JQkZTfXy/h8hHdUFMXQJJvUOP5ykmuamPNOfp7ksBpnxyb5RhNbulUUxSZJ1uxm5C9lWU5qVQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUob3qgEXI40nKbq6X8fEuqg6AhdRWSdpqnL2yLMuOZsb8q7Is7yyK4pkkI2sYX68oiqXKsny52V1z8Zl5XD+rJRUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQofaqAxYxRaXLi+Lgec2UZXlSK1rmtn4u76/04wYLge3qmL2maRXz3vvpGuaKJNskuai5Oe+wuCgGJPl4NyNvJvl5i3IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgMu1VByxiyrm8v2jR/h910/C2k1rQ0Z1//VjMqxdItqxj9pqmVcx776drnN0yyUVNbJmbjyUZ1M31S8uyfKVVMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCV9qoDFkHFv/y+7AENb6uiBVgARVEMSbJKjeNPlGX5fDN7unFbHbMbNK2ie/vM4/pZLakAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAirVVHUBTlO/wAhZO6yUpapy9o5kh3SnL8uEkU2ocf29RFL2bmPNviqJYNcmYbkaeTHJNi3IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgUm1VB9AUxb+8gIXX+nXM3tm0itrcUePcYknWbmbIO9hnHtfPLcuyqyUlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAULG2qgMA6NY6dcz+tWkVtXmgjtnRTav4F0VR9EqyZzcjZZJzWpQDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlWurOgCAbq1cx+zDTato/P56nmtB7ZhkRDfXx5dl+XiLWgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKBybVUHANCtleqYfbhpFbV5qI7Zep5rQe0zj+tnt6QCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeoi2qgMAeGdFUfRJMqLG8ZfLspzezJ4aPFnH7EpNq5hDURTDkuzUzcirSX7bihYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoKdqqDgBgrkal9q/TzzczpEb1NKzUtIp/tmeS3t1c/3lZljNb1AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9QlvVAQDM1fA6Zp9vWkXtXk7SUePs0s0MmcPe87h+dksqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAdpqzoAgLlaoo7ZF5pWUaOyLMskL9U43rsoikHN7CmKYqMka3cz8ueyLP/czAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoidqqDgBgrpasY/a1plXUp56Oep5vfuwzj+tnNXk/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9EjtVQcAMFdL1jE7tWkV9amnY4kkjzcjoiiK/kl272ZkZpILm7G7pyqK4ogkR1Td8ZZBVQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8m7VXHQDAXC1ex+zrzYqoUz0dizcrIslHkwzu5vpvy7J8tYn7e6LFkgyqOgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDqtVcdAMBcLVbH7BtNq6hPPR31PF+93khyVDfXf9PE3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCjtVcdAMBc9a5jtqNpFfWpp6NPsyLKsvx1kl836/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwMGurOgCAuepTx2xH0yrqM7uO2XqeDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiQtqoDAJirPnXMdjStoj71dNTzfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECDtFUdAMBc1fM1urNpFfWpp8P3IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKhAW9UBAMxVRx2z7U2rqE/vOmZnN60CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmKv2qgMAmKs365jt3bSK+tTzfWV20yp4J7OSTK064i2Dqg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4N2uvOgCAuXqzjtme8vW8dx2z9TwfC6gsy+8m+W7VHUlSFMXrSQZV3QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPBu1VZ1AABzNbuO2T5Nq6hPPR1vNq0CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmKu2qgMAmKs36pgd1LSK+tTTMb1pFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBctVUdAMBcTa5jdnDTKupTT0c9zwcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0SFvVAQDM1eQ6Zgc1raI+9XS80rQKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYK7aqg4AYK5eqWN2iaZV1GdoHbOTm1YBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzFVb1QEAzNUrdcwu07SKGhVFsViSoTWOTyvL8s1m9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvrK3qAADm6uk6ZpdtWkXt6mmo59kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACABmqrOgCAd1aW5fNJZtQ4vkwzW2pUT8NjTasAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAutVWdQAA3Xq8xrl+RVEs28yQGrynjtnHmlYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdKut6gAAuvVYHbOrNK2i8fsfbVoFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0K22qgMA6Nbf6phdtWkVjd//YNMqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgG61VR0AQLf+XMfsOk2rqM3oOmbvbFoFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0K22qgMA6Naddcxu0LSKeSiKon+SNWscf7Esy2ea2QMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMXVvVAQB064Ek02ucXa8oiqq+rq+bpFeNs3c2sQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYh7aqAwCYu7IsO5NMrHF8QJINmpjTnc3rmL2taRUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAPLVVHQDAPF1dx+y2Tato3N56ngcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABosPaqA95NiqJ4VAMwH65O8u0aZ7dL8p0mtvyboigGJNm0xvHXkvypiTkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAPLRXHfAuUMzx64ot3Fdlw9y8Uxswb5OSvJpkaA2zY4qiWLYsy+ea3DSnXZMsVuPsdWVZdjSxBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJiHtqoD3mXKJr96QsOCtAHvoCzLriSX1TjeluQTTcx5J5+sY/Y3TasAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAatJWdQAANbmgjtl9m1bxL4qiWCHJdjWOT0/y2ybmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVoqzrgXaZo8qsnNCxIGzB31yd5usbZtYui2LGJLXM6JEl7jbO/LctyWhNbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBq0VR0AwLyVZdmV5Nw6jvxvk1L+oSiK4Un2rePIOc1qAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGrXVnUAADX7cZKZNc5uWhTFHs2MSfLdJINqnL2jLMvxzYwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAatNWdQAAtSnL8oUk59Zx5ISiKIY1o6Uoiq2S7FXHke81owMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoX3vVAQDU5bgk+yTpU8PsskkuKIpibFmWXY0KKIpieJKfJylqPPLXJL9u1H6qUxTF55N8rgG3GtCAewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCf2qsOWASVVQcAi66yLB8riuKEJEfUeGT7JKcXRbF/WZYL/PWpKIqhScYlWaaOYweXZdm1oLvpEYYlWavqCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZMW9UBi5jCa75eQH2+neSpOub3TXJuURR9F2RpURQrJrk2yeg6jl1SluU1C7IXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaKz2qgMWIStVHQCLmqIotkhyXYvXfrMoim824D57l2V5bgPu82/KspxeFMVnk/wuSVHjsT2TjC6KYr+yLCfWs68oiiLJp5KclGRoHUcnJzm0nl0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA87VXHbCoKMvyiaobgHePsiyvLIrihCRfruPY6CS3F0Xx6yQ/TTK+LMuuuQ0XRTEoyUeSHJxkvXoTk/x3WZZP13kOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaLL2qgMAmG9HJNk4yWZ1nCmSfPSt16tFUUxKcm+SV5PMSDI4ydJJ1ksyOsli89l2bFmWV83nWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaJhzzz03e++99zznPv3pT+fcc89tfhBAD9BedQAA86csy46iKHZJcl2SdebjFkOTbPvWq5HOTfL1Bt+TnuGlJPc34D5rJGlrwH0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYD+1VBwAw/8qynFwUxTZJrk+yVsU5SXJRks+UZVlWHULjlWV5SpJTFvQ+RVG8nmTQghcBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0RmdnZ+6///7ce++9eeCBB/Lggw/mmWeeyfPPP5/JkydnxowZmTlzZvr06ZO+ffumf//+WXrppTNixIgst9xyWXvttbPOOutk3XXXzeKLL17148C71vPPP5+//e1vefXVVzN16tRMnTo1vXr1yqBBgzJo0KAsvfTSWXPNNTN48OCqUwEAKtdedQAAC6Ysy5eKohiT5JdJtqkw5fgkR5Rl2VVhAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzT1KlTc9NNN+X666/PzTffnD//+c+ZPn36PM/NnDkzM2fOzJQpU/Lss8/mrrvu+qfrbW1t2WCDDbL11lvnox/9aDbYYIMmPcHC58gjj8zRRx9d0+wSSyyRa6+9NqNHj25y1aLppZdeyimnnFL3uRVXXDF77bVX44OapCzL3HHHHfn973+fq6++Ovfcc0+mTJlS09mRI0dmvfXWyw477JCxY8dmpZVWam4sAEAP1F51AAALrizLyUVR7JDku0m+nKRo4fppSfYty/KXLdwJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdbn//vtz5ZVX5oorrsgtt9ySjo6Ohu/o6urKxIkTM3HixBx77LFZa621su+++2a//fbLwIEDG75vYXH00Ufn6KOPrnl+8uTJ2WabbXLdddflve99bxPLFk0HHXRQLr744rrPbb755tlrr70aH9Rgr7zySn7605/m1FNPzdNPPz1f93jmmWfyzDPP5IorrkiSbLjhhjn44IPziU98In369GlkLgBAj9VWdQAAjVGWZWdZll9NsmmSO1u09ldJ1ijL8pct2gcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1u+eee/KNb3wjq6++etZee+189atfzQ033JCOjo6W7L///vtz2GGHZdSoUTn66KMzY8aMluztSY499tgceeSRdZ97+eWXs/XWW+f+++9vQtWi6ze/+U0uvvjiqjOaYurUqfnyl7+c5ZZbLv/zP/+Tp59+umH3njRpUvbcc8+ssMIKOeOMM1KWZcPuDQDQU7VXHQBAY5VleVtRFP+R5NNJDk3yvkavSDIuyffKsry+wfcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB3lZkzZ+all17K9OnT09HRkY6OjnR2dqZXr15pb29Pe3t7+vfvn2HDhqVv375V58JC4YUXXsjP38ceGAABAABJREFUf/7znHvuubnnnnuqzkmSTJ48OUceeWTOOeecnHzyyfnQhz5UdVJLnHDCCTniiCPm+/yLL76YrbfeOtdff31WX331BpYtmiZPnpzPfe5zVWc0xcUXX5xDDz00zz77bFP3vPDCC9l///1z5pln5vTTT8+6667b1H0AAFVqrzoAYG7Ksrw+SVF1x8KoLMuuJOckOacoiq2S7JlkhyTDF+C2DyS5MskZZVn+bcErAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg3WXmzJl57rnn8uyzz/7j18mTJ9d8fokllsiIESOy7LLL/uPXvn37NrEYFj5XX311xo4dm46OjqpT3tFjjz2WnXbaKQcddFBOOOGE9OnTp+qkpjnxxBPz5S9/eYHv8/zzz2errbbK9ddfn1VXXbUBZYuugw8+OC+88ELVGQ01e/bsHHrooTnllFNauvdPf/pTNtlkk/zkJz/Jpz/96ZbuBgBolfaqAwBorrIsr01ybVEURZL1k2ySZM0kayVZLsmgt159k7yRZGqS15I8muSvSe5Lcn1Zlo+3PB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZyr732Wu68887cf//9eemllxboXpMnT87kyZNz7733/uN9w4YNy1prrZX1118/Q4YMWdBcWOi99tpr6ejoqDpjnn784x9n4sSJufLKK7PkkktWndNwp556ag455JCG3e/ZZ5/NVlttlQkTJmTllVdu2H0XJb/73e/y85//vOqMhpoyZUo+/OEP58Ybb6xk/8yZM7PXXnvlz3/+c374wx+mKIpKOgAAmqW96gAAWqMsyzLJHW+9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAJunq6spjjz2WiRMn5m9/+1vKsmzarpdeeikTJkzIDTfckNVXXz3/8R//kZVWWiltbW1N2wk0xu23354PfvCD+eMf/5iRI0dWndMwP/3pT3PQQQc1/L5PP/10ttxyy0yYMCErrrhiw++/MJsyZUoOPPDAqjMaaurUqdlhhx1y++23V52SE088MR0dHfnxj39cdQoAQEO1Vx0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsCiYMWNG7rrrrkyaNCmvvPJKS3eXZZkHHnggDzzwQJZccslsuOGGWXfdddOvX7+WdgD1uf/++7P99tvn5ptvzpAhQ6rOWWBnn312DjzwwJRl2ZT7P/nkk9lyyy0zYcKErLDCCk3ZsTA69NBD8+yzz1ad0TAzZszI2LFjc/vtt1ed8g+nnHJK+vXrl+OPP77qFACAhmmvOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYdbV1ZXbb789119/fWbNmlV1Tl555ZWMGzcu119/fbbYYotstNFGaWtrqzoLeryiKPKe97wnG264YdZff/2svPLKWXHFFTNixIgMGDAgAwYMSEdHR9544408++yzeeSRR3LnnXdm/Pjxue2229LZ2Tlfe++777585CMfybhx49KrV68GP1XrnH/++dlvv/1SlmVd55Zeeum8+OKLNc8//vjj2WqrrTJhwoSMHDmy3sxFzh/+8Iece+65VWc01EEHHZSbbrqp7nP9+vXLhz/84Wy99dbZYIMNstxyy2XxxRfP7NmzM2XKlDz44IO54447ctlll+Xmm2+u+3P1+9//ftZdd9186lOfqrsNAKAnaq86AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBh9fLLL+eyyy7LU089VXXKv5k1a1bGjRuX+++/P7vsskuWWmqpqpOgx1lqqaWy4447Zvvtt892222XYcOGdTvfq1evLLbYYlliiSXy3ve+N7vsskuOOuqovPDCCzn77LPzox/9KC+++GLdHePHj8/3v//9HH744fP7KJW68MILs/fee6erq6vmM0VR5IQTTsjee++dXXfdNRMmTKj57COPPJItt9wyEyZMyLLLLjs/yYuE119/Pfvvv3/VGQ11/vnn5+yzz67rzMCBA/PlL385hx56aAYPHvxv1/v06ZMBAwZk5MiR2XLLLfPlL385Dz/8cI488shcdNFFKcuy5l0HHHBA1l9//ay55pp1NQIA9ERtVQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGy6urpyyy235Cc/+UmeeuqpqnO69dRTT+UnP/lJbr311nR1dVWdA5UbOHBg9txzz1x11VV57rnncv755+dTn/pUhg0bNt/3HD58eI444og8+uijOeKII9Le3l73Pb75zW/mgQcemO+Gqlx88cXZc8896/r60qdPn/ziF7/IoYcemsUXXzzjxo3Lxz/+8br2PvTQQ9lqq63ywgsv1Ju8yPjKV74yz+9B//mf/9mimgX3xBNP5LOf/WxdZzbZZJP89a9/zTe/+c0MHjy45nOrrLJKLrzwwowfPz7Dhw+v+dwbb7yRPfbYI52dnXV1AgD0RG1VBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsTF5++eWcc845+eMf/5iOjo6qc2rS0dGRcePG5ZxzzsnLL79cdQ5UYu21187JJ5+cZ555Juedd1523HHHtLe3N3THgAED8p3vfCc33nhjll122brOzpo1K1//+tcb2tNsv/nNb/KpT30qnZ2dNZ8ZMmRIxo0bl0984hP/eN9iiy2Wiy66KIccckhd+x944IFstdVWeemll+o6tygYP358fvrTn3Y7s9JKK+Xoo49uUdGCO+SQQzJ9+vSa53ffffdMmDAhyy233Hzv3HLLLXPnnXdm9dVXr/nM3XffnVNOOWW+dwIA9BRtVQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzuvffe/OQnP8lTTz1Vdcp8eeqpp/KTn/wk9957b9Up0DJbbLFFxo0bl3vvvTcHHXRQBg8e3PSdG2+8cW677basvPLKdZ37zW9+k7vuuqs5UQ122WWXZffdd09HR0fNZ0aOHJkbb7wxW2yxxb9dK4oiP/zhD3P88cenKIqa73n//fdn6623zssvv1zzmYXdtGnTsu+++85z7qc//Wn69+/fgqIF94c//CGXXnppzfO77rprLrjggvTu3XuBd48YMSLXXnttVlpppZrPHHnkkXnxxRcXeDcAQJXaqg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWBj86U9/yiWXXJKOjo6qUxZIR0dHLrnkkkycOLHqFGiqHXbYIbfeemuuu+66bLfddi3fv8IKK+Saa67JUkstVde5008/vUlFjXPllVfm4x//eGbPnl3zmbXWWiu33npr3ve+93U79+Uvfzk/+9nP0qdPn5rvfc8992TbbbfN5MmTaz6zMPva176Wxx9/vNuZvfbaK9tss01rghrgq1/9as2zq622Wi644IK0t7c3bP+IESPyq1/9qubPu9deey3HHHNMw/YDAFShreoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgJ7uxhtvzFVXXVV1RkNdeeWVufHGG6vOgIbbeOONc/311+f3v/99Nt5440pbVlpppfzsZz+r68xFF12UWbNmNalowY0bNy4f+chH8uabb9Z8ZsyYMbnpppuy/PLL1zT/yU9+Mr///e8zePDgmnfcdddd2XbbbTNlypSazyyMJkyYkFNPPbXbmeHDh+eEE05oUdGCu+qqq3LPPffUNNvW1pZf/OIXGThwYMM7Nthgg3z729+uef7MM8/MK6+80vAOAIBWaas6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAnu/HGGzN+/PiqM5pi/PjxufHGG6vOgIbZcccdc+utt2bzzTevOuUftt9++3zyk5+seX7KlCm55ZZbmlg0/6655prsuuuumTVrVs1nPvKRj+SPf/xjhg4dWteurbbaKjfccENGjBhR85k777wz2223XV5//fW6di0spk+fns985jMpy7LbuZNPPjlLLLFEi6oW3LHHHlvz7H777Zf111+/aS2HHHJIVl999Zpmp0+fnpNOOqlpLQAAzdZWdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABATzVx4sSMHz++6oymGj9+fCZOnFh1BjTEgAEDqk54R0cddVTa2tpqnr/uuuuaWDN/rrvuunz4wx/OzJkzaz7zhS98IRdffHH69u07XztHjx6dW2+9NWuuuWbNZyZOnJgddtghU6dOna+dPdnXv/71PPLII93O7LLLLvnYxz7WoqIFd9ddd+XGG2+sabZfv345+uijm9rTu3fvHHvssTXPn3baaeno6GhiEQBA89T+PxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAd5F77703V155ZdUZLXHllVfm3nvvrToDFlmrrLJKttpqq5rnJ06c2MSa+t14443ZeeedM2PGjJrmi6LIsccem5NOOiltbW0LtHuFFVbITTfdlA984AM1n7n11lszduzYTJs2bYF29yS33HJLTjrppG5nBg8enFNPPbVFRY1x/vnn1zy71157ZdiwYU2s+btddtklq622Wk2zL730Uv7whz80uQgAoDkW7F/qAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIugl19+OZdeemnVGS116aWX5uWXX646AxZZu+22W82zDz30UBNL6nPLLbdk7NixeeONN2qa7927d84///wcfvjhDWtYYoklcs0112TXXXet+cxNN92UnXbaKdOnT29YR1VmzpyZffbZJ11dXd3OHXfccRkxYkSLqhZcZ2dnLrrooprnDznkkObFzKEoinzxi1+sef5nP/tZE2sAAJqnveoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgJ6kq6srl112WTo6OqpOaamOjo5cdtll2XvvvdPW1lZ1DixyxowZU/Ps448/nq6ursr/Lt5+++3ZcccdM23atJrmBw0alF//+tfZdtttG97St2/f/PrXv84XvvCFnHrqqTWdmTBhQnbeeedcccUV6devX8ObWuXII4/M3/72t25nPvjBD2b//fdvUVFjXHfddXnuuedqmt1oo42y2mqrNbno/9t9991zyCGHZPbs2fOcvfzyyzNt2rQMHDiwBWWLlldffTVXX3117r777tx333156KGHMmXKlLz++uuZMWNG+vbtm/79+2f48OFZaaWVstpqq2XTTTfNZpttlqWXXrrq/Ibp6urKM888k8ceeywvvfRS3njjjUyfPj2dnZ0ZMGBA+vfvn6FDh2allVbKqFGj0rt376qTG+qVV17J1VdfnYkTJ+avf/1rHnroobz22muZOnVqOjs7M2jQoAwaNChLLrlk1lhjjay99tpZb731ssUWWyzUX9sXxJQpU/Loo4/mmWeeybRp0zJ9+vTMmDEjffr0yYABAzJw4MCssMIKWXnllTNkyJCqcxuis7MzTz75ZJ577rm89NJLmTJlSmbNmpVZs2alvb09/fv3/6fX0KFDM2rUqAwdOrTqdOjR2qsOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOhJbrvttjz11FNVZ1Tiqaeeyu23355NNtmk6hRY5Ky66qopiiL/jz07j7O6Lhv/f50zAwyD7DtCICgumSQuuKMhuG+hpWQmLoDL7ZpZkqXmbprarZbgfqdW3ApobgTumELkhqmoiKDsyD4Ms/3++P667+pW+JzhnPOZwefz8Zh/4nq/r9fnODMcTnV1dRudrampiTVr1kTLli2LUPbFpk+fHgcddFCsXLky0XyXLl3iiSeeiJ133rlgTdlsNm677bbYcsstY/To0YnOTJkyJY466qiYOHFilJWVFaytUF577bW46aabNjhTVlYWY8aMiUwmU6Sq/HjiiScSz55wwgkFLPm/2rVrFwcffHA89thjG52tqKiIZ599No444ogilBXfc889FwcccMBG5wYOHBjPPffcRufWrVsX999/fzz88MPx4osvRnV19ZfOrlmzJtasWROLFy+Ot99+OyIibrzxxshms7HPPvvEsGHD4qSTTormzZsnfp6GYMWKFfH000/HSy+9FC+99FLMnDkz1q9fn+hsNpuNPn36xN577x377LNPDBkyJHr06FHg4vyrqKiIhx9+OMaMGROvvvpq1NbWfunssmXLYtmyZTFnzpyYMWPG//zv5eXlceCBB8aJJ54Y3/72t6OkpKQY6UW3bt26eP755+Pll1+Ol19+OWbMmBHLly9PfL5Tp06x1157xd577x0HH3xw7LjjjoWLzaNZs2bF5MmTY+rUqfHXv/41Pvjgg8Q/J/+sVatW0bNnz+jVq1f07ds3BgwYEHvssUej/LmBQihNOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgoViyZElMmTIl7YxUTZ48ObbZZpvo0KFD2imwWSkrK4u2bdvGsmXLEs2vXr06WrZsWeCqL/a3v/0thgwZEitWrEg0v+2228ZTTz0VvXr1KmzY/++SSy6J7t27x2mnnRZVVVUbnZ80aVJ8+9vfjkcffTSaNWtWhML8qKysjOHDh0dNTc0G5372s59F3759i1SVP5MmTUo8e9RRRxWw5IsdeeSR8dhjjyWanTRpUhxxxBEFLmrc1q5dG7/61a/i1ltvjUWLFm3SXbW1tfHCCy/ECy+8ED/72c/i4osvjnPOOSdKS0vzVJt/tbW1MX78+HjggQfiySefjMrKynrfM2vWrJg1a1bce++9kclkYp999olhw4bF97///WjRokWey/OrsrIybr311rj22msT/334ZdauXRsTJ06MiRMnRp8+feKiiy6K008/PbLZbJ5q01NXVxdPPvlkPPTQQzFhwoRYtWpVve9atGhRjB8/PsaPHx8XXXRR7LjjjvG9730vRo4cGW3bts1j9aZbuHBhjB07Nh566KGYOXNmXu5cuXJlvPXWW/HWW2/9y//etWvX2GOPPeLggw+OY445Jjp27JiXfdDYNP7fmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5UFtbGxMmTIjq6uq0U1JVXV0dEyZMiNra2rRTYLNTXl6eeLaurq6AJV/uzTffjMGDB8fnn3+eaH7PPfeMl19+OXr16lXYsH9z0kknxWOPPRZbbLFFovknn3wyjj322Fi/fn2By/LniiuuiHfeeWeDM/369YuLLrqoSEX5M3/+/Hj77bcTzfbp06fo318REQceeGDi2WeeeaaAJY3fM888EzvuuGP89Kc/jUWLFuX17kWLFsWFF14Yu+66a7z55pt5vTsfqqur45577ontt98+hg4dGuPHj4/Kysq83V9XVxcvvvhinHHGGdGrV6+46qqrYuXKlXm7P58mT54cO+ywQ/zoRz+KZcuW5fXuDz/8MEaNGhV77bVXzJw5M693F1NVVVXcc889scMOO8Rhhx0W//Vf/xWrVq3K64633347fvKTn0TPnj3jxz/+cSxfvjyv99fHp59+GiNGjIgePXrET3/606L8N5w/f348+uijMXLkyOjatWsceOCB8dvf/jZWr15d8N3QkGTTDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoCF599dWYO3du2hkNwty5c+PVV19NOwM2O6tWrUo8u8UWWxSw5IvNnDkzDjzwwFi6dGmi+SOPPDImT54c7du3L3DZFzvooIPiueeei86dOyeaf/zxx+O73/1uVFVVFbhs082YMSOuv/76Dc6UlJTEXXfdFaWlpUWqyp9nn3028eyBBx5YwJIv16tXr+jTp0+i2ffeey/mz59f4KLGp6amJs4999w46KCDYvbs2QXd9cYbb8Ree+0Vjz76aEH35GLatGmx2267xSmnnBLvv/9+wfctWbIkfvrTn8b2228f//3f/13wfUnV1NTE6NGjY8iQIfHRRx8VdNerr74a/fv3j/vuu6+gewph0qRJ8fWvfz1OOeWUePfddwu+b9WqVXHdddfFdtttFw8//HDB932Rurq6uOWWW6Jv374xZsyY1P5+rqmpicmTJ8eoUaNi+vTpqTRAWrJpBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkraKiIp577rm0MxqU5557LioqKtLOgM1GVVVVrFy5MtFsSUlJbLHFFgUu+ld///vfY9CgQbF48eJE8yNHjoxHHnkkmjdvXuCyDdtll11i6tSpsc022ySaHz9+fAwbNiyqq6sLXFZ/VVVVMXz48I02XnDBBbHLLrsUqSq/pk+fnnh2jz32KGBJ/nb/9a9/LWBJ47NixYo47LDD4tZbby3azjVr1sSxxx4bDz/8cNF2fpHa2toYPXp07LHHHvH6668Xff9nn30Wxx57bAwdOjRWrVpV9P3/rKKiIo455pi4+uqro7a2tig7169fHyeffHJceeWVRdm3qVasWBHDhg2LIUOGxKxZs4q+f+HChXHCCSfEsGHDYu3atUXbu2LFijjkkEPivPPOK+pe4F9l0w4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASNvrr78elZWVaWc0KJWVlfHGG2+knQGbjZkzZ0ZdXV2i2V69ekU2my1w0f96//33Y9CgQbFw4cJE81dccUX85je/iZKSkgKXJdO7d++YOnVqDBgwINH8uHHj4sQTT4yampoCl9XPVVddFW+++eYGZ/r06ROXX355kYryb8aMGYlnd9lllwKWbNiuu+6aeDaXZ9rcrVq1KgYPHhxPP/100XfX1tbGSSedFH/+85+LvjsiYsWKFXH44YfH1VdfHbW1tak0/MMjjzwSe+yxR8yaNSuV/atXr46DDz44HnvssVT2X3rppXHVVVelsjupt956K3bbbbd46KGH0k6Jhx56KPbaa6+YO3duwXctXrw49t5771R+RwD/qnj/4gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABogGpra2PatGlpZzRI06ZNi7q6urQzYLMwffr0xLN9+/YtYMm/+vDDD+Nb3/pWzJ8/f6OzpaWlcffdd8ell15ahLLcdOjQIaZMmRKHH354ovnf//738YMf/CBqa2sLXJabN998M66++uqNzt15553RvHnzIhTlX11dXbz++uuJZsvKymKHHXYobNAG7LrrrolnZ8yYUcCSxmPdunVx5JFHpvreqqqqKr73ve/FggULirp32bJlMXDgwHjyySeLundD3nnnndhrr73irbfeKure6urqOO644+KFF14o6t5/d+mll8bDDz+casOXeeqpp2KPPfaIWbNmpZ3yP954443Yf//9Y+7cuQXbsXr16jj44INj5syZBdsBJFeadgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAmmbPnh3Lli1LO6NBWrp0acyePTt69+6ddgo0ehMnTkw8u/vuuxew5H/Nnj07DjjggPj00083OtuiRYv44x//GIccckgRyuqnvLw8xo8fH6NGjYqxY8dudP53v/tdlJaWxt133x3ZbLYIhRtWXV0dw4cPj6qqqg3OnXrqqfGtb32rSFX5N2fOnFixYkWi2W222SZKSkoKXPTltttuu8Szb7zxRgFLGo/TTjstnnvuuUSzrVq1iv79+0efPn2iW7du0aJFiygpKYk1a9bEp59+Gu+9915MmzYtKioqcu5YtGhRjBo1KsaPH5/z2fpYvnx5DB48uEF+HyxZsiQGDRoUzz77bHz9618vys4zzzwznnrqqXqf79KlS+y8886x7bbbRrt27aK8vDzWrl0by5cvj/fffz9ef/31mDdv3kbvqauri+HDh8dOO+1U75ZCmDhxYhx33HGxfv36tFP+j48++ij233//mDp1anTu3Dnv95999tkxY8aMvN8L1E9p2gEAQOOQyWTOiogz83BVizzcAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQN9OmTUs7oUGbNm1a9O7dO+0MaNRWrFgRzzzzTOL5/fffv3Ax/785c+bEAQccEHPnzt3obKdOneLxxx+P3XbbreBdm6qkpCTGjBkTW265ZVx++eUbnb/vvvuitLQ0xowZE5lMpgiFX+7666+PGTNmbHCma9eu8ctf/rJIRYXx0UcfJZ7deuutC1iycR06dIg2bdrE8uXLNzo7d+7cqK6ujtLS0sKHNVBjx46N3/3udxuc6dq1a3z/+9+P73znO7HzzjtHNpvd4Pz69evjySefjNtuuy0mTZqUU8+ECRNi8uTJMWjQoJzO5aqmpiaGDh260Z/fL9O5c+c4+OCD44ADDogddtghevXqFS1btoySkpJYtWpVLFiwIP7+97/Hyy+/HE888US89957Oe9YvHhxHHLIIfHXv/41OnbsWK/OpB544IEYM2ZMzufatWsXp5xySpx44onRr1+/jc7PnDkzHnrooRg7dmwsXLjwS+fWrVsXw4cPjxEjRuTcVAjPPPNMHHvssVFVVVWv89/85jdj4MCBseuuu8bWW28dX/va16JVq1bRvHnzqKqqilWrVsWcOXPi3XffjZdeeikef/zx+PTTT3Pa8dFHH8Wxxx4bU6ZMiSZNmtSr84s89dRTcd9999Xr7LbbbhuDBg2K7bbbLvr06RO9e/eOli1bRosWLaJFixaRyWSisrIy1q5dG0uWLInFixfH7NmzY9asWfHOO+/EtGnTYt68eXl7FthcfHXftQAAueoYETukHQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkE8rVqyI9957L+2MBu3dd9+NFStWROvWrdNOgUbrzjvvjMrKykSzbdq0iT333LOgPfPmzYtvfetbMWfOnI3O9unTJ55++uno06dPQZvy7bLLLovu3bvHqFGjoqamZoOzd911V5SWlsYdd9wRmUymSIX/6p133okrrrhio3O//vWvo02bNoUPKqDZs2cnnt1mm20KWJLM1ltvHdOnT9/oXE1NTXzyySfRu3fvIlQ1PB9//HGcc845X/rn7du3j1/84hdxyimnRLNmzRLf27Rp0zjqqKPiqKOOimeeeSZOO+20mDt3buLzl1xySbz66quJ5+vjkksuiSlTpuR8buedd46f/OQnccwxx0RpaekXzrRr1y7atWsXO+ywQwwdOjRuuummeOmll+KGG26IiRMn5rRv7ty5cfzxx8czzzwTJSUlOfcm8dFHH8VZZ52V05kmTZrE+eefHz/96U+jZcuWic99/etfjyuvvDJ++tOfxvXXXx/XXnttVFRUfOHsa6+9lvjv4UJ677334rvf/W5UVVXldK5bt24xcuTIGD58ePTo0eNL50pKSqKsrCw6duwYu+66a5x44olRV1cXkydPjmuuuSan79OXXnopzj///PjP//zPnFq/TF1dXVx88cU5nenYsWOce+65ceKJJ0bPnj03Ol9aWhotWrSIjh07xvbbbx/77bffv/z5/PnzY/LkyfHnP/85Hn/88Vi6dGlOPbA5yqYdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCWGTNmRF1dXdoZDVpdXV3MmDEj7QxotNavXx+33npr4vnjjjsumjVrVsCiiO7du8eHH34YdXV1G/364IMPok+fPgXtKZTTTjstqqurEz3nb37zm8hkMql01tTUxPDhw6OysnKDc8ccc0wMHTq0SFWFM3v27MSzX/va1wpYkv+GXJ5tczNnzpyoqKj4wj876qij4t13340zzjhjk36/DRkyJKZNmxb9+/dPfOa1116LqVOn1nvnxkyaNCmuv/76nM6Ul5fHb37zm5g+fXocd9xxUVpamtP5ffbZJyZMmBCTJk2K7t2753R2ypQpcfXVV+d0JhejRo2KVatWJZ7/2te+Fi+++GJcd9110bJly3rtLCsri5/97Gfx2muvxbbbbvulc2+88Ua97s+XVatWxRFHHBHLly9PfGaLLbaIG264IT788MP42c9+Fj169Mh5byaTiQMPPDAmT54c48ePj27duiU+e9ttt8Wzzz6b884vMmXKlHjzzTcTz//oRz+KOXPmxOjRo6Nnz555aejatWuceOKJce+998aCBQvimWeeiWHDhhX8fRc0ZNm0AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADS8s4776Sd0Ch4naD+br755pg3b17i+eHDhxewhobopptuitdee22DM23atInbbrutSEWFNXv27MSzXbp0KWBJ/htyebavip/85Cfx6KOPRocOHfJyX+fOnePpp5+OPn36JD7z29/+Ni+7/11FRUWcccYZOZ3p3bt3TJ8+PUaOHBnZbHaT9h944IHx+uuvxwEHHJDTuauuuiref//9Tdr9RSZOnBiTJk1KPL/ddtvFK6+8EgMGDMjL/h133DFeeeWV2HXXXfNyX75ddNFFMWvWrMTze+21V7z11lvxwx/+MMrKyvLScNRRR8WMGTNi7733TnxmxIgRsW7duk3efd999yWay2az8cc//jGuu+66aN68+Sbv/TKlpaUxePDg+N3vfheffvppXH311dGpU6eC7YOGatP+JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABopNatWxeLFy9OO6NRWLx4caxbty7tDGh0Fi5cGFdddVXi+f322y/23HPPAhbR0Lz33nvxs5/9bKNzN9xwQ3Tt2rUIRYW3cOHCxLNdunQpYEn+GxYtWlTAksZn9OjRcfXVV0cmk8nrvR06dIgHH3wwSkpKEs1PmDAh1q9fn9eGiIirr746Pvzww8Tz2267bbz44oux/fbb562hffv28cQTT8TBBx+c+ExlZWWcccYZeWuIiKipqYkf/vCHiee7d+8ezz77bHTr1i2vHW3bto0///nPeX2N82HKlClx5513Jp4fNmxYTJkyJXr16pX3ls6dO8ekSZNi0KBBieY/+OCDuP322zd57zPPPJNo7uc//3kce+yxm7wvF+3bt4+f/OQnMWfOnNh5552LuhvSlk07AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAN8+fPTzuhUfF6Qe5GjRoVK1euTDx/6aWXFrCGhqa2tjZOOeWUWLdu3Qbn9t9//zj11FOLVFV4y5YtSzzbuXPnApbkv2Hp0qUFLGlcjjvuuLjyyisLdv/uu+8ew4cPTzS7YsWKmDJlSl73L126NG6++ebE8x06dIgnn3wyunXrlteOiIiysrIYN25cfPOb30x8ZsqUKfHss8/mreGRRx6JWbNmJZpt2rRpjB8/Prp06ZK3/f+sdevWMXHixGjdunVB7s9VbW1tnH322VFXV5doftiwYfHAAw9Es2bNCtbUvHnzGD9+fOy4446J5q+//vpYu3Ztvfd98MEHsXDhwo3Ode/ePUaPHl3vPZuqrKyswXzfQLGUph0AADQaiyPinTzcs11EZPNwDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAa+99lpMmzYt7YyiO/7446N9+/aJZj/77LMC12xexo0bFwMHDozdd9+9KPsefPDB+Pzzz4uyK5922223or1GNGz33XdfjB8/PvH8oYceGgceeGDhgmhwbr311pg6deoGZ5o3bx5jxoyJTCZTpKrCW7p0aeLZ1q1bF7Ak/w25PNvmbMstt4yxY8cWfM/o0aPj7rvvjtra2o3OPv/883HwwQfnbffNN98cq1evTjSbyWTioYceiq222ipv+/9dixYtYvz48bHTTjvFypUrE535xS9+EQcccEBe9v/yl79MPPvzn/88dtlll7zs/TJbb7113HjjjXHaaacVdE8SDzzwQPz9739PNLvnnnvGvffeG9lstsBVEVtssUU88sgj0a9fv6ioqNjg7MKFC+Oee+6Js846q1673n333URzP/jBD6KkpKReO4D6KU07AABoHOrq6m6LiNs29Z5MJrMyIlpuehEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsCFr1qyJxYsXp51RdDU1NYln58+fX8CSzc+aNWtizZo1Rdv3+eefN8rv4WK+RjRcH3zwQZxzzjmJ55s1axa33HJLAYtoaD788MMYPXr0Rucuu+yy2HrrrYtQVDxLly5NPNuyZcsCluS/YdmyZQUsaTxuvvnmaNWqVcH39OrVKwYPHhxPP/30RmdffPHFvO2trKyM2267LfH8qFGj4sADD8zb/i/Ts2fPuPHGG+P0009PNP/ss8/GjBkzon///pu0d8aMGfHaa68lmt1+++3jRz/60SbtS+rUU0+N++67L6//7XNVXV0dl19+eaLZli1bxu9///to0qRJgav+1zbbbBNXXHFFXHTRRRudHTt2bJx11ln12vPJJ58kmttzzz3rdT9Qf9m0AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADS8Nlnn6WdAGyG1q5dG9/+9rdj5cqVic9ccsklsfXWWxewioakrq4uTj311Fi7du0G5/r37x8XXnhhkaqKo7q6OtasWZNotkmTJlFWVlbgoo1r1apV4tnly5cXLqSR+OY3vxlDhw4t2r6ku954442oq6vLy84JEybE559/nmi2TZs2cdVVV+VlbxKnnnpq7LLLLonn77333k3e+eCDDyaeveKKK6K0tHSTdyZ19dVXF23XF/nTn/4Us2fPTjR71VVXRY8ePQpc9H/9x3/8R6K9r7/+esyYMaNeO1atWpVornv37vW6H6i/bNoBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMW2bt26WLZsWdoZjU51dXXaCdDgjRw5Mt56663E87vv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Nx5//PEoLy8vUBWwMZ06dYpf/OIXieeXLVsWBx54YLzwwgubvPtXv/pVjBgxIurq6hLNl5SUxH/+539u8l4av4EDB8bw4cMTz9fU1MTw4cPjkksuiZqamrw03HPPPTF48OBYuXJl4jPf+MY34sILL8zL/n/Wtm3buOaaa3I6c91118VBBx0Un3zyySbtXrBgQRxzzDFx8cUXf+lMWVnZJu3YFJ07d4577703MplM4jP33XdffOMb34gnnniigGX/1/Tp0+O8886LLbfcMk4//fR4++2383b3woUL4/LLL4+ePXvGd77znfjTn/4U1dXVebv/y6xZsyaOP/74uO+++xKfGTFiRAGLoOHIph0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Bjstttuceyxx0ZpaWnaKZuktLQ0jj322Nhtt93SToG8u+qqq6Kuri6nMy+++GJsscUWkclkGtTXySefXJgXCRqoM888M/bcc8/E80uWLIlvfetbcdlll0VFRUXO++bOnRvf/va344ILLoja2trE5y688MLo169fzvvYPP3yl7+MHj16JJ6vq6uLa665JgYMGBAvvfRSvfd++OGHcfTRR8cpp5yS0/d/06ZN4+677y7Y+9nTTz89jjzyyJzO/PnPf47tttsuLr744pg7d25OZxcuXBiXX3559O3bN8aPH/+lcy1atIiLLroop7vz7ZBDDokf//jHOZ35+OOP47DDDot99903Jk6cGDU1NXnvqqmpiZdffjlGjx4dffv2jd122y1uueWWWL58ed53/UNVVVX88Y9/jMMPPzy6desWZ555ZjzxxBP1+l2+IbW1tfHggw/GzjvvHL///e8TnzvooINip512ymsLNFSN+9MNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCLacccdo0uXLjFhwoSYO3du2jk569GjRxx99NHRvn37tFMA4F+UlJTEww8/HDvvvHMsW7Ys0Zmampq4/PLLY+zYsXHeeefFsGHDolu3bhs8M2PGjLj33ntjzJgxsW7dupwa995777jqqqtyOsPmrV27djFu3LjYb7/9orKyMvG5v/71r7HvvvvGwIEDY+TIkXHIIYdEmzZtNnimsrIynn/++bjrrrvi0Ucfjaqqqpx7f/3rX8euu+6a87lc3HXXXbHzzjvHvHnzEp+pqKiI66+/Pm688cYYOHBgDBkyJHbZZZfo27dvtGvXLsrLy6OioiI+//zzmDVrVvztb3+LZ555JqZMmZLodbj66qujVatWm/JYeXHVVVfFp59+Gvfff39O51566aV46aWXomvXrnHMMcfEoYceGnvttVe0bds254ZFixbF22+/HX/5y1/iL3/5S7z44ouxfPnynO/Jl8WLF8cdd9wRd9xxRzRv3jz22muv2GeffWLvvfeOnXbaKTp37pzTfTU1NfHqq6/GY489FuPGjYsPPvggp/NNmjSJX/3qVzmdgcasNO0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgMakQ4cOMXz48Hj11Vdj8uTJUV1dnXbSRpWWlsagQYNiwIABkc1m084BgC/0ta99LR544IE44ogjora2NvG5Tz/9NC666KK4+OKLY/vtt49dd901ttxyy2jTpk1UVVXF8uXLY9asWTF9+vSYN29evdo6duwYDz/8cJSWltbrPJuv3XffPe6444445ZRTcj77/PPPx/PPPx8lJSXRr1+/2GGHHaJnz57RsmXLKCkpidWrV8f8+fPj3XffjenTp8fatWvr3Tlq1KgYMWJEvc8n1aFDh3j88cdj3333jVWrVuV0tqamJqZMmRJTpkzJW8+hhx4aZ599dtx///15u7O+MplM3HXXXbFixYqYMGFCzufnz58ft99+e9x+++0REdGrV6/Ydttto3v37tGlS5coLy+PsrKyqKmpicrKyqioqIilS5fGggULYv78+fH+++/H8uXL8/xU+VNRURGTJ0+OyZMn/8//1q5du9h2222jW7du0a1bt2jbtm2UlZVFs2bNorKyMlavXh1r1qyJefPmxXvvvRezZs2KysrKejdcc801sf322+fjcaBR8K4GAEhqcUS8k4d7tosI/w8FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCoZbPZ2HPPPWObbbaJCRMmxNy5c9NO+lI9evSIo48+Otq3b592CgBs1KGHHhq//e1vY8SIEVFXV5fT2dra2pg5c2bMnDkzr01t2rSJp59+Orp3757Xe9l8DB8+PFatWhXnnntuvc7X1NTEjBkzYsaMGXku+39OOumkuO222wpy9xfp169fjBs3Lo444ohYv3590fZ+Ucfvf//7yGazqTX8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AAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5azoAALgNy7L8WlW/XGHq2RU2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+EJrOgAAuBnfV9XP6QgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+TqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDOmg4AAG7G71X1+go7r6qqr7ADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAF1gul0u6AQB4RJZlOVXV/mPn+/2+TqfTYBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDQHQ6HOp/Pn7pyvlwuh6meW9fpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAOZ0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgTqcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY0+kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmdDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA5nQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBOpwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjT6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZ0OgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgDmdDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYE6nAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmNPpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5nQ6AAAAAAAAAAAAAAAAAAAA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AAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA913UAAPAxXC6XP845v7/D1Jd32AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOA7XdcBAMCH8cs557d1BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9N1gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPRkHQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQE/WAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9GQdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAz3UdAAB8GH+dc/58h51fzzl5hx0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+w+XxeKwbAIBP5HK5vJ5znv7p/vT0dF5fX4tFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA/93z8/N5e3v72svb4/F4bvV8dFkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JN1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBzXQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8Lnd7/dzv9+/+Xe73c7tdvvhPQAAAAAAAAAAAAAAAAAAAPCzu64DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPjc7vf7eXl5+Ve/t9vtx8YAAAAAAAAAAAAAAAAAAADAJ5B1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVkHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQk3UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9WQcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCTdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1ZBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8zc59R0dVL1oc32fSExICoUOoAQIoLYAUgYAUlaaIYAcExYJ6LVdUUMAC9oYFRZoF4aIicpVO6KGIQCihQ4DQa3o/7w+f914VyJlkzswA389arPXWnf07e08yM5n3hwcAAAAAAAAAAAAAAAAAAAAAAAAA4D4OTw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA+zg8PQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADu4/D0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALiPw9MDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D4OTw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA+zg8PQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADu4/D0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALiPw9MDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D6+nh4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgTUzT1PHjx5WUlKSjR48qIyNDGRkZysrKUmBgoEJDQxUWFqbQ0FCVK1dONWvWlK/vlXGLx/Pnz2vx4sVKSEjQtm3btGvXLp09e1apqalKS0uTv7+/QkNDVbp0adWtW1fR0dFq1aqVOnbsqBIlSnh6Pq5wOTk5Wr16tZYvX64dO3Zo586dOnbsmNLS0pSenq7AwMD/vDerVaumBg0aqEGDBoqNjVVUVJSn53tEXl6eDh06pP379+vMmTPKyMhQenq6CgoKFBISouDgYJUpU0Y1a9ZUZGSkfHx8PD3ZbY4dO6ZFixYpISFBW7du1b59+3T+/HmlpKQoOztbQUFBCgkJUcWKFVWjRg3Vq1dPrVu3Vps2bRQeHu7p+S6XmZmpAwcOKCkpSSkpKUpPT1dGRoZ8fHwUHBz8n59FzZo1VaFCBU/Pdavt27dr5cqV2rlzp3bt2qV9+/YpJSVFaWlpSktLk8PhUEhIiEqWLKny5curTp06+vLLL23flZ+fr0OHDuno0aM6efKkzp49q+zsbGVnZ8vX11dBQUEKCgpSRESEKleurMqVKyssLMz2XXBeWlqa9u3bp4MHD/7nb1pmZqb8/f0VEhKikJAQVa5cWTVq1FCZMmU8Pdftzpw5o7i4OG3btk07d+7U7t27derUqf+8B3NychQcHKwSJUqobNmyqlSpkl599VXFxMTYtunUqVM6dOiQTpw4oVOnTikrK0vZ2dkqKChQUFCQgoOD//OvRIkSqlKliipXriyHw2HbJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoCsM0TU9vAAAAVxHDMFIkhV7s8dDQUKWkpLhxEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuNodOHBAcXFxWrt2rdauXasdO3YoKyvL8nl/f3/Vrl1b9erVU/369dW+fXu1adNGAQEBtm2OjY3VsmXLCs3FxcUpNjb2kpns7Gx99dVXmj59upYvX67c3Fyn9/j5+alDhw568MEH1atXL/n6+jp9DeBCTNPU4sWL9fnnn+uXX35Renp6ka4THR2tXr166ZFHHlHVqlULzb/zzjs6e/ZsoblnnnlG4eHhRdpkh927d2vp0qVatWqV4uPjtW/fPuXl5Vk66+fnp2uvvVZt2rRR+/btdeONNyokJMTmxZc2ZcoUDRw4sNBc//79NWXKlEJz58+f1xdffKGZM2dq3bp1Ksq9ef38/NSpUyfdc8896tu372X5eWeaptatW6cVK1Zo1apVWrdunY4cOWL5fIkSJdS8eXO1adNGN9xwg9q1ayeHw2Hj4sINGDBAU6dOLTQ3efJkDRgwoNDcqlWrNHnyZM2bN0/JyclObSlZsqTOnTvn1JnCHD16VPHx8frtt9+UkJCgbdu26eDBg5bf33+oUKGCmjRpopiYGN1www1q06aN/Pz8XLq1MNWrV1dSUpJbO61w5726f/vtNy1ZskQrV67U2rVrdezYMctnw8LC1KxZM11//fVq166d2rdv7xWfQ0uXLlWHDh0KzbVv315Lly4tNHfs2DF98cUX+umnn7RhwwYVFBQ4tWfWrFm65ZZbnDpzMampqVq4cKFWr16tNWvWKDExUWfOnHH6On5+fqpSpYqqV6+uGjVqKCYmRi1btlTDhg294ncIAAAAAAAAAAAAAAAAAAAAAAAAAAAAXC7CwsKUmpp6qUiqaZph7tpzuTPc+R/cAwAAGIaRIin0Yo+HhoYqJSXFjYsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDVKCkpSV999ZV++OEHbdy40eXXDw4OVvv27dW5c2fddtttqlq1qkuvHxsbq2XLlhWai4uLU2xs7AUfy8rK0nvvvacPPvhAx48fd9m2KlWqaPTo0RowYIAcDofLrmuFK34udqtevbqSkpIKze3fv1/Vq1e3f5AX+/HHH/XCCy8oMTHRZdf09fVVv3799NJLL6lOnToXzV1Ov6fk5GR99dVXmjFjhjZt2uSy64aEhKhHjx4aMmSIx94vU6ZM0cCBAwvN9e/fX1OmTLno42fOnNHYsWP1+eefu/R+d9WrV9fIkSM1YMAAl13TThs3btTXX3+tf/3rXzp8+LDLrluxYkX17dtXjz76qGrXru2y6zpjwIABmjp1aqG5yZMnX/T3ZZqmpk2bprfffrtY76WSJUvq3LlzRT4vSadPn9aiRYu0YMECxcXFaf/+/cW63sWEhYWpW7duGjJkiNq3b29Lx19Z/Xx1N7vv1Z2UlKQvvvhC3377rfbu3euy65YpU0a333677r//fjVr1sxl13XW0qVL1aFDh0Jz7du319KlSy/6+Pbt2/XKK6/o+++/V25ubpH3zJo1S7fcckuRz+fl5enHH3/UpEmTtHjxYuXk5BT5WoUJCgpSTEyM2rVrpz59+qhJkya2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAABXgrCwMKWmpl4qkmqaZpi79lzu3HuHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+Kj4/X7bffrlq1aunFF1/Uxo0bbenJyMjQ3Llz9dRTT6lGjRq6+eabNWvWLOXl5dnS56wVK1aoYcOGeuGFF3T8+HGXXvvw4cMaNGiQYmJitGnTJpdeG1eHffv2qV27drr11luVmJjo0mvn5eXpm2++UaNGjfT66697zXuyKHbu3KlBgwapZs2aev75513+fktPT9f06dPVoUMHtW7dWgsXLnTp9d1l2rRpqlevnt5++22lpKS49NoHDhzQwIED1aFDByUlJbn02q60ePFide7cWU2bNtW7776rw4cPu/T6R48e1QcffKDo6Gjdeeed2rlzp0uv7w5btmxRu3btdM8993jsb1dycrI+/PBDxcbGqnz58rrjjjs0adIk7d+/37bOlJQUffvtt4qNjVWDBg30ww8/2NZ1tdq9e7fuv/9+1a5dW6+++qr27t3r0uufOnVKn376qZo3b66uXbtqxYoVLr2+u6Snp2vYsGFq3Lixpk+frtzcXI/syMvL0+eff67q1avr9ttv19y5c5WTk2NrZ2ZmplauXKkxY8aoadOmioqK0vPPP+/y70AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCEOTw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACw2/79+9W7d2+1bt1a3333nfLz893WXVBQoLlz56p3796KjIzU/v373dZ9Ia+++qrat2+v3bt329qzadMmtWzZUuPGjbO1B1eWr776So0bN9aKFSts7cnKytLzzz+vdu3a6dSpU7Z2udr58+f12GOPqUGDBpo0aZJycnJs74yPj1eXLl10xx136NixY7b3uUJGRob69u2ru+++WydOnLC1a+nSpWrevLlWrlxpa4+zdu/erS5duqhTp05atGiR7X0FBQWaPn26GjZsqFGjRik7O9v2Tlf47LPPFBMT47Hf37Rp09S5c2dVrVpVTzzxhJYtW+bW7yl/2L59u2677Ta1bt1aO3bscHv/lSY7O1svvfSSrrnmGk2ePFm5ubm2dy5YsEDt2rXTPffco5MnT9re5yo7d+5UkyZN9Oabb7rl53QxGzZsUOPGjTVkyBAlJyd7bMfevXv1+uuv64033vDYBgAAAAAAAAAAAAAAAAAAAAAAAAAAAABXD4enBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANiloKBAY8aMUb169TRr1ixPz9GxY8d0/vx5j3Tn5+frwQcf1IsvvijTNN3SmZ2drccff1wPP/ywCgoK3NKJy9dLL72k++67T6mpqW7rjI+PV+vWrbV37163dRbHnDlzFB0drY8++kj5+flu758xY4auueYaLVq0yO3dzkhOTla7du00c+ZMt3WePHlSXbp00bJly9zWeTGmaWrMmDG69tprtXDhQrf35+TkaPTo0bruuut04MABt/dbVVBQoMcee0wPPfSQcnNzPbbj8ccf16JFi7zm72R8fLxiYmL0+eefe3rKZWvr1q1q1KiRXnnlFeXk5Li9/5tvvlF0dLTmzJnj9m5nLVy4UC1bttTu3bs9umPcuHFq2bKltm3b5tEdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOBuDk8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsMPx48fVpUsXDR8+XNnZ2Z6e43FDhgzRhAkTPNI9fvx43XHHHcrLy/NIP7zfww8/rFdeecUj3bt371b79u2VnJzskX4r8vPz9cILL6hXr146duyYR7ecPn1aN954o95//32P7riYI0eOqF27dtqwYYPbuzMzM9WjRw9t2bLF7d1/OHv2rLp16+YVf/s2b96sZs2aaenSpR7dcTGPPPKIPvroI0/P8EoZGRkaMmSInn32WU9Puez88MMPatWqlXbu3OnRHWfOnFGvXr302muvyTRNj265mKVLl6pHjx46d+6cR3c8++yzevzxx/meCgAAAAAAAAAAAAAAAAAAAAAAAAAAAOCq5PD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFdLTExUTEyMFi9e7OkpXmHs2LGaOHGiRzfMnDlTjzzyiEc3wDuNGDFC48eP9+iG5ORk9ejRQ+np6R7dcSFZWVnq2bOnxo4dK9M0PT1HkpSfn68nn3xSr732mqen/MmZM2fUpUsX7du3z2MbUlNT1a9fP2VkZLi9e//+/WrWrJnmzp3r9u6LOX36tG6++WYtWrTI01P+ZNSoUfrss888PcPrvfXWW3r00Uc9PeOy8cUXX6hPnz5KS0vz9BRJkmmaGjFihB555BGv+fvxh4SEBN1yyy3Kzs726I6xY8fqrbfe8ugGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAkX08PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcKX169frpptu0unTpz09xSssXLhQw4cPt5yvW7eurr32WtWqVUthYWHy9/dXWlqaTpw4ocTERP36669KS0sr0pYJEyaoevXqeuGFF4p0HleeSZMm6bXXXivy+cDAQDVt2lR169ZVlSpVFBISIofDodTUVB09elS7du3Shg0blJ6eXui1Nm7cqAcffFDffPNNkfe4WkZGhnr27KnFixd7esoFjRgxQv7+/vrnP//p6SnKz8/Xrbfeqm3btlnKR0REqGnTpqpZs6YqVKig4OBgGYahtLQ0HTp0SImJidqwYYNyc3Od3pKYmKgXXnhB77//vtNni2rPnj3q2LGjDh065LZOqzIzM9WzZ0/NmzdP7dq18/Qc/fLLLxo9erTlfGRkpK699lrVrFlTERERCgkJUX5+/n/+Nm7fvl0JCQlKTU21cbXnfPLJJ4qKitKTTz7p6SlebcqUKXrwwQdlmqanp/zN+PHj5ePjo48++sjTUyRJaWlpuvXWW3X+/HlL+ZCQEDVp0kS1atX6z996Pz8/paWl6fz589q1a5e2bdumpKQkp3YsWbJEI0aMKMpTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIArhq+nBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALjKtm3b1LlzZ50/f77I14iKilLbtm3VsmVLRUVFqXr16ipVqpSCg4Pl6+urzMxMpaSk6MiRIzp8+LC2bdumLVu2aNWqVTp8+LALn03xpaWlaejQoTJN85K5unXr6uGHH9Ztt92mKlWqXDKbm5urFStWaOLEifruu++Uk5Pj1KYXX3xR119/vdq1a+fUOVx5tm3bpqFDhzp9zs/PT7169dL999+v2NhYBQUFXTKfk5OjlStXaurUqZo5c6YyMzMvmp02bZruuOMOpzfZIS8vT7169dLixYuLdL5kyZK64YYb1KJFCzVu3FhVq1ZVhQoV/vNZlp6erlOnTmnv3r1av3694uLiFBcXp/z8fKd6nnvuOdWvX1/dunUr0k5XGTlypJYvX37JTK1atXTfffepT58+ql+/fqHXTE9P1+zZs/X+++9r/fr1Tu35+OOP9dBDDyk6Otqpc0WRnJys2NhYJScnF+l8ZGSkOnXqpGbNmqlBgwaqWrWqIiIi/vPeSk9PV3Jysnbv3q34+HjNnz9fmzdvdqojMzNTffr00a+//qqqVasWaacrnDlzRi+88EKhuSZNmui+++7TLbfcourVqxeaz83NVVxcnL788kvNmzfPBUv/ztfXV9dcc40aN26sOnXqqE6dOqpYsaLKly+v0qVLKyAgQIGBgcrIyND58+d1/vx5nTlzRlu2bNGvv/6qDRs2aMuWLSooKHC6+5lnntF1112n1q1bF/t5HDhw4KKPjRo1SqNHjy70GiNHjtSoUaOKvcVVFi9erMGDBxf6fetCHA6HWrVqpa5duyomJkbR0dGKiIhQiRIllJWVpXPnzmnPnj3asmWLFixYoEWLFl3y79jFfPzxx4qMjNSwYcOcPutqTz/9tPbt23fJTEREhO666y7dcccdatGihXx9C7+d+o4dO/T9999r3LhxhWazs7N1//33F+n9UKpUKd1www1q3LixoqKiFBUVpTJlyigkJEQhISEKCAhQdna2srOzdfbsWZ04cUJHjhzR7t27tWvXLm3YsEHbtm1Tbm6u090AAAAAAAAAAAAAAAAAAAAAAAAAAAAA4GpGUf5jeQAAgKIyDCNFUujFHg8NDVVKSoobFwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCvFsWPH1LJlSyUlJTl9tmTJknrwwQd19913q1GjRkXesH//fv3888/66aeftGTJEuXn5/8ts3HjRjVu3LjIHZIUGxurZcuWFZpr1KiRNm/efNHHy5cvr7Fjx2rAgAEyDMPpHQcOHNDTTz+tH374walzkZGRSkhIUHh4uNOdl2L15xIXF6fY2FiXdltVvXp1S6/R/fv3q3r16vYP8pDs7Gw1a9ZMW7dudercLbfcorfeektRUVFF6k1OTtaIESM0ZcqUi2YqVaqknJwcnTp1qtDr2fl7evjhhzV+/HinzhiGoW7duunhhx9W586d5efn59T5EydO6NNPP9UHH3ygs2fPWj5XsmRJbdiwQbVq1XKqrzBTpkzRwIEDC83VqVNHe/bsUUFBwQUfr1q1qt544w3dfvvt8vHxKdKWadOm6bHHHtOZM2csn+nbt69mzJhRpD6rMjIy1LZtW/32229OnQsODtY999yjIUOGqGnTpk73bt++XW+//ba++uor5eXlWT7XpEkTrVmzRv7+/k53XsqAAQM0derUQnOlSpW65Gu7YcOGeuONN3TjjTcWecvBgwdVtWpVy/kyZcro9OnTF3ysadOm6tq1q7p27aoWLVooKCioyLsk6dChQ5o0aZImT57s9Pel6Ohobdq0SQEBAcXacCmjRo3S6NGjC82NHDlSo0aNsm2HMw4ePKiYmBhLfzP+V0BAgB555BENHTpUNWvWtHzu3LlzmjRpkl5//XWdPHnSqU4fHx/NmzdPnTp1cuqcFUuXLlWHDh0KzRX2HgwJCdGIESM0dOhQlShRokhbMjMzlZaWprJly1408+677+rpp5+2fE2Hw6E+ffro8ccfV8uWLYv8t+QPWVlZWr16tRYtWqSff/5ZCQkJf8v079//kt9XAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKtVWFiYUlNTLxVJNU0zzF17LncOTw8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorvz8fPXu3VtJSUlOnQsICNDIkSN18OBBvfnmm2rUqFGxdtSoUUNDhw7VggULdPjwYb311luKiooq1jWLY/PmzRd9rGPHjtq8ebMGDhwowzCKdP3q1avr+++/16RJkxQUFGT53KFDhzRs2LAideLK8O6772rr1q2W88HBwZo8ebJmzZpVrPdU5cqVNXnyZM2ZM0elS5e+YObIkSM6depUkTtc4bPPPtP48eOdOtOhQwdt2LBBc+bM0c033yw/Pz+ne8uVK6eRI0dq9+7duu+++yyfO3/+vAYPHizTNJ3udIVdu3apoKDggo89+OCD2r59u+644w75+PgUueOuu+7SmjVrVKNGDctnvv/+ex08eLDInVYMGjRIv/32m+W8YRh68MEHtXfvXn322Wdq2rRpkXrr16+vSZMmaePGjbruuussn9u4caPGjBlTpE5XOHv27AX/d8MwNGLECP3666+68cYbi9VRtWrVYp2vV6+exowZo3379mnDhg0aM2aM2rdv79Tf2YuJjIzUyJEjtX//fn366acKC7N+L+8dO3bonXfeKfaGK4lpmrr77rud/ptxww03KDExUe+++65q1qzp1Nnw8HA99dRT2r17t4YMGeLU2fz8fN111106ffq0U+dc6WLvQUlq1aqVtmzZoueee04lSpQockdQUJDKli170ccLCgr04YcfWr5es2bNlJiYqBkzZqhNmzbF+lvyh8DAQHXs2FFjxozR5s2btWvXLo0ePVqRkZHFvjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOMPh6QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADFNXbsWMXHxzt1pnnz5tqyZYtGjRqlsLAwl2+qUKGCnnnmGe3cuVM//vijWrZs6fKOourbt6/mz5+v8uXLu+R6AwcO1Lx581SiRAnLZ7744gtt3rzZJf24vBw5ckRjxoyxnC9ZsqQWLFigAQMGuGxD9+7dtWLFClWqVMll13SVffv26amnnrKc9/f310cffaTFixerSZMmLtkQERGhqVOnatKkSfL397d0ZunSpZo4caJL+l3BMAx98skn+uyzzxQSEuKSa9auXVsLFixQRESEpXx+fr6tP5Pp06dr+vTplvOVKlXS4sWL9dlnn6lChQou2XDNNddoxYoVevjhhy2fGTt2rLZt2+aSflfw8/PT9OnT9corr8jPz88jGwzD0K233qrFixdr+/btev7551WjRg1b+x566CFt375dN954o+Vz7777rtLS0mzbdbmZMGGCVq5c6dSZF154QQsWLCj277dkyZIaP368pk2bpoCAAMvnTp48qWeeeaZY3Xbo27ev4uLibH3d/2Hp0qVKSkqylL399tu1cuVK1alTx9ZNtWvX1ksvvaQDBw5o9uzZatOmja19AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAHh6cHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFEdCQoJefvllp87cfffdWr58uWrXrm3Tqv9yOBzq1auX4uPj9e9//1tlypSxvfNSunXrpmnTpsnX19el123Xrp1++ukny9ctKCjQM88849INuDy88sorSktLs5T19/fXnDlz1KZNG5fvqF+/vhYsWKCSJUu6/NpFZZqm7r//fmVkZFjKlypVSosWLdKjjz4qwzBcvmfgwIH6/vvv5e/vbyk/YsQIZWZmunxHUXz++ed6+OGHXX7dqKgoff7555bzM2fOdPkGSTpx4oQee+wxy/lGjRpp3bp1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AAAAAFAAL730UlQqlbxj1LVKpRIvvfRS3jEAoCGV8w4AAAAA83nuuedi7969ecdIxeTz2rlzZ85JAAAAAAAAAAAAAAAAAAAAgKI7evRo3hEayo9//ONYt27dDbWRJEmN0lxqq6WlpWbtzWdiYqLqfRfyHGtZDwAAAAAAAAAAAAAAAAAAAGgWhw4dyjtCQzh06FA8+OCDeccAgIZTzjsAAAAAzOXAgQOxd+/evGOkau/evdHR0RFbt27NOwoAAAAAAAAAAAAAAAAAAEDDmJiYiIiISqUSlUplar3a5WKOyevYyfWOjo4YHBxcWKEW6cc//nEcO3YstTrUa1s/+7M/Gx0dHQsr1iL85Cc/ib/+67+uOldW9Th//nyNn2lz+x//43/kHeEqg4OD8YlPfCKTvr785S/H17/+9Uz6ykKSJFXt99u//duxbNmylNNEvPHGG/GZz3ym5u1W+zzzau9nfuZnYseOHTVtcy5//Md/HKdOnbrhdmpVg1q0c702Vq1aFb/6q796w/1UY9++fXHgwIGq9q31OEqjzWrb+9jHPhZ9fX017Xs2P/nJT+Jzn/tczdut9znigQceiHvvvbembc7lv/23/xbDw8NV7Vvvdau2zZtuuil+4Rd+oeZ9z+aFF16IV155pebt1vtr8Yu/+IvR29tb0zZn89Of/jT+4i/+oiZtNdL73L333hvvete7brifavzv//2/4/Tp01XtW+/jsto2V6xYET/7sz9b875n8/d///fxne98p+bt1vtr8eEPfzi6u7tr2uZsTpw4saDrO9Z73aptc/PmzbFx48aa9z2bZ599Ns6ePVvTNuv9nHnp0qXxgQ98oGbtzefQoUPx+uuvV7VvvddtIe3t2rUrurq6atr3bN5+++14/vnnr7tfI50jVOP222+P9evX33A71fja174WY2NjNW2z3sd6b29v3HfffTVrbz6vv/56DA0NVbVvvddtIe3dd9990dnZWdO+ZzMyMhL/8A//UPN26/1845Zbbok1a9bUtM25vPzyy3Hu3Lmq9q33ulXbZldXV2zatKnmfc/mxz/+cfz0pz+tebv1/lrcdddd0d7eXtM2Z3PmzJmqz9Oup5HONVauXBn9/f033E81vve978WFCxeq2rfex2W1bXZ0dMS6detq3vdsjh07Fm+//XbN26331+KWW26J1tbWmrY5m7GxsTh69GjV+9d73aptc+nSpZl8JxwRcfTo0bh48WJN26z3c+bW1tYYGBioWXvzGRkZiTNnzlS1b73XbSHtLVu2LMrl9G9zeuHChap+dt9I5wjV6OzszOR31CIihoeHp34/rFbqfay3tLRk8n1aRMT58+dzO09Lo81q22tra4tSqVTTvmczMTER4+PjNW+33s83SqVSJvWNuPK72NWo9nmmMdYBAAAAAIBLxsbG4tixY3nHaAjHjh2LsbGxzH42CwDNIv3fGgMAAIBFOHjwYDzzzDN5x8jEM888E52dnbF58+a8owAAAAAAAAAAAAAAAAAANLVKpTJ1k7cbWdaijdnaam1tjWXLltXyKc/ppz/9aZw6dSqX55lnW+9///szufnzsWPH4m//9m8XnbNe6rXQNh588MHYsmXLAiq1eP/xP/7Hqm882ixuueWW+PVf//VM+vqHf/iHePHFFzPpq5588IMfzOTitmNjY/GDH/wg9X6A6tT6JsA3qlKp1Pzm5Y1gITdbvVHnzp2Lc+fOZdZfPRgbG8usr/PnzxfuPC0iuzE8Pj4eb7/9diZ91ZMsx/CJEyfi1KlTmfVXD1paWjLra3h4OI4ePZpZf/Uiq/f28+fPx9DQUCZ91ZPbb789s75+9KMfFW6OOHv2bGZ9HTt2LL773e9m1l+9eOSRRzLpZ3R0NA4dOpRJX/Vk1apVsXHjxkz6OnToUOHmiMHBwfjABz6QSV8//vGP45vf/GYmfdWTHTt2RFdXV+r9nD59Ovbv3596P/VmyZIlsX79+kz6OnDgQCHniPvuuy+Tvl5//fX4+te/nklf9WTz5s3R2dmZej+nTp2KL33pS6n3U28eeuihWLNmTSZ9/c3f/E0h54hNmzZl0tehQ4cKOUesW7cuk9+PeOutt+L//J//k3o/9eahhx6K/v7+TPr6y7/8y0LOEZ/4xCcy6evv//7vCzlH/M7v/E4mv6d2/Pjx+NM//dPU+6k3Dz30UDzwwAOZ9PW5z33OHJGi559/3hyRojfffDP+y3/5L6n3U2+ynCP+5E/+xByRon379pkjUnTkyBFzRMr+03/6T001RyRJct19BgcH4+Mf/3gGaSK+9KUvxfPPP3/d/arJnUUbtWrnU5/6VCxduvTGw1zHkSNHUvmsUataptXerl27Ytu2bTVtcy7/+T//5xgeHq5q33qvW7Vtrly5Mv7ZP/tnNe97Ns8991wqP/us99fiox/9aPT29ta0zdm8+eab8ed//udV71/vdau2ze3bt8d73vOemvc9m//5P/9nnD59uqZt5lW3ag0MDMTjjz9es/bm8+KLL8a3vvWtmrTVSOcav/ALvxA9PT016Ws+x44diy984QtV798sc8R73vOeeOc731nzvmezZ8+emv97gnqfI5YvXx4PP/xwzdqbzyuvvBKvvfZaVfvWe90W0t6HPvShWLJkSU37ns3Jkyen/m14LdX7XLJp06bMfh/7y1/+coyOjla1b73Xrdo2+/r6Mvu+59VXX43Dhw9fd79GOkeoxs6dOzP7HaoDBw7UvN16H+sbNmyIdevW1bTNubzwwgtV/xuyeq9btW12d3dn9lnu8OHDceTIkZq3W++vxXve855Mrh9x+vTp+Pa3v131/ot9nidOnFjUcUV19OjRzH5XHACaRTnvAAAAADDT8ePH4+mnn847RqaefvrpWLVqVWb/kBkAAAAAAAAAAAAAAACAhatUKlGpVKbWq11OXy+VSplcMC8iYnh4eOri0dfLVe1yMcdkfey9994bbW1tCyvWIpw8eTJefPHFBT+XyeWN1CONtqrd9/777493vetdC6jU4v3RH/1RnDlzpqb1qndr166Nj33sY5n09Y1vfGNqDBfJ9u3bM7n585kzZ+LgwYOp91Nvzp8/n3eEptYocxnXl8YFsgEAAAAAAAAAAACgiKr5Pessfxe7UqnExMREZv0VzcTERJw7dy7vGJkbHx/PrK+zZ89O/bvEouju7s6sr9HR0Xj77bcz669eZDUvXrhwIY4fP55JX/Xk7NmzmfX105/+NE6dOpVZf/Ugy/OIt99+O4aGhjLrr15cvHgxk37OnTsXhw8fzqSverJ+/frM+vr+979fuDlicHAws77efPPNOHToUGb91Yvdu3dn0s/Zs2fjlVdeyaSvetLf3x+33357Jn1961vfKuQc8cADD2TS149+9KPYv39/Jn3Vk/e+973R2dmZej8jIyPxta99LfV+6k17e3usW7cuk76ef/75Qs4R73nPezLp63vf+158/etfz6SvenLXXXdlcq2vt99+O/7qr/4q9X5YmKNHj2b6eQgAmkE57wAAAAAw3cTEROzZsyfTX6KtB+Pj47Fnz5548skno1Qq5R0HAAAAAAAAAAAAAACABnHu3Lk4f/58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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZnNnUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWZzZ1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVmc2dQEAAAAAAAAA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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(15, 6), dpi=800)\n", + "for n, data in gpu_res_approx.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--x', label=f'2^{n} nodes')\n", + "\n", + "for n, data in cpu_res_approx.items():\n", + " x, y = get_xy(data)\n", + " plt.plot(x, y, '--o', label=f'2^{n} nodes')\n", + "\n", + "plt.annotate('gpu generators', (gpu_res_approx[15][1][0], gpu_res_approx[15][1][1]+5e9))\n", + "plt.annotate('cpu generators', (cpu_res_approx[15][1][0], cpu_res_approx[15][1][1]+5e5))\n", + "\n", + "\n", + "plt.title('Approximate generator performance') \n", + "plt.xlabel('Total edges to generate') \n", + "plt.ylabel('Edges per seconds')\n", + "plt.legend()\n", + "plt.yscale('log')\n", + "plt.xscale('log')\n", + "plt.savefig(\"/workspace/img/edge_perf.png\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2fdddd6", + "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.8.15" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/performance/tabular_generator.ipynb b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/performance/tabular_generator.ipynb new file mode 100644 index 000000000..694e6dba7 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/demos/performance/tabular_generator.ipynb @@ -0,0 +1,410 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "efa59e1a", + "metadata": {}, + "source": [ + "# Copyright 2023 NVIDIA Corporation. All Rights Reserved.\n", + "#\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# http://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License.\n", + "# ==============================================================================" + ] + }, + { + "cell_type": "markdown", + "id": "303a4030", + "metadata": {}, + "source": [ + "# Tabular data generation performance demo" + ] + }, + { + "cell_type": "markdown", + "id": "eb20f456", + "metadata": {}, + "source": [ + "## Overview\n", + "\n", + "In this notebbok we compare the performance (throughput) of tabular data generators presented in the SynGen tool. \n", + "\n", + "Available generators:\n", + "\n", + "1. [KDE (Kernel Density Estimation)](#1)\n", + "1. [Uniform](#2)\n", + "1. [Gaussian](#3)\n", + "1. [Random](#4)" + ] + }, + { + "cell_type": "markdown", + "id": "94485946", + "metadata": {}, + "source": [ + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "dbcdb188", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:The OGB package is out of date. Your version is 1.3.5, while the latest version is 1.3.6.\n" + ] + } + ], + "source": [ + "# preprocessing\n", + "from syngen.preprocessing.datasets import IEEEPreprocessing\n", + "\n", + "# generators\n", + "from syngen.generator.tabular import (\n", + " KDEGenerator,\n", + " UniformGenerator, \n", + " GaussianGenerator, \n", + " RandomMVGenerator,\n", + ")\n", + "\n", + "# Others\n", + "import time\n", + "import pandas as pd\n", + "from collections import defaultdict\n", + "from syngen.utils.types import MetaData" + ] + }, + { + "cell_type": "markdown", + "id": "79ae9fca", + "metadata": {}, + "source": [ + "### Helper function" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f58103a7", + "metadata": {}, + "outputs": [], + "source": [ + "def measure_throughput(generator, n=10, samples = 100000, gpu=False):\n", + " times = []\n", + " for _ in range(n):\n", + " start = time.perf_counter()\n", + " generator.sample(samples, gpu=gpu)\n", + " elapsed = time.perf_counter() - start\n", + " times.append(elapsed)\n", + " return int((samples * n) / sum(times))" + ] + }, + { + "cell_type": "markdown", + "id": "0b6d13f8", + "metadata": {}, + "source": [ + "### Load tabular features" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "40202e32", + "metadata": {}, + "outputs": [], + "source": [ + "data_path = '/workspace/data/ieee-fraud'\n", + "preprocessed_path = '/workspace/data/ieee_preprocessed'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "260b9fe9", + "metadata": {}, + "outputs": [], + "source": [ + "preprocessing = IEEEPreprocessing(source_path=data_path, destination_path=preprocessed_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2481c224", + "metadata": {}, + "outputs": [], + "source": [ + "feature_spec_original = preprocessing.transform(use_cache=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e2db8da3", + "metadata": {}, + "outputs": [], + "source": [ + "original_tabular_data, categorical_features = feature_spec_original.get_tabular_data(MetaData.EDGES, 'user-product', return_cat_feats=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "f668be54", + "metadata": {}, + "outputs": [], + "source": [ + "results_dict = defaultdict(dict)" + ] + }, + { + "cell_type": "markdown", + "id": "7b5a559e", + "metadata": {}, + "source": [ + "\n", + "## KDE (Kernel Density Estimation) Generator\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "81bd5eff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "avg throughput: 371296, 592132\n" + ] + } + ], + "source": [ + "kde_generator = KDEGenerator()\n", + "kde_generator.fit(original_tabular_data, categorical_columns=categorical_features)\n", + "\n", + "results_dict['kde-cpu'] = measure_throughput(kde_generator, gpu=False)\n", + "results_dict['kde-gpu'] = measure_throughput(kde_generator, gpu=True)\n", + "print(f\"avg throughput: {results_dict['kde-cpu']}, {results_dict['kde-gpu']}\")" + ] + }, + { + "cell_type": "markdown", + "id": "5b7f1597", + "metadata": {}, + "source": [ + "\n", + "## Uniform Generator" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "857ab154", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "avg throughput: 897421, 3621726\n" + ] + } + ], + "source": [ + "uniform_generator = UniformGenerator()\n", + "uniform_generator.fit(original_tabular_data, categorical_columns=categorical_features)\n", + " \n", + "results_dict['uniform-cpu'] = measure_throughput(uniform_generator, gpu=False)\n", + "results_dict['uniform-gpu'] = measure_throughput(uniform_generator, gpu=True)\n", + "print(f\"avg throughput: {results_dict['uniform-cpu']}, {results_dict['uniform-gpu']}\")" + ] + }, + { + "cell_type": "markdown", + "id": "ae51cc19", + "metadata": {}, + "source": [ + "\n", + "## Gaussian Generator" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "47f763a4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "avg throughput: 530683, 983408\n" + ] + } + ], + "source": [ + "gaussian_generator = GaussianGenerator()\n", + "gaussian_generator.fit(original_tabular_data, categorical_columns=categorical_features)\n", + " \n", + "results_dict['gaussian-cpu'] = measure_throughput(gaussian_generator, gpu=False)\n", + "results_dict['gaussian-gpu'] = measure_throughput(gaussian_generator, gpu=True)\n", + "print(f\"avg throughput: {results_dict['gaussian-cpu']}, {results_dict['gaussian-gpu']}\")" + ] + }, + { + "cell_type": "markdown", + "id": "f0f879ec", + "metadata": {}, + "source": [ + "\n", + "## Random Generator" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "34d45583", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "avg throughput: 440086, 6438646\n" + ] + } + ], + "source": [ + "random_generator = RandomMVGenerator()\n", + "random_generator.fit(original_tabular_data, categorical_columns=categorical_features)\n", + " \n", + "results_dict['random-cpu'] = measure_throughput(random_generator, gpu=False)\n", + "results_dict['random-gpu'] = measure_throughput(random_generator, gpu=True)\n", + "print(f\"avg throughput: {results_dict['random-cpu']}, {results_dict['random-gpu']}\")" + ] + }, + { + "cell_type": "markdown", + "id": "3a70c2e6", + "metadata": {}, + "source": [ + "## Results" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "e02de4d1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
kde-cpukde-gpuuniform-cpuuniform-gpugaussian-cpugaussian-gpurandom-cpurandom-gpu
ieee37129659213289742136217265306839834084400866438646
\n", + "
" + ], + "text/plain": [ + " kde-cpu kde-gpu uniform-cpu uniform-gpu gaussian-cpu gaussian-gpu \\\n", + "ieee 371296 592132 897421 3621726 530683 983408 \n", + "\n", + " random-cpu random-gpu \n", + "ieee 440086 6438646 " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.DataFrame(results_dict, index=['ieee'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f30700e1", + "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.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/build_docker.sh b/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/build_docker.sh new file mode 100755 index 000000000..523f9c582 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/build_docker.sh @@ -0,0 +1,7 @@ +if [ ! "$(ls | grep -c docker_scripts)" -eq 1 ]; then + echo "Run this script from root directory. Usage: bash ./docker_scripts/build_docker.sh" + exit 1 +fi + +IMG="${IMAGE:=graph_gen}" +docker build . -t ${IMG} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/run_docker_interactive.sh b/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/run_docker_interactive.sh new file mode 100755 index 000000000..7bb159401 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/run_docker_interactive.sh @@ -0,0 +1,13 @@ +if [ ! "$(ls | grep -c docker_scripts)" -eq 1 ]; then + echo "Run this script from root directory. Usage: bash ./docker_scripts/run_docker_interactive.sh" + exit 1 +fi + +IMG="${IMAGE:=graph_gen}" + +nvidia-docker run --rm -it \ + --ipc=host \ + --net=host \ + -v "$(pwd)":/workspace \ + ${IMG} \ + bash diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/run_docker_notebook.sh b/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/run_docker_notebook.sh new file mode 100755 index 000000000..dc55c5551 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/docker_scripts/run_docker_notebook.sh @@ -0,0 +1,17 @@ +if [ ! "$(ls | grep -c docker_scripts)" -eq 1 ]; then + echo "Run this script from root directory. Usage: bash ./docker_scripts/run_docker_notebook.sh" + exit 1 +fi + +IMG="${IMAGE:=graph_gen}" + +CMD='cd /workspace && echo -e "\nOPEN http://:9916/ and copy token\n\n" && jupyter notebook --ip=0.0.0.0 --port=9916' + +nvidia-docker run --rm -it \ + --ipc=host \ + --net=host \ + -v "$(pwd)":/workspace \ + ${IMG} \ + bash -c "${CMD}" + +# OPEN http://:9916/ diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/img/degree_centrality_feature_distribution.png b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/degree_centrality_feature_distribution.png new file mode 100644 index 000000000..c1048ea28 Binary files /dev/null and b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/degree_centrality_feature_distribution.png differ diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/img/degree_distribution_quality.png b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/degree_distribution_quality.png new file mode 100644 index 000000000..ecf462d09 Binary files /dev/null and b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/degree_distribution_quality.png differ diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/img/edge_perf.png b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/edge_perf.png new file mode 100644 index 000000000..2a39c2235 Binary files /dev/null and b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/edge_perf.png differ diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/img/graph_structure statistics.png b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/graph_structure statistics.png new file mode 100644 index 000000000..c7217d55d Binary files /dev/null and b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/graph_structure statistics.png differ diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/img/pca_components.png b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/pca_components.png new file mode 100644 index 000000000..7e9a06e02 Binary files /dev/null and b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/pca_components.png differ diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/img/syngen_architecture.png b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/syngen_architecture.png new file mode 100644 index 000000000..77630f276 Binary files /dev/null and b/Tools/DGLPyTorch/SyntheticGraphGeneration/img/syngen_architecture.png differ diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/requirements.txt b/Tools/DGLPyTorch/SyntheticGraphGeneration/requirements.txt new file mode 100644 index 000000000..0b114d7cd --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/requirements.txt @@ -0,0 +1,6 @@ +snap-stanford==6.0.0 +similaritymeasures==0.6.0 +seaborn==0.12.2 +ipywidgets==8.0.4 +ipython_autotime==0.3.1 +scikit-plot>=0.3.7 diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/get_datasets.sh b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/get_datasets.sh new file mode 100755 index 000000000..e442a323f --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/get_datasets.sh @@ -0,0 +1,185 @@ +#Note: Each user is responsible for checking the content of datasets and the applicable licenses and determining if suitable for the intended use + +if [ ! "$(ls | grep -c ^scripts$)" -eq 1 ]; then + echo "Run this script from root directory. Usage: bash ./scripts/get_datasets.sh" + exit 1 +fi + +mkdir -p data +cd data || exit 1 + +# Lastfm +echo "Processing lastfm ..." +echo "@inproceedings{feather, +title={{Characteristic Functions on Graphs: Birds of a Feather, from Statistical Descriptors to Parametric Models}}, +author={Benedek Rozemberczki and Rik Sarkar}, +year={2020}, +pages = {1325–1334}, +booktitle={Proceedings of the 29th ACM International Conference on Information and Knowledge Management (CIKM '20)}, +organization={ACM}, +}" +if [ "$(ls | grep -c "^lasftm_asia$")" -ge 1 ]; then + echo "Lastfm directory already exists, skipping ..." +else + wget https://snap.stanford.edu/data/lastfm_asia.zip + unzip lastfm_asia.zip + rm lastfm_asia.zip +fi + + +# Twitch +echo "Processing Twitch ..." +echo "@misc{rozemberczki2019multiscale, + title={Multi-scale Attributed Node Embedding}, + author={Benedek Rozemberczki and Carl Allen and Rik Sarkar}, + year={2019}, + eprint={1909.13021}, + archivePrefix={arXiv}, + primaryClass={cs.LG} +}" +if [ "$(ls | grep -c "^twitch$")" -ge 1 ]; then + echo "Twitch directory already exists, skipping ..." +else + mkdir -p twitch && cd twitch || exit 1 + wget https://snap.stanford.edu/data/twitch_gamers.zip && unzip twitch_gamers.zip + rm twitch_gamers.zip + cd .. +fi + + +# Orkut +echo "Processing Orkut ..." +echo "@inproceedings{yang2012defining, + title={Defining and evaluating network communities based on ground-truth}, + author={Yang, Jaewon and Leskovec, Jure}, + booktitle={Proceedings of the ACM SIGKDD Workshop on Mining Data Semantics}, + pages={1--8}, + year={2012} +}" +if [ "$(ls | grep -c "^orkut$")" -ge 1 ]; then + echo "Orkut directory already exists, skipping ..." +else + mkdir -p orkut && cd orkut || exit 1 + wget https://snap.stanford.edu/data/bigdata/communities/com-orkut.ungraph.txt.gz && gzip -d com-orkut.ungraph.txt.gz + rm com-orkut.ungraph.txt.gz + cd .. +fi + + +# Tabformer +echo "Processing tabformer ..." +echo "@inproceedings{padhi2021tabular, + title={Tabular transformers for modeling multivariate time series}, + author={Padhi, Inkit and Schiff, Yair and Melnyk, Igor and Rigotti, Mattia and Mroueh, Youssef and Dognin, Pierre and Ross, Jerret and Nair, Ravi and Altman, Erik}, + booktitle={ICASSP 2021-2021 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP)}, + pages={3565--3569}, + year={2021}, + organization={IEEE}, + url={https://ieeexplore.ieee.org/document/9414142} +}" +if [ "$(ls | grep -c "^tabformer$")" -ge 1 ]; then + echo "Tabformer directory already exists, skipping ..." +else + if [ "$(ls | grep -c "^transactions.tgz$")" -eq 0 ]; then + echo "transactions.tgz not found, skipping ..." + echo "Download tabformer manually - https://github.com/IBM/TabFormer/tree/main/data/credit_card/ and store it as ./data/transactions.tgz" + else + mkdir -p tabformer && mv transactions.tgz tabformer && cd tabformer || exit 1 + tar zxvf transactions.tgz + mv transactions.tgz .. + python ../../scripts/time_filter_tabformer.py ./card_transaction.v1.csv + rm card_transaction.v1.csv + cd .. + fi +fi + + +# IEEE +echo "Processing IEEE ..." +# kaggle competitions download -c ieee-fraud-detection +if [ "$(ls | grep -c "^ieee-fraud$")" -ge 1 ]; then + echo "IEEE directory already exists, skipping ..." +else + if [ "$(ls | grep -c "^ieee-fraud-detection.zip$")" -eq 0 ]; then + echo "ieee-fraud-detection.zip not found, skipping ..." + echo "Download IEEE manually from https://www.kaggle.com/competitions/ieee-fraud-detection/data and store it as ./data/ieee-fraud-detection.zip" + # kaggle competitions download -c ieee-fraud-detection // exemplary command to download + else + mkdir -p ieee-fraud && mv ieee-fraud-detection.zip ieee-fraud && cd ieee-fraud || exit 1 + unzip ieee-fraud-detection.zip "*_transaction.csv" + mv ieee-fraud-detection.zip .. + python ../../scripts/ieee_fraud.py . + rm *_transaction.csv + cd .. + fi +fi + + + +# Paysim +echo "Processing Paysim ..." +if [ "$(ls | grep -c "^paysim$")" -ge 1 ]; then + echo "Paysim directory already exists, skipping ..." +else + if [ "$(ls | grep -c "^paysim.zip$")" -eq 0 ]; then + echo "paysim.zip not found, skipping ..." + echo "Download paysim manually from https://www.kaggle.com/datasets/ealaxi/paysim1/download?datasetVersionNumber=2 and store it as ./data/paysim.zip" + #kaggle datasets download -d ealaxi/paysim1 #exemplary command to download + else + mkdir -p paysim && mv paysim.zip paysim && cd paysim || exit 1 + unzip paysim.zip + mv paysim.zip .. + cd .. + fi +fi + + + +# credit +echo "Processing credit ..." +if [ "$(ls | grep "^credit$")" -ge 1 ]; then + echo "credit directory already exists, skipping ..." +else + if [ "$(ls | grep -c "^credit.zip$")" -eq 0 ]; then + echo "credit.zip not found, skipping ..." + echo "Download credit manually from https://www.kaggle.com/datasets/kartik2112/fraud-detection/download?datasetVersionNumber=1 and store it as ./data/credit.zip" + # kaggle datasets download -d kartik2112/fraud-detection // exemplary command to download + else + mkdir -p credit && mv credit.zip credit && cd credit || exit 1 + unzip credit.zip "fraudTrain.csv" + mv credit.zip .. + python ../../scripts/time_filter_credit.py ./fraudTrain.csv + rm "fraudTrain.csv" + cd .. + fi +fi + + + +# CORA +echo "Processing CORA ..." +echo "@article{sen:aim08, + title = {Collective Classification in Network Data}, + author = {Prithviraj Sen, Galileo Mark Namata, Mustafa Bilgic, Lise Getoor, Brian Gallagher, and Tina Eliassi-Rad}, + journal = {AI Magazine}, + year = {2008}, + publisher = {AAAI}, + pages = {93--106}, + volume = {29}, + number = {3}, +}" +if [ "$(ls | grep -c "^cora$")" -ge 1 ]; then + echo "CORA directory already exists, skipping ..." +else + python -m syngen preprocess --source-path=./cora --dataset=cora --download +fi + + +# Rating +echo "Processing Rating ..." + +if [ "$(ls | grep -c "^epinions$")" -ge 1 ]; then + echo "Rating file already exists, skipping ..." +else + python -m syngen preprocess --source-path=./epinions --dataset=epinions --download +fi diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/ieee_fraud.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/ieee_fraud.py new file mode 100755 index 000000000..202baa96b --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/ieee_fraud.py @@ -0,0 +1,60 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys +import pandas as pd +import numpy as np +from pathlib import Path + +if __name__ == '__main__': + data_path = sys.argv[1] + # - path containing ieee-fraud-detection data + # https://www.kaggle.com/competitions/ieee-fraud-detection + data_path = Path(data_path) + + # - concat data files + + train_trn = pd.read_csv(data_path / 'train_transaction.csv') + test_trn = pd.read_csv(data_path / 'test_transaction.csv') + # - not every transactionID has an associated transaction identification ... + data = pd.concat([train_trn, test_trn], axis=0) + + user_cols = ['addr1', 'addr2', 'card1', 'card2', 'card3', 'card4', 'card5', 'card6'] + # - product columns that can be used to create unique id + product_cols = ['ProductCD', 'R_emaildomain'] + for c in user_cols: + data.loc[:, c] = data[c].fillna('').astype(str) + + for c in product_cols: + data.loc[:, c] = data[c].fillna('').astype(str) + + data['user_id'] = '' + user_cols_selected = ['card1'] # - select only card1 + for c in user_cols_selected: + data.loc[:, 'user_id'] = data['user_id'] + data[c] + + data['product_id'] = '' + for c in product_cols: + data.loc[:, 'product_id'] = data['product_id'] + data[c] + + # - drop id cols + data.drop(columns=user_cols + product_cols, inplace=True) + + # - select last transaction + data = data.sort_values('TransactionDT').groupby(['user_id', 'product_id']).tail(1) + + # - dump data + save_path = os.path.join(data_path, 'data.csv') + data.to_csv(save_path, index=False) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/time_filter_credit.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/time_filter_credit.py new file mode 100755 index 000000000..56c370765 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/time_filter_credit.py @@ -0,0 +1,28 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import pandas as pd +from pathlib import Path + +if __name__ == '__main__': + data_path = sys.argv[1] + save_path = Path(data_path).parent + save_path = save_path / 'data.csv' + df = pd.read_csv(data_path) + df['user'] = df['first'] + df['last'] + df = df.groupby(['user', 'merchant'], axis=0).tail(1).reset_index(drop=True) + df = df.drop(columns=['user']) + # - save data + df.to_csv(save_path, index=False) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/time_filter_tabformer.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/time_filter_tabformer.py new file mode 100755 index 000000000..745cc58ad --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/scripts/time_filter_tabformer.py @@ -0,0 +1,38 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import pandas as pd +from pathlib import Path + +if __name__ == '__main__': + + tabformer_path = sys.argv[1] + save_path = Path(tabformer_path).parent + save_path = save_path / 'card_transaction.v2.csv' + df = pd.read_csv(tabformer_path) + # - create seconds columns to sort transactions by + t = df["Time"].str.split(":", expand=True) + t = t[0].apply(int) * 3600 + t[1].apply(int) * 60 + df.loc[:, "Seconds"] = t + df['Card ID'] = df["User"].astype(str) + df["Card"].astype(str) + sorted_df = df.sort_values(by="Seconds") + + # - get last element + tdf = sorted_df.groupby(by=["Card ID", "Merchant Name"], + axis=0).tail(1).reset_index(drop=True) + tdf = tdf.drop(columns=["Card ID", "Seconds"]) + + # - save data + tdf.to_csv(save_path, index=False) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/__init__.py similarity index 84% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/__init__.py rename to Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/__init__.py index 8ad3be9f6..44d6e3348 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/__init__.py +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -10,4 +10,4 @@ # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and -# limitations under the License. \ No newline at end of file +# limitations under the License. diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/__main__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/__main__.py new file mode 100644 index 000000000..df5b14dc0 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/__main__.py @@ -0,0 +1,55 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import sys +import traceback + +from syngen.cli import get_parser + + +logging.basicConfig() +logging.root.setLevel(logging.NOTSET) +logger = logging.getLogger(__name__) +log = logger + + +def get_args(): + parser = get_parser() + + try: + args = parser.parse_args() + except TypeError: + parser.print_help() + sys.exit(0) + + return args, sys.argv + + +def main(): + args, argv = get_args() + log.info("=========================================") + log.info("| Synthetic Graph Generation Tool |") + log.info("=========================================") + + try: + _ = args.action(args) + except Exception as error: + print(f"{error}") + traceback.print_tb(error.__traceback__) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/__init__.py new file mode 100644 index 000000000..59dcb46e7 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .graph import * diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/analyser.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/analyser.py new file mode 100644 index 000000000..f8eb2a4d1 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/analyser.py @@ -0,0 +1,150 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time + +import matplotlib.pyplot as plt +import pandas as pd + +from syngen.analyzer.graph.plotting import ( + plot_clustering_coef_distribution, + plot_degree_distribution, + plot_eigenvalue_histogram_distribution, + plot_eigenvalue_rank_distribution, + plot_hopplot, + plot_in_degree_distribution, + plot_leading_singular_vector_rank, + plot_out_degree_distribution, + plot_singular_value_histogram_distribution, + plot_singular_value_rank_distribution, + plot_strongly_connected_component_distribution, + plot_weakly_connected_component_distribution, +) +from syngen.analyzer.graph.stats import ( + get_connectivity, + get_global_stats, + get_path_stats, + get_transitivity, +) +from syngen.analyzer.graph.utils import timed + + +class AnalysisModule: + @staticmethod + def check_assertions(graphs): + assert len(graphs), "Expected at least 1 graph" + assert ( + len(set([graph.is_directed for graph in graphs])) == 1 + ), "All graphs have to be directed or undirected" + + @staticmethod + def maybe_wrap_timer(f, timer, title): + return timed(f, title) if timer else f + + def compare_graph_stats( + self, + *graphs, + global_stats=True, + connectivity=True, + transitivity=True, + path_stats=True, + timer=False, + fast=True, + ): + + self.check_assertions(graphs) + results = [] + category_functions = [] + + if global_stats: + category_functions.append(("Global stats", get_global_stats)) + if connectivity: + category_functions.append(("Connectivity", get_connectivity)) + if transitivity: + category_functions.append(("Transitivity", get_transitivity)) + if path_stats: + category_functions.append(("Path stats", get_path_stats)) + + for category, F in category_functions: + + start = time.perf_counter() + stats = [F(G, fast=fast) for G in graphs] + parsed = [ + tuple( + [category, statistic] + + [graph_stats[statistic] for graph_stats in stats] + ) + for statistic in stats[0] + ] + results += parsed + + if timer: + elapsed = time.perf_counter() - start + print(f'Category "{category}" took {elapsed:.2f}s') + + names = [ + graph.name if graph.name else f"G{i}" + for i, graph in enumerate(graphs, 1) + ] + columns = ["Category", "Statistic"] + names + return pd.DataFrame(results, columns=columns) + + def compare_graph_plots(self, *graphs, hop_plot_iters=128, timer=False): + + self.check_assertions(graphs) + + is_directed = graphs[0].is_directed + + if is_directed: + fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) + ax1, ax2, ax3, ax4 = ax3, ax4, ax1, ax2 + fig.set_size_inches(18, 6 * 2, forward=True) + else: + fig, (ax1, ax2) = plt.subplots(1, 2) + fig.set_size_inches(18, 6, forward=True) + + pdd = self.maybe_wrap_timer( + plot_degree_distribution, timer, "Degree distribution" + ) + pidd = self.maybe_wrap_timer( + plot_in_degree_distribution, timer, "In degree distribution" + ) + podd = self.maybe_wrap_timer( + plot_out_degree_distribution, timer, "Out degree distribution" + ) + ph = self.maybe_wrap_timer(plot_hopplot, timer, "Hop plot") + + if is_directed: + pidd(ax3, *graphs) + podd(ax4, *graphs) + pdd(ax1, *graphs) + ph(ax2, *graphs, hop_plot_iters=hop_plot_iters) + + return fig + + def compare_graph_dd(self, *graphs, timer=False): + + self.check_assertions(graphs) + + fig, ax1 = plt.subplots(1, 1) + fig.set_size_inches(18.5, 10.5, forward=True) + pdd = ( + timed(plot_degree_distribution, "Degree distribution") + if timer + else plot_degree_distribution + ) + + pdd(ax1, *graphs) + + return fig diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/frechet.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/frechet.py new file mode 100644 index 000000000..8433f0d9b --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/frechet.py @@ -0,0 +1,171 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import similaritymeasures + + +def get_normalised_cdf(nodes, cdf_points=100): + unique_nodes, unique_nodes_counts = np.unique(nodes, return_counts=True) + node_degree, node_degree_counts = np.unique( + unique_nodes_counts, return_counts=True + ) + node_degree_normalized = ( + node_degree / node_degree[-1] + ) # they are sorted, so [-1] is max + node_degree_counts_normalized = node_degree_counts / np.sum( + node_degree_counts + ) # to have density + F = node_degree_counts_normalized + cdf_points_for_F = np.array( + F.shape[0] * (np.logspace(0, 1, num=cdf_points + 1) - 1) / 9, + dtype=np.int32, + ) + F_normalized = np.zeros(shape=(cdf_points, 2)) + F_normalized[:, 0] = node_degree_normalized[ + np.array( + (cdf_points_for_F[0:-1] + cdf_points_for_F[1:]) / 2, dtype=np.int32 + ) + ] + for i in range(cdf_points_for_F.shape[0] - 1): + beginning = cdf_points_for_F[i] + end = cdf_points_for_F[i + 1] + matching_list = F[beginning:end] + F_normalized[i, 1] = np.mean(matching_list) + F_normalized[i, 0] = ( + node_degree_normalized[beginning] + + ( + node_degree_normalized[end - 1] + - node_degree_normalized[beginning] + ) + / 2 + ) + return F_normalized + + +def get_dd_plot2(data): + out_dd, in_dd = list(zip(*data)) + out_dd, in_dd = list(out_dd), list(in_dd) + unique_nodes, unique_nodes_counts = np.unique(out_dd, return_counts=True) + degree_counts = Counter(unique_nodes_counts) + x_out, y_out = zip(*degree_counts.items()) + unique_nodes, unique_nodes_counts = np.unique(in_dd, return_counts=True) + degree_counts = Counter(unique_nodes_counts) + x_in, y_in = zip(*degree_counts.items()) + + return (x_in, y_in), (x_out, y_out) + + +def get_nan_indicies(*values): + indicies = None + for value in values: + filtered = np.isnan(value) + current_nan = filtered[:, 0] + filtered[:, 1] + indicies = current_nan if indicies is None else indicies + current_nan + return indicies + + +def remove_nans(*values): + indicies = get_nan_indicies(*values) + return tuple(F[~indicies] for F in values) + + +def get_frechet_score( + edges_original, edges_to_compare, cdf_points=1000, log=True +): + F1_normalized = get_normalised_cdf(edges_original, cdf_points=cdf_points) + F2_normalized = get_normalised_cdf(edges_to_compare, cdf_points=cdf_points) + F1, F2 = remove_nans(F1_normalized, F2_normalized) + if log: + F1 = np.log(F1) + F2 = np.log(F2) + score = similaritymeasures.frechet_dist(F1, F2) + return score + + +def get_frechet_score_normalized( + edges_original, + edges_to_compare, + edges_normalize, + cdf_points=1000, + log=True, +): + F1_normalized = get_normalised_cdf(edges_original, cdf_points=cdf_points) + F2_normalized = get_normalised_cdf(edges_to_compare, cdf_points=cdf_points) + F3_normalized = get_normalised_cdf(edges_normalize, cdf_points=cdf_points) + F1, F2, F3 = remove_nans(F1_normalized, F2_normalized, F3_normalized) + + if log: + F1 = np.log(F1) + F2 = np.log(F2) + F3 = np.log(F3) + + score = similaritymeasures.frechet_dist(F1, F2) + worst_score = similaritymeasures.frechet_dist(F1, F3) + + eps = 1e-6 + if worst_score < eps or score >= worst_score: + normalized_score = 0 + else: + normalized_score = min(1 - score / worst_score, 1) + return normalized_score + + +def get_out_in_dd(edges): + out_dd = edges[:, 0] + in_dd = edges[:, 1] + return out_dd, in_dd + + +def get_frechet_score_directed( + edges_original, edges_to_compare, cdf_points=1000, log=True +): + original_out_dd, original_in_dd = get_out_in_dd(edges_original) + compare_out_dd, compare_in_dd = get_out_in_dd(edges_to_compare) + + dd_score = get_frechet_score( + edges_original, edges_to_compare, cdf_points, log + ) + out_dd_score = get_frechet_score( + original_out_dd, compare_out_dd, cdf_points, log + ) + in_dd_score = get_frechet_score( + original_in_dd, compare_in_dd, cdf_points, log + ) + + return dd_score, out_dd_score, in_dd_score + + +def get_frechet_score_directed_normalized( + edges_original, + edges_to_compare, + edges_normalize, + cdf_points=1000, + log=True, +): + original_out_dd, original_in_dd = get_out_in_dd(edges_original) + compare_out_dd, compare_in_dd = get_out_in_dd(edges_to_compare) + normalize_out_dd, normalize_in_dd = get_out_in_dd(edges_normalize) + + dd_normalized_score = get_frechet_score_normalized( + edges_original, edges_to_compare, edges_normalize, cdf_points, log + ) + out_dd_normalized_score = get_frechet_score_normalized( + original_out_dd, compare_out_dd, normalize_out_dd, cdf_points, log + ) + in_dd_normalized_score = get_frechet_score_normalized( + original_in_dd, compare_in_dd, normalize_in_dd, cdf_points, log + ) + + return dd_normalized_score, out_dd_normalized_score, in_dd_normalized_score diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/graph.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/graph.py new file mode 100644 index 000000000..47958d2bc --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/graph.py @@ -0,0 +1,85 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import snap +from syngen.utils.types import MetaData + + +def safeSNAP(f): + def wrapper(*args, **kwargs): + graph = args[0] + graph.maybe_load_snap() + return f(*args, **kwargs) + + return wrapper + + +class Graph(object): + def __init__(self, path=None, name=None, load_eagerly=False, is_directed=False, _snap_graph=None): + self.path = path + self.name = name + self.is_directed = is_directed + self.snapGraph = _snap_graph + + if load_eagerly: + self.maybe_load_snap() + + def maybe_load_snap(self): + if not self.snapGraph: + graph_type = snap.TNGraph if self.is_directed else snap.TUNGraph + self.snapGraph = snap.LoadConnList(graph_type, self.path) + + @staticmethod + def instantiate_from_feature_spec(feature_spec, edge_name, graph_name=None): + + edge_info = feature_spec.get_edge_info(edge_name) + + is_bipartite = edge_info[MetaData.SRC_NODE_TYPE] != edge_info[MetaData.DST_NODE_TYPE] + is_directed = edge_info[MetaData.DIRECTED] + + graph_type = snap.TNGraph if is_directed else snap.TUNGraph + + struct_data = feature_spec.get_structural_data(edge_name) + + if is_bipartite: + num_src_nodes = feature_spec.get_node_info(edge_info[MetaData.SRC_NODE_TYPE])[MetaData.COUNT] + num_dst_nodes = feature_spec.get_node_info(edge_info[MetaData.DST_NODE_TYPE])[MetaData.COUNT] + + num_nodes = num_src_nodes + num_dst_nodes + else: + num_nodes = feature_spec.get_node_info(edge_info[MetaData.SRC_NODE_TYPE])[MetaData.COUNT] + + snap_graph = graph_type.New(num_nodes, len(struct_data)) + + for i in range(num_nodes): + snap_graph.AddNode(i) + + for e in struct_data: + snap_graph.AddEdge(int(e[0]), int(e[1])) + + return Graph(_snap_graph=snap_graph, is_directed=is_directed, name=graph_name) + + @safeSNAP + def edge_count(self): + return self.snapGraph.GetEdges() + + @safeSNAP + def node_count(self): + return self.snapGraph.GetNodes() + + @safeSNAP + def get_edges(self): + return [ + (EI.GetSrcNId(), EI.GetDstNId()) for EI in self.snapGraph.Edges() + ] diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/plotting.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/plotting.py new file mode 100644 index 000000000..870206e98 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/plotting.py @@ -0,0 +1,412 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import os +from functools import partial +from typing import Dict + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +from scipy.sparse.linalg import eigsh + +from syngen.analyzer.graph.graph import safeSNAP +from syngen.utils.types import ColumnType + +TMP_NAME = "tmp" + + +def common_plot(f, ax, *graphs, **kwargs): + for i, G in enumerate(graphs, 1): + f(G, i, ax, **kwargs) + + if len(graphs) > 1: + ax.legend() + + +def parse_file(plot, filename): + parsed_filename = f"{plot}.{filename}.tab" + with open(parsed_filename, "r") as f: + lines = f.read().splitlines() + + x_values = [] + y_values = [] + for line in lines: + if len(line) and "#" not in line: + x, y = line.split() + x_values.append(float(x)) + y_values.append(float(y)) + + return x_values, y_values + + +def clear_files(plot, filename): + files_to_clean = [ + f"./{plot}.{filename}.plt", + f"./{plot}.{filename}.png", + f"./{plot}.{filename}.tab", + ] + for file in files_to_clean: + try: + os.remove(file) + except FileNotFoundError: + print(f"File {file} attempted to be removed, but not found") + + +def parse_snap_object(snap_object): + zipped = [(pair.GetVal1(), pair.GetVal2()) for pair in snap_object] + x, y = zip(*zipped) + return x, y + + +def get_degree_dist(snapGraph): + return parse_snap_object(snapGraph.GetDegCnt()) + + +def get_in_degree_dist(snapGraph): + return parse_snap_object(snapGraph.GetInDegCnt()) + + +def get_out_degree_dist(snapGraph): + return parse_snap_object(snapGraph.GetOutDegCnt()) + + +def get_clustering_coef_dist(snapGraph): + return parse_snap_object(snapGraph.GetClustCf(True, -1)[1]) + + +def get_strongly_connected_component(snapGraph): + return parse_snap_object(snapGraph.GetSccSzCnt()) + + +def get_weakly_connected_component(snapGraph): + return parse_snap_object(snapGraph.GetWccSzCnt()) + + +@safeSNAP +def _add_to_axis_idd(G, i, ax): + graph_name = G.name or f"Graph {i}" + title = "Log-log in degree distribution" + G = G.snapGraph + x, y = get_in_degree_dist(G) + ax.set_xscale("log") + ax.set_xlabel("In degree") + ax.set_yscale("log") + ax.set_ylabel("Number of nodes") + ax.set_title(title) + ax.scatter(x, y, label=graph_name, s=5) + + +@safeSNAP +def _add_to_axis_odd(G, i, ax): + graph_name = G.name or f"Graph {i}" + title = "Log-log out degree distribution" + G = G.snapGraph + x, y = get_out_degree_dist(G) + ax.set_xscale("log") + ax.set_xlabel("Out degree") + ax.set_yscale("log") + ax.set_ylabel("Number of nodes") + ax.set_title(title) + ax.scatter(x, y, label=graph_name, s=5) + + +@safeSNAP +def _add_to_axis_dd(G, i, ax): + graph_name = G.name or f"Graph {i}" + title = "Log-log degree distribution" + G = G.snapGraph + x, y = get_degree_dist(G) + ax.set_xscale("log") + ax.set_xlabel("Degree") + ax.set_yscale("log") + ax.set_ylabel("Number of nodes") + ax.set_title(title) + ax.scatter(x, y, label=graph_name, s=5) + + +@safeSNAP +def _add_to_axis_ccd(G, i, ax): + graph_name = G.name or f"Graph {i}" + title = "Log-log distribution of clustering coefficient" + G = G.snapGraph + x, y = get_clustering_coef_dist(G) + ax.set_xscale("log") + ax.set_xlabel("Degree") + ax.set_yscale("symlog") + ax.set_ylabel("Clustering coefficient") + ax.set_title(title) + ax.scatter(x, y, label=graph_name, s=5) + + +@safeSNAP +def _add_to_axis_scc(G, i, ax): + graph_name = G.name or f"Graph {i}" + title = "Log-log distribution of sizes of strongly connected components" + G = G.snapGraph + x, y = get_strongly_connected_component(G) + ax.set_xscale("log") + ax.set_xlabel("Size of strongly connected component") + ax.set_yscale("symlog") + ax.set_ylabel("Number of components") + ax.set_title(title) + ax.scatter(x, y, label=graph_name, s=5) + + +@safeSNAP +def _add_to_axis_wcc(G, i, ax): + is_directed = G.is_directed + weakly_string = " weakly " if is_directed else " " + title = ( + f"Log-log distribution of sizes of{weakly_string}connected components" + ) + graph_name = G.name or f"Graph {i}" + G = G.snapGraph + x, y = get_weakly_connected_component(G) + ax.set_xscale("log") + ax.set_xlabel(f"Size of{weakly_string}connected component") + ax.set_yscale("symlog") + ax.set_ylabel("Number of components") + ax.set_title(title) + ax.scatter(x, y, label=graph_name, s=5) + + +@safeSNAP +def _add_to_axis_hp(G, i, ax, hop_plot_iters=128): + is_directed = G.is_directed + graph_name = G.name or f"Graph {i}" + title = "Hop plot" + plot = "hop" + G = G.snapGraph + G.PlotHops(TMP_NAME, "Hop plot", is_directed, hop_plot_iters) + num_hops, num_nodes = parse_file(plot=plot, filename=TMP_NAME) + num_hops = [int(num_hop) for num_hop in num_hops] + parse_file(plot=plot, filename=TMP_NAME) + clear_files(plot=plot, filename=TMP_NAME) + ax.set_xlabel("Number of hops") + ax.set_ylabel("Number of pairs of nodes") + ax.set_yscale("log") + ax.set_title(title) + ax.plot(num_hops, num_nodes, "--", marker="o", label=graph_name) + + +@safeSNAP +def _add_to_axis_svr(G, i, ax, num_spectral_values=100): + graph_name = G.name or f"Graph {i}" + title = "Singular value rank distribution" + plot = "sngVal" + G = G.snapGraph + G.PlotSngValRank(num_spectral_values, TMP_NAME, title) + ranks, sin_values = parse_file(plot, filename=TMP_NAME) + ranks = [int(rank) for rank in ranks] + parse_file(plot=plot, filename=TMP_NAME) + clear_files(plot=plot, filename=TMP_NAME) + ax.set_xlabel("Rank") + ax.set_ylabel("Singular value") + ax.set_yscale("log") + ax.set_title(title) + ax.plot( + ranks, sin_values, "--", marker="o", label=graph_name, markersize=5 + ) + + +@safeSNAP +def _add_to_axis_evr(G, i, ax, num_spectral_values=100): + graph_name = G.name or f"Graph {i}" + title = "Eigenvalue rank distribution" + plot = "eigVal" + G = G.snapGraph + G.PlotEigValRank(num_spectral_values, TMP_NAME, title) + ranks, eig_values = parse_file(plot, filename=TMP_NAME) + ranks = [int(rank) for rank in ranks] + parse_file(plot=plot, filename=TMP_NAME) + clear_files(plot=plot, filename=TMP_NAME) + ax.set_xlabel("Rank") + ax.set_ylabel("Eigenvalue") + ax.set_yscale("log") + ax.set_title(title) + ax.plot( + ranks, eig_values, "--", marker="o", label=graph_name, markersize=5 + ) + + +@safeSNAP +def _add_to_axis_svd(G, i, ax, num_spectral_values=100): + graph_name = G.name or f"Graph {i}" + title = "Singular value distribution" + plot = "sngDistr" + G = G.snapGraph + G.PlotSngValDistr(num_spectral_values, TMP_NAME, title) + sin_values, counts = parse_file(plot=plot, filename=TMP_NAME) + parse_file(plot=plot, filename=TMP_NAME) + clear_files(plot=plot, filename=TMP_NAME) + ax.set_xlabel("Singular value") + ax.set_ylabel("Count") + ax.set_yscale("symlog") + ax.set_title(title) + ax.plot( + sin_values, counts, "--", marker="o", label=graph_name, markersize=5 + ) + + +@safeSNAP +def _add_to_axis_evd(G, i, ax, num_spectral_values=100): + graph_name = G.name or f"Graph {i}" + title = "Eigenvalue distribution" + plot = "eigDistr" + G = G.snapGraph + G.PlotEigValDistr(num_spectral_values, TMP_NAME, title) + eig_values, counts = parse_file(plot, filename=TMP_NAME) + parse_file(plot=plot, filename=TMP_NAME) + clear_files(plot=plot, filename=TMP_NAME) + ax.set_xlabel("Eigenvalue") + ax.set_ylabel("Count") + ax.set_yscale("symlog") + ax.set_title(title) + ax.plot( + eig_values, counts, "--", marker="o", label=graph_name, markersize=5 + ) + + +@safeSNAP +def _add_to_axis_lsv(G, i, ax): + graph_name = G.name or f"Graph {i}" + title = "Leading singular vector rank distribution" + plot = "sngVecL" + G = G.snapGraph + G.PlotSngVec(TMP_NAME, title) + ranks, components = parse_file(plot, filename=TMP_NAME) + ranks = [int(rank) for rank in ranks] + parse_file(plot=plot, filename=TMP_NAME) + clear_files(plot=plot, filename=TMP_NAME) + ax.set_xlabel("Rank") + ax.set_ylabel("Component of leading singular vector") + ax.set_yscale("log") + ax.set_title(title) + ax.plot( + ranks, components, "--", marker="o", label=graph_name, markersize=5 + ) + + +def plot_node_degree_centrality_feat_dist( + data, + feat_name_col_info: Dict[str, ColumnType], + src_col: str = "src", + dst_col: str = "dst", +): + + # - suppress matplotlib debug logger + matplotlib_logger = logging.getLogger("matplotlib") + matplotlib_logger.setLevel(logging.WARNING) + + src_degree = ( + data.groupby(src_col, as_index=False) + .count()[[src_col, dst_col]] + .rename(columns={dst_col: "src_degree"}) + ) + + # - normalized src_degree + src_degree_vals = src_degree["src_degree"].values + normalized_src_degree = (src_degree_vals - np.min(src_degree_vals)) / ( + np.max(src_degree_vals) - np.min(src_degree_vals) + ) + src_degree.loc[:, "src_degree"] = normalized_src_degree + + # - normalized dst_degree + dst_degree = ( + data.groupby(dst_col, as_index=False) + .count()[[src_col, dst_col]] + .rename(columns={src_col: "dst_degree"}) + ) + dst_degree_vals = dst_degree["dst_degree"].values + normalized_dst_degree = (dst_degree_vals - np.min(dst_degree_vals)) / ( + np.max(dst_degree_vals) - np.min(dst_degree_vals) + ) + + dst_degree.loc[:, "dst_degree"] = normalized_dst_degree + + # - merge + data = data.merge(src_degree, how="outer", on=src_col) + data = data.merge(dst_degree, how="outer", on=dst_col) + + # - normalize continuous columns + for feat, col_info in feat_name_col_info.items(): + col_type = col_info["type"] + if col_type == ColumnType.CONTINUOUS: + vals = data[feat].values + min_, max_ = np.min(vals), np.max(vals) + data.loc[:, feat] = (vals - min_) / (max_ - min_) + + # - plot heat maps + def heat_map(x, y): + heatmap, xedges, yedges = np.histogram2d(x, y, bins=30) + extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]] + return heatmap.T, extent + + nr = 1 # - num plots per row + fig, axs = plt.subplots(len(feat_name_col_info), nr, figsize=(12, 8)) + + c = 0 + for feat in feat_name_col_info: + if nr * len(feat_name_col_info) == 1: + heatmap, extent = heat_map( + data["src_degree"].values, data[feat].values + ) + axs.imshow(heatmap, extent=extent, origin="lower") + axs.set_xlabel("src_degree") + axs.set_ylabel("feat") + else: + # - src degree dist + heatmap, extent = heat_map( + data["src_degree"].values, data[feat].values + ) + axs[c].imshow(heatmap, extent=extent, origin="lower") + axs[c].set_xlabel("src_degree") + axs[c].set_ylabel("feat") + c += nr + + return fig + + +# Degree distribution +plot_degree_distribution = partial(common_plot, _add_to_axis_dd) +# In degree distribution +plot_in_degree_distribution = partial(common_plot, _add_to_axis_idd) +# Out degree distribution +plot_out_degree_distribution = partial(common_plot, _add_to_axis_odd) +# Hop plot +plot_hopplot = partial(common_plot, _add_to_axis_hp) +# Clustering coefficient distribution +plot_clustering_coef_distribution = partial(common_plot, _add_to_axis_ccd) +# Strongly connected component distribution +plot_strongly_connected_component_distribution = partial( + common_plot, _add_to_axis_scc +) +# Weakly connected component distribution +plot_weakly_connected_component_distribution = partial( + common_plot, _add_to_axis_wcc +) +# Eigenvalue rank distribution +plot_eigenvalue_rank_distribution = partial(common_plot, _add_to_axis_evr) +# Singular value rank distribution +plot_singular_value_rank_distribution = partial(common_plot, _add_to_axis_svr) +# Eigenvalue rank distribution +plot_eigenvalue_histogram_distribution = partial(common_plot, _add_to_axis_evd) +# Singular value rank distribution +plot_singular_value_histogram_distribution = partial( + common_plot, _add_to_axis_svd +) +# Leading singular vector rank distribution +plot_leading_singular_vector_rank = partial(common_plot, _add_to_axis_lsv) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/stats.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/stats.py new file mode 100644 index 000000000..07cf089d6 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/stats.py @@ -0,0 +1,232 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from copy import deepcopy +from operator import itemgetter + +import numpy as np + +from syngen.analyzer.graph.graph import safeSNAP + + +def get_normalised_cdf(nodes, cdf_points=100, debug=False): + unique_nodes, unique_nodes_counts = np.unique(nodes, return_counts=True) + node_degree, node_degree_counts = np.unique( + unique_nodes_counts, return_counts=True + ) + if debug: + print( + "unique_nodes,unique_nodes_counts", + unique_nodes, + unique_nodes_counts, + ) + print( + "node_degree,node_degree_counts", node_degree, node_degree_counts + ) + node_degree_normalized = ( + node_degree / node_degree[-1] + ) # they are sorted, so [-1] is max + node_degree_counts_normalized = node_degree_counts / np.sum( + node_degree_counts + ) # to have density + if debug: + print( + "node_degree_normalized,node_degree_counts_normalized", + node_degree_normalized, + node_degree_counts_normalized, + ) + plt.plot(node_degree_normalized, node_degree_counts_normalized) + plt.yscale("log") + plt.xscale("log") + plt.title("DD normalized log-log") + plt.show() + F = np.cumsum(node_degree_counts_normalized) + cdf_points_for_F = (np.logspace(0, 1, num=cdf_points) - 1) / 9 + F_normalized = np.zeros(shape=(cdf_points_for_F.shape[0], 2)) + F_normalized[:, 0] = cdf_points_for_F + for i, p in enumerate(cdf_points_for_F): + matching_list = F[node_degree_normalized <= p] + F_normalized[i, 1] = matching_list[-1] if len(matching_list) else 0.0 + if debug: + print("F_normalized", F_normalized) + plt.plot(F_normalized[:, 0], F_normalized[:, 1]) + plt.plot(node_degree_normalized, F) + plt.yscale("log") + plt.xscale("log") + plt.title("Normalized CDF of DD normalized log-log ") + plt.show() + return F_normalized + + +# Global stats +@safeSNAP +def get_global_stats(G, *args, **kwargs): + is_directed = G.is_directed + + G = G.snapGraph + num_nodes = G.GetNodes() + num_edges = G.GetEdges() + + density = num_edges / ((num_nodes - 1) * num_nodes) if num_nodes > 1 else 0 + + if not is_directed: + density = 2 * density + + average_degree = num_edges / num_nodes if num_nodes else 0 + self_loops = G.CntSelfEdges() + + zero_degrees = num_nodes - G.CntNonZNodes() + zero_in_degrees = len( + [item.GetVal2() for item in G.GetNodeInDegV() if item.GetVal2() == 0] + ) + zero_out_degrees = len( + [item.GetVal2() for item in G.GetNodeOutDegV() if item.GetVal2() == 0] + ) + uniq_bidirectional = G.CntUniqBiDirEdges() + uniq_undirected = G.CntUniqUndirEdges() + uniq_directed = G.CntUniqDirEdges() + + return { + "Nodes": num_nodes, + "Edges": num_edges, + "Density": around(density, 4), + "Average degree": around(average_degree, 2), + "Zero deg nodes": zero_degrees, + "Zero in deg nodes": zero_in_degrees, + "Zero out deg nodes": zero_out_degrees, + "Self loops": self_loops, + "Bidirectional edges": uniq_bidirectional, + "Unique undirected edges": uniq_undirected, + "Unique directed edges": uniq_directed, + } + + +# Connectivity +@safeSNAP +def get_connectivity(G, *args, **kwargs): + is_directed = G.is_directed + G = G.snapGraph + + def get_stats(component_dist_snap): + component_dist = [ + (comp.GetVal1(), comp.GetVal2()) for comp in component_dist_snap + ] + if len(component_dist): + largest_component = max(component_dist, key=itemgetter(0))[0] + else: + largest_component = 0 + number_of_components = sum( + num_component for size, num_component in component_dist + ) + percent = 100 * largest_component / G.GetNodes() + return number_of_components, percent + + # Weakly connected components + number_of_weak_components, percent_of_weak = get_stats(G.GetWccSzCnt()) + is_weakly_connected = number_of_weak_components == 1 + + if is_directed: + # Strongly connected components + number_of_strong_components, percent_of_strong = get_stats( + G.GetSccSzCnt() + ) + is_strongly_connected = number_of_strong_components == 1 + + result = { + "Is strongly connected": is_strongly_connected, + "Is weakly connected": is_weakly_connected, + "Number of strongly connected components": number_of_strong_components, + "Percent of nodes in largest strongly connected component": around( + percent_of_strong + ), + "Number of weakly connected components": number_of_weak_components, + "Percent of nodes in largest weakly connected component": around( + percent_of_weak + ), + } + + else: + result = { + "Is connected": is_weakly_connected, + "Number of connected components": number_of_weak_components, + "Percent of nodes in largest component": around(percent_of_weak), + } + + return result + + +# Cluster coefficient and triangles +@safeSNAP +def get_transitivity(G, fast=True, *args, **kwargs): + G = G.snapGraph + results_dict = {} + if fast: + samples = min(G.GetNodes(), int(1e3)) + results_dict["Clustering coefficient"] = G.GetClustCf(samples) + else: + cc, ct, op = G.GetClustCfAll()[0] + results_dict = { + "Clustering coefficient": cc, + "Number of closed triangles": ct, + "Number of open triangles": op, + } + + return results_dict + + +# Distances info +@safeSNAP +def get_path_stats(G, *args, **kwargs): + is_directed = G.is_directed + G = G.snapGraph + + # Only effective diameter if BFS will be too slow or not accurate + # approx_eff_diam = G.GetAnfEffDiam() + + num_test_nodes = max(100, G.GetNodes() // 1000) + approx_eff_diam, _, approx_diam, average_path_length = G.GetBfsEffDiamAll( + num_test_nodes, is_directed + ) + + return { + "90% effective diameter": around(approx_eff_diam), + "Approx. full diameter": approx_diam, + "Average shortest path length": around(average_path_length), + } + + +# Degree similarity +def get_dd_simmilarity_score(edges_original, edges_synthetic, cdf_points=1000): + F_normalized_original = get_normalised_cdf( + edges_original, cdf_points=cdf_points, debug=False + ) + F_normalized_synthetic = get_normalised_cdf( + edges_synthetic, cdf_points=cdf_points, debug=False + ) + abs_F = np.abs(F_normalized_original[:, 1] - F_normalized_synthetic[:, 1]) + where_non_zero = F_normalized_original[:, 1] != 0 + error = np.average( + np.divide( + abs_F[where_non_zero], F_normalized_original[:, 1][where_non_zero] + ) + ) # average error of normalized CDFs + error = min(error, 1) + if error < 0: + raise ValueError("Negative values in CDFs!") + simmilarity_score = 1.0 - error + return simmilarity_score + + +def around(number, decimals=2): + return np.around(number, decimals) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/utils.py new file mode 100644 index 000000000..86f5e67bf --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/graph/utils.py @@ -0,0 +1,26 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time + + +def timed(F, desc): + def inner(*args, **kwargs): + start = time.perf_counter() + res = F(*args, **kwargs) + elapsed = time.perf_counter() - start + print(f'"{desc}" took {elapsed:.2f}s') + return res + + return inner diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/__init__.py new file mode 100644 index 000000000..3bd3303fb --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/__init__.py @@ -0,0 +1,17 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .tabular_metrics import TabularMetrics +from .utils import load_data diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/tabular_metrics.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/tabular_metrics.py new file mode 100644 index 000000000..d95a4fcbd --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/tabular_metrics.py @@ -0,0 +1,674 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import warnings +from collections import Counter +from itertools import combinations +from typing import Dict, List, Optional + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import seaborn as sns +from dython.nominal import associations, numerical_encoding +from scipy import stats +from scipy.spatial import distance +from scipy.special import kl_div +from sklearn.decomposition import PCA + +from syngen.utils.types import DataFrameType, ColumnType + + +warnings.simplefilter(action="http://github.com/ignore", category=pd.errors.PerformanceWarning) +matplotlib._log.disabled = True +logger = logging.getLogger() +logger.setLevel(logging.CRITICAL) + + +class TabularMetrics(object): + def __init__( + self, + real: DataFrameType, + fake: DataFrameType, + categorical_columns: Optional[List] = [], + nrows: Optional[int] = None, + seed: Optional[int] = 123, + verbose: bool = False, + debug: bool = False, + ): + """ + Args: + real (DataFrameType): the original dataset + fake (DataFrameType): the generated dataset + categorical_columns (list): list of categorical columns in tabular data + nrows (int): number of rows to use for evaluation (default: None), will use the minimum of real/fake data length + seed (int): sets the random seed for reproducibility. (default: 123) + verbose (bool): print intermediate results (default: False) + debug (bool): debug mode (default: False) + """ + assert all(c in fake.columns for c in real.columns) and len( + real.columns + ) == len(fake.columns), r"Real and fake have different columns." + self.real = real + self.fake = fake[real.columns] + + self.nrows = nrows + self.seed = seed + self.verbose = verbose + self.debug = debug + + self.categorical_columns = categorical_columns + self.numerical_columns = [ + column + for column in real.columns + if column not in categorical_columns + ] + # Make sure columns and their order are the same. + if len(real.columns) == len(fake.columns): + fake = fake[real.columns.tolist()] + assert ( + real.columns.tolist() == fake.columns.tolist() + ), "Columns in real and fake dataframe are not the same" + + # Make sure the number of samples is equal in both datasets. + if nrows is None: + self.nrows = min(len(self.real), len(self.fake)) + elif len(fake) >= nrows and len(real) >= nrows: + self.nrows = nrows + else: + raise Exception( + f"Make sure nrows < len(fake/real). len(real): {len(real)}, len(fake): {len(fake)}" + ) + + self.real = self.real.sample(self.nrows) + self.fake = self.fake.sample(self.nrows) + + self.real.loc[:, self.categorical_columns] = ( + self.real.loc[:, self.categorical_columns] + .fillna("[NAN]") + .astype(str) + ) + self.fake.loc[:, self.categorical_columns] = ( + self.fake.loc[:, self.categorical_columns] + .fillna("[NAN]") + .astype(str) + ) + + self.real.loc[:, self.numerical_columns] = self.real.loc[ + :, self.numerical_columns + ].fillna(self.real[self.numerical_columns].mean()) + self.fake.loc[:, self.numerical_columns] = self.fake.loc[ + :, self.numerical_columns + ].fillna(self.fake[self.numerical_columns].mean()) + + def kl_divergence(self) -> float: + def get_frequencies(real, synthetic): + f_obs, f_exp = [], [] + real, synthetic = Counter(real), Counter(synthetic) + for value in synthetic: + if value not in real: + warnings.warn( + f"Unexpected value {value} in synthetic data." + ) + real[value] += 1e-6 # Regularization to prevent NaN. + + for value in real: + f_obs.append(synthetic[value] / sum(synthetic.values())) + f_exp.append(real[value] / sum(real.values())) + return f_obs, f_exp + + numerical_columns = self.numerical_columns + # - continuous columns + cont_scores = [] + for columns in combinations(numerical_columns, r=2): + columns = list(columns) + rd_cont = self.real[columns] + rd_cont[pd.isna(rd_cont)] = 0.0 + rd_cont[pd.isna(rd_cont)] = 0.0 + column1, column2 = rd_cont.columns[:2] + + real, xedges, yedges = np.histogram2d( + rd_cont[column1], rd_cont[column2] + ) + fake, _, _ = np.histogram2d( + self.fake[column1], self.fake[column2], bins=[xedges, yedges] + ) + + f_obs, f_exp = fake.flatten() + 1e-5, real.flatten() + 1e-5 + f_obs, f_exp = f_obs / np.sum(f_obs), f_exp / np.sum(f_exp) + + score = 1 / (1 + np.sum(kl_div(f_obs, f_exp))) + cont_scores.append(score) + + # - discrete columns + categorical_columns = self.categorical_columns + cat_scores = [] + for columns in combinations(categorical_columns, r=2): + columns = list(columns) + real = self.real[columns].itertuples(index=False) + fake = self.fake[columns].itertuples(index=False) + + f_obs, f_exp = get_frequencies(real, fake) + score = 1 / (1 + np.sum(kl_div(f_obs, f_exp))) + cat_scores.append(score) + + return np.nanmean(cont_scores + cat_scores) + + def correlation_correlation( + self, comparison_metric: str = "pearsonr" + ) -> float: + """ + computes the column-wise correlation of each dataset, and outputs the + `comparison_metric` score between the datasets. + + Args: + comparison_metric (str): metric to be used to compare between the datasets + see `scipy.stats` + Returns: + corr (float): correlation score + """ + comparison_metric = getattr(stats, comparison_metric) + total_metrics = pd.DataFrame() + for ds_name in ["real", "fake"]: + ds = getattr(self, ds_name) + corr_df = associations( + ds, nominal_columns=self.categorical_columns, nom_nom_assoc='theil', compute_only=True + ) + values = corr_df['corr'].values + values = values[~np.eye(values.shape[0], dtype=bool)].reshape( + values.shape[0], -1 + ) + total_metrics[ds_name] = values.flatten() + correlation_correlations = total_metrics + corr, p = comparison_metric( + total_metrics["real"], total_metrics["fake"] + ) + if self.debug: + print("\nColumn correlation between datasets:") + print(total_metrics.to_string()) + return corr + + def statistical_correlation(self, comparison_metric="spearmanr") -> float: + """ + computes correlation between basic statistics of each dataset for each column + + Args: + comparison_metric (str): metric to be used to compare between the datasets + see `scipy.stats` + Returns: + corr (float): correlation score + + """ + total_metrics = pd.DataFrame() + comparison_metric = getattr(stats, comparison_metric) + discrete_values = { + c: self.real[c].unique() for c in self.categorical_columns + } + for ds_name in ["real", "fake"]: + ds = getattr(self, ds_name) + metrics = {} + num_ds = ds.loc[:, self.numerical_columns] + cat_ds = ds.loc[:, self.categorical_columns] + for idx, value in num_ds.mean().items(): + metrics[f"mean_{idx}"] = value + for idx, value in num_ds.median().items(): + metrics[f"median_{idx}"] = value + for idx, value in num_ds.std().items(): + metrics[f"std_{idx}"] = value + for idx, value in num_ds.var().items(): + metrics[f"variance_{idx}"] = value + for cc in self.categorical_columns: + cdf = ds[cc] + v = cdf.value_counts(normalize=True) + unique_vals = set(v.index) + for d in discrete_values[cc]: + if d not in unique_vals: + metrics[f"count_{d}"] = 0.0 + else: + metrics[f"count_{d}"] = v[d] + total_metrics[ds_name] = metrics.values() + + total_metrics.index = metrics.keys() + statistical_results = total_metrics + + if self.debug: + print("\nBasic statistical attributes:") + print(total_metrics.to_string()) + corr, p = comparison_metric( + statistical_results["real"], statistical_results["fake"] + ) + return corr + + def plot_cumsums(self, nr_cols=4, fname=None): + """ + Plot the cumulative sums for all columns in the real and fake dataset. + Height of each row scales with the length of the labels. Each plot contains the + values of a real columns and the corresponding fake column. + Args: + fname: If not none, saves the plot with this file name. + """ + nr_charts = len(self.real.columns) + nr_rows = max(1, nr_charts // nr_cols) + nr_rows = nr_rows + 1 if nr_charts % nr_cols != 0 else nr_rows + + max_len = 0 + # Increase the length of plots if the labels are long + if not self.real.select_dtypes(include=["object"]).empty: + lengths = [] + for d in self.real.select_dtypes(include=["object"]): + lengths.append( + max( + [ + len(x.strip()) + for x in self.real[d].unique().tolist() + ] + ) + ) + max_len = max(lengths) + + row_height = 6 + (max_len // 30) + fig, ax = plt.subplots( + nr_rows, nr_cols, figsize=(16, row_height * nr_rows) + ) + fig.suptitle("Cumulative Sums per feature", fontsize=16) + if nr_rows == 1 and nr_cols == 1: + axes = [ax] + else: + axes = ax.flatten() + for i, col in enumerate(self.real.columns): + r = self.real[col] + f = self.fake.iloc[:, self.real.columns.tolist().index(col)] + self.cdf(r, f, col, "Cumsum", ax=axes[i]) + plt.tight_layout(rect=[0, 0.02, 1, 0.98]) + + if fname is not None: + plt.savefig(fname) + + plt.show() + + def plot_mean_std(self, ax=None, fname=None) -> None: + """ + Plot the means and standard deviations of each dataset. + + Args: + ax: Axis to plot on. If none, a new figure is made. + fname: If not none, saves the plot with this file name. + """ + real = self.real + fake = self.fake + if ax is None: + fig, ax = plt.subplots(1, 2, figsize=(10, 5)) + fig.suptitle( + "Absolute Log Mean and STDs of numeric data\n", fontsize=16 + ) + + ax[0].grid(True) + ax[1].grid(True) + real = real.select_dtypes(include=np.number).reset_index() + fake = fake.select_dtypes(include=np.number).reset_index() + real_mean = np.log(np.add(abs(real.mean()).values, 1e-5)) + fake_mean = np.log(np.add(abs(fake.mean()).values, 1e-5)) + min_mean = min(real_mean) - 1 + max_mean = max(real_mean) + 1 + line = np.arange(min_mean, max_mean) + sns.lineplot(x=line, y=line, ax=ax[0]) + sns.scatterplot(x=real_mean, y=fake_mean, ax=ax[0]) + ax[0].set_title("Means of real and fake data") + ax[0].set_xlabel("real data mean (log)") + ax[0].set_ylabel("fake data mean (log)") + + real_std = np.log(np.add(real.std().values, 1e-5)) + fake_std = np.log(np.add(fake.std().values, 1e-5)) + min_std = min(real_std) - 1 + max_std = max(real_std) + 1 + line = np.arange(min_std, max_std) + sns.lineplot(x=line, y=line, ax=ax[1]) + sns.scatterplot(x=real_std, y=fake_std, ax=ax[1]) + ax[1].set_title("Stds of real and fake data") + ax[1].set_xlabel("real data std (log)") + ax[1].set_ylabel("fake data std (log)") + + if fname is not None: + plt.savefig(fname) + + if ax is None: + plt.show() + + def convert_numerical(self, real, fake): + """ + Convert categorical columns to numerical + """ + for c in self.categorical_columns: + if real[c].dtype == "object": + real[c] = pd.factorize(real[c], sort=True)[0] + fake[c] = pd.factorize(fake[c], sort=True)[0] + return real, fake + + def cdf( + self, + real_data, + fake_data, + xlabel: str = "Values", + ylabel: str = "Cumulative Sum", + ax=None, + ) -> None: + """ + Plot continous density function on optionally given ax. If no ax, cdf is plotted and shown. + Args: + xlabel: Label to put on the x-axis + ylabel: Label to put on the y-axis + ax: The axis to plot on. If ax=None, a new figure is created. + """ + + x1 = np.sort(real_data) + x2 = np.sort(fake_data) + y = np.arange(1, len(real_data) + 1) / len(real_data) + + ax = ax if ax else plt.subplots()[1] + + axis_font = {"size": "14"} + ax.set_xlabel(xlabel, **axis_font) + ax.set_ylabel(ylabel, **axis_font) + + ax.grid() + ax.plot(x1, y, marker="o", linestyle="none", label="Real", ms=8) + ax.plot(x2, y, marker="o", linestyle="none", label="Fake", alpha=0.5) + ax.tick_params(axis="both", which="major", labelsize=8) + ax.legend(loc="upper center", bbox_to_anchor=(0.5, 1.1), ncol=3) + import matplotlib.ticker as mticker + + # If labels are strings, rotate them vertical + if isinstance(real_data, pd.Series) and real_data.dtypes == "object": + ticks_loc = ax.get_xticks() + r_unique = real_data.sort_values().unique() + if len(r_unique) > len(ticks_loc): + import pdb; pdb.set_trace() + ticks_loc = ticks_loc[: len(r_unique)] + + ax.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc)) + ax.set_xticklabels(r_unique, rotation="vertical") + + if ax is None: + plt.show() + + def plot_correlation_difference( + self, + plot_diff: bool = True, + cat_cols: list = None, + annot=False, + fname=None, + ) -> None: + """ + Plot the association matrices for the `real` dataframe, `fake` dataframe and plot the difference between them. + Has support for continuous and categorical data types. + All Object and Category dtypes are considered to be categorical columns if `cat_cols` is not passed. + + - Continuous - Continuous: Uses Pearson's correlation coefficient + - Continuous - Categorical: Uses so called correlation ratio (https://en.wikipedia.org/wiki/Correlation_ratio) for both continuous - categorical and categorical - continuous. + - Categorical - Categorical: Uses Theil's U, an asymmetric correlation metric for Categorical associations + Args: + plot_diff: Plot difference if True, else not + cat_cols: List of Categorical columns + boolean annot: Whether to annotate the plot with numbers indicating the associations. + """ + real = self.real + fake = self.fake + cmap = sns.diverging_palette(220, 10, as_cmap=True) + + if cat_cols is None: + cat_cols = real.select_dtypes(["object", "category"]) + if plot_diff: + fig, ax = plt.subplots(1, 3, figsize=(24, 7)) + else: + fig, ax = plt.subplots(1, 2, figsize=(20, 8)) + + real_corr = associations( + real, + nominal_columns=cat_cols, + plot=False, + nom_nom_assoc='theil', + mark_columns=True, + annot=annot, + ax=ax[0], + cmap=cmap, + )["corr"] + fake_corr = associations( + fake, + nominal_columns=cat_cols, + plot=False, + nom_nom_assoc='theil', + mark_columns=True, + annot=annot, + ax=ax[1], + cmap=cmap, + )["corr"] + + if plot_diff: + diff = abs(real_corr - fake_corr) + sns.set(style="white") + sns.heatmap( + diff, + ax=ax[2], + cmap=cmap, + vmax=0.3, + square=True, + annot=annot, + center=0, + linewidths=0.5, + cbar_kws={"shrink": 0.5}, + fmt=".2f", + ) + + titles = ( + ["Real", "Fake", "Difference"] if plot_diff else ["Real", "Fake"] + ) + for i, label in enumerate(titles): + title_font = {"size": "18"} + ax[i].set_title(label, **title_font) + plt.tight_layout() + + if fname is not None: + plt.savefig(fname) + + plt.show() + + def plot_pca(self, fname=None): + """ + Plot the first two components of a PCA of real and fake data. + Args: + fname: If not none, saves the plot with this file name. + """ + real, fake = self.convert_numerical(self.real, self.fake) + + pca_r = PCA(n_components=2) + pca_f = PCA(n_components=2) + + real_t = pca_r.fit_transform(real) + fake_t = pca_f.fit_transform(fake) + + fig, ax = plt.subplots(1, 2, figsize=(12, 6)) + fig.suptitle("First two components of PCA", fontsize=16) + sns.scatterplot(ax=ax[0], x=real_t[:, 0], y=real_t[:, 1]) + sns.scatterplot(ax=ax[1], x=fake_t[:, 0], y=fake_t[:, 1]) + ax[0].set_title("Real data") + ax[1].set_title("Fake data") + + if fname is not None: + plt.savefig(fname) + + plt.show() + + def visual_evaluation(self, save_dir=None, **kwargs): + """ + Plots mean, std, cumulative sum, correlation difference and PCA + Args: + save_dir: directory path to save images + kwargs: any key word argument for matplotlib. + """ + if save_dir is None: + self.plot_mean_std() + self.plot_cumsums() + self.plot_correlation_difference( + plot_diff=True, cat_cols=self.categorical_columns, **kwargs + ) + self.plot_pca() + else: + save_dir = Path(save_dir) + save_dir.mkdir(parents=True, exist_ok=True) + + self.plot_mean_std(fname=save_dir / "mean_std.png") + self.plot_cumsums(fname=save_dir / "cumsums.png") + self.plot_correlation_difference( + plot_diff=True, + cat_cols=self.categorical_columns, + fname=save_dir / "correlation_difference.png", + **kwargs, + ) + self.plot_pca(fname=save_dir / "pca.png") + + def evaluate( + self, comparison_metric: str = "pearsonr" + ) -> Dict[str, float]: + """ + evaluate synthetic data + + Args: + comparison_metric (str): metric to be used to compare between the datasets + see `scipy.stats` + + Returns: + results (dict): dictionary containing computed metrics, := metric_name, := score + + """ + statistical_correlation = self.statistical_correlation( + comparison_metric + ) + kl_divergence = self.kl_divergence() + correlation_correlation = self.correlation_correlation() + + results = { + "statistical_correlation": statistical_correlation, + "kl_divergence": kl_divergence, + "correlation_correlation": correlation_correlation, + } + + return results + + +def dd_feat_heatmap( + data, + feat_name_col_info: Dict[str, ColumnType], + src_col: str = "src", + dst_col: str = "dst", +): + src_degree = ( + data.groupby(src_col, as_index=False) + .count()[[src_col, dst_col]] + .rename(columns={dst_col: "src_degree"}) + ) + + # - normalized src_degree + src_degree_vals = src_degree["src_degree"].values + normalized_src_degree = src_degree_vals / np.sum(src_degree_vals) + src_degree.loc[:, "src_degree"] = normalized_src_degree + + # - normalized dst_degree + dst_degree = ( + data.groupby(dst_col, as_index=False) + .count()[[src_col, dst_col]] + .rename(columns={src_col: "dst_degree"}) + ) + dst_degree_vals = dst_degree["dst_degree"].values + normalized_dst_degree = dst_degree_vals / np.sum(dst_degree_vals) + + dst_degree.loc[:, "dst_degree"] = normalized_dst_degree + + # - merge + data = data.merge(src_degree, how="outer", on=src_col) + data = data.merge(dst_degree, how="outer", on=dst_col) + + # - normalize continuous columns + for feat, col_info in feat_name_col_info.items(): + col_type = col_info["type"] + min_ = col_info["min"] + max_ = col_info["max"] + if col_type == ColumnType.CONTINUOUS: + vals = data[feat].values + data.loc[:, feat] = (vals - min_) / (max_ - min_) + + # - plot heat maps + def heat_map(x, y): + heatmap, xedges, yedges = np.histogram2d(x, y, bins=10) + extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]] + return heatmap.T, extent + + heat_maps = [] + for feat in feat_name_col_info: + heatmap, _ = heat_map(data["src_degree"].values, data[feat].values) + heat_maps.append(heatmap) + + return heat_maps + + +def compute_dd_feat_js( + real, + fake, + feat_name_col_info: Dict[str, ColumnType], + src_col: str = "src", + dst_col: str = "dst", +): + + col_info = {} + for col_name, col_type in feat_name_col_info.items(): + if col_type == ColumnType.CONTINUOUS: + min_ = real[col_name].min() + max_ = real[col_name].max() + col_info[col_name] = {"type": col_type, "min": min_, "max": max_} + + elif col_type == ColumnType.CATEGORICAL: + # - none of the datsets align on categorical for now.. + pass + + real_heatmaps = dd_feat_heatmap( + real, col_info, src_col=src_col, dst_col=dst_col + ) + + fake_heatmaps = dd_feat_heatmap( + fake, col_info, src_col=src_col, dst_col=dst_col + ) + + heatmaps = list(zip(real_heatmaps, fake_heatmaps)) + score = 0.0 + for r, f in heatmaps: + s = distance.jensenshannon(r, f, axis=1) # - along feats + np.nan_to_num(s, copy=False, nan=1.0) + s = np.mean(s) + score += s + return score + + +def get_frequencies(real, synthetic): + f_obs, f_exp = [], [] + real, synthetic = Counter(real), Counter(synthetic) + for value in synthetic: + if value not in real: + warnings.warn(f"Unexpected value {value} in synthetic data.") + real[value] += 1e-6 # Regularization to prevent NaN. + + for value in real: + f_obs.append(synthetic[value] / sum(synthetic.values())) + f_exp.append(real[value] / sum(real.values())) + return f_obs, f_exp diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/utils.py new file mode 100644 index 000000000..2938294fa --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/analyzer/tabular/utils.py @@ -0,0 +1,102 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Any, Dict, List, Tuple, Union + +import pandas as pd + +try: + import ipywidgets as widgets + from IPython import get_ipython + from IPython.core.display import HTML, Markdown, display +except ImportError: + print("IPython not installed.") +from typing import Dict + + +def load_data( + path_real: str, + path_fake: str, + real_sep: str = ",", + fake_sep: str = ",", + drop_columns: List = None, +) -> Tuple[pd.DataFrame, pd.DataFrame]: + """ + Load data from a real and synthetic data csv. This function makes sure that the loaded data has the same columns + with the same data types. + Args: + path_real: string path to csv with real data + path_fake: string path to csv with real data + real_sep: separator of the real csv + fake_sep: separator of the fake csv + drop_columns: names of columns to drop. + Return: Tuple with DataFrame containing the real data and DataFrame containing the synthetic data. + """ + real = pd.read_csv(path_real, sep=real_sep, low_memory=False) + fake = pd.read_csv(path_fake, sep=fake_sep, low_memory=False) + if set(fake.columns.tolist()).issubset(set(real.columns.tolist())): + real = real[fake.columns] + elif drop_columns is not None: + real = real.drop(drop_columns, axis=1) + try: + fake = fake.drop(drop_columns, axis=1) + except: + print(f"Some of {drop_columns} were not found on fake.index.") + assert len(fake.columns.tolist()) == len( + real.columns.tolist() + ), f"Real and fake do not have same nr of columns: {len(fake.columns)} and {len(real.columns)}" + fake.columns = real.columns + else: + fake.columns = real.columns + + for col in fake.columns: + fake[col] = fake[col].astype(real[col].dtype) + return real, fake + + +def dict_to_df(data: Dict[str, Any]): + return pd.DataFrame( + {"result": list(data.values())}, index=list(data.keys()) + ) + + +class EvaluationResult(object): + def __init__( + self, name, content, prefix=None, appendix=None, notebook=False + ): + self.name = name + self.prefix = prefix + self.content = content + self.appendix = appendix + self.notebook = notebook + + def show(self): + if self.notebook: + output = widgets.Output() + with output: + display(Markdown(f"## {self.name}")) + if self.prefix: + display(Markdown(self.prefix)) + display(self.content) + if self.appendix: + display(Markdown(self.appendix)) + return output + + else: + print(f"\n{self.name}") + if self.prefix: + print(self.prefix) + print(self.content) + if self.appendix: + print(self.appendix) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/__init__.py new file mode 100644 index 000000000..4e105380e --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/__init__.py @@ -0,0 +1,20 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .edge_ds import EdgeDS + +DATASET_SOURCE = { + "edge_ds": EdgeDS, +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/base_dataset.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/base_dataset.py new file mode 100644 index 000000000..a895c2788 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/base_dataset.py @@ -0,0 +1,20 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from abc import ABC + + +class BaseDataset(ABC): + def get_graph(self, *args, **kwargs): + raise NotImplementedError("`get_graph` fn not implemented") diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/edge_ds.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/edge_ds.py new file mode 100644 index 000000000..13add1a33 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/data_loader/datasets/edge_ds.py @@ -0,0 +1,120 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Optional + +import dgl +import numpy as np +import torch + +from syngen.configuration import SynGenDatasetFeatureSpec +from syngen.utils.types import DataFrameType, MetaData + +from .base_dataset import BaseDataset + + +class EdgeDS(BaseDataset): + """ + lean DGL graph builder for edge classification, + """ + + def __init__( + self, + target_col: str = "label", + add_reverse: bool = True, + train_ratio: float = 0.8, + test_ratio: float = 0.1, + val_ratio: float = 0.1, + **kwargs, + ): + + self.target_col = target_col + self.add_reverse = add_reverse + self.train_ratio = train_ratio + self.test_ratio = test_ratio + self.val_ratio = val_ratio + + def get_graph( + self, + feature_spec: SynGenDatasetFeatureSpec, + edge_name + ): + struct_data = feature_spec.get_structural_data(edge_name) + + edge_info = feature_spec.get_edge_info(edge_name) + + is_bipartite = edge_info[MetaData.SRC_NODE_TYPE] != edge_info[MetaData.DST_NODE_TYPE] + + if is_bipartite: + offset = struct_data[:, 0].max() + 16 + struct_data[:, 1] = struct_data[:, 1] + offset + + # - construct dgl graph + g = dgl.graph((struct_data[:, 0], struct_data[:, 1])) + g.ndata["feat"] = torch.rand((g.num_nodes(), 32)) + + assert g.num_nodes() == (struct_data.max() + 1), f"expected {(struct_data.max() + 1)}, got {g.num_nodes()}" + + if self.add_reverse: + edge_reverse = np.zeros_like(struct_data) + edge_reverse[:, 0] = struct_data[:, 1] + edge_reverse[:, 1] = struct_data[:, 0] + g.add_edges(edge_reverse[:, 0], edge_reverse[:, 1]) + + edge_data = feature_spec.get_tabular_data(MetaData.EDGES, edge_name) + + feature_cols = list(set(edge_data.columns) - {self.target_col}) + + num_rows = len(edge_data) + num_edges = g.num_edges() + + # - extract edge features + labels + features = edge_data[feature_cols].astype(np.float32).values + labels = edge_data[self.target_col].fillna(0).astype(np.float32).values + + if num_rows == num_edges // 2: + # - add reverse features + features = np.concatenate([features, features], axis=0) + # - add reverse labels + labels = np.concatenate([labels, labels], axis=0) + + # - add edge data + g.edata["feat"] = torch.Tensor(features) + g.edata["labels"] = torch.Tensor(labels) + + # - dataset split + num_train = int(self.train_ratio * num_edges) + num_val = int(self.val_ratio * num_edges) + num_test = int(self.test_ratio * num_edges) + + masks = torch.randperm(len(features)) + train_idx = masks[:num_train] + val_idx = masks[num_train : num_train + num_val] + test_idx = masks[num_train + num_val : num_train + num_val + num_test] + + train_mask = torch.zeros(len(features), dtype=torch.bool) + train_mask[train_idx] = True + + val_mask = torch.zeros(len(features), dtype=torch.bool) + val_mask[val_idx] = True + + test_mask = torch.zeros(len(features), dtype=torch.bool) + test_mask[test_idx] = True + + g.edata["train_mask"] = train_mask + g.edata["val_mask"] = val_mask + g.edata["test_mask"] = test_mask + + edge_eids = np.arange(0, len(struct_data)) + return g, edge_eids diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/__init__.py new file mode 100644 index 000000000..4627e7286 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/__init__.py @@ -0,0 +1,22 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .gat_ec import GATEC +from .gcn_ec import GCNEC + +MODELS = { + "gat_ec": GATEC, + "gcn_ec": GCNEC, +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/gat_ec.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/gat_ec.py new file mode 100644 index 000000000..8629938b3 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/gat_ec.py @@ -0,0 +1,166 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import dgl +import torch +import torch.nn as nn +import torch.nn.functional as F + +""" + GAT: Graph Attention Network + Graph Attention Networks (Veličković et al., ICLR 2018) + https://arxiv.org/abs/1710.10903 +""" +from syngen.benchmark.models.layers.gat_layers import ( + CustomGATLayer, + CustomGATLayerEdgeReprFeat, + CustomGATLayerIsotropic, + GATLayer, +) +from syngen.benchmark.models.layers.score_predictor import ScorePredictor + + +class GATEC(nn.Module): + @staticmethod + def add_args(parser): + parser.add_argument( + "--in-feat-dropout", + type=float, + default=0.1, + help="input feature dropout (default: 0.1)", + ) + parser.add_argument( + "--dropout", type=float, default=0.1, help="dropout (default: 0.1)" + ) + parser.add_argument("--batch_norm", action="http://github.com/store_true", default=False) + parser.add_argument("--n-heads", type=int, default=2) + parser.add_argument("--layer-type", type=str, default="dgl") + parser.add_argument("--residual", action="http://github.com/store_true", default=False) + parser.add_argument("--edge_feat", action="http://github.com/store_true", default=False) + + def __init__( + self, + in_dim, + in_dim_edge, + hidden_dim, + out_dim, + num_classes, + n_heads, + in_feat_dropout, + dropout, + n_layers, + readout=False, + edge_feat=False, + batch_norm=False, + residual=False, + layer_type="dgl", + device="cuda", + **kwargs, + ): + super().__init__() + + self.in_dim = in_dim + self.in_dim_edge = in_dim_edge + self.hidden_dim = hidden_dim + self.out_dim = out_dim + self.num_classes = num_classes + self.n_heads = n_heads + self.dropout = dropout + self.n_layers = n_layers + self.readout = readout + self.batch_norm = batch_norm + self.residual = residual + self.device = device + + self.layer_type = { + "dgl": GATLayer, + "edgereprfeat": CustomGATLayerEdgeReprFeat, + "edgefeat": CustomGATLayer, + "isotropic": CustomGATLayerIsotropic, + }.get(layer_type, GATLayer) + + self.embedding_h = nn.Linear( + self.in_dim, self.hidden_dim * self.n_heads + ) + + if self.layer_type != GATLayer: + self.edge_feat = edge_feat + self.embedding_e = nn.Linear( + self.in_dim_edge, self.hidden_dim * self.n_heads + ) + + self.in_feat_dropout = nn.Dropout(in_feat_dropout) + + self.layers = nn.ModuleList( + [ + self.layer_type( + self.hidden_dim * self.n_heads, + self.hidden_dim, + self.n_heads, + self.dropout, + self.batch_norm, + self.residual, + ) + for _ in range(n_layers - 1) + ] + ) + self.layers.append( + self.layer_type( + self.hidden_dim * self.n_heads, + self.out_dim, + 1, + self.dropout, + self.batch_norm, + self.residual, + ) + ) + self.edge_score = ScorePredictor(2 * out_dim, num_classes) + + def forward( + self, + blocks, + edge_subgraph, + input_features, + edge_features, + *args, + **kwargs, + ): + h = self.embedding_h(input_features.float()) + h = self.in_feat_dropout(h) + if self.layer_type == GATLayer: + for idx, conv in enumerate(self.layers): + h = conv(blocks[idx], h) + else: + if not self.edge_feat: + e = torch.ones_like(edge_features).to(self.device) + e = self.embedding_e(edge_features.float()) + + for idx, conv in enumerate(self.layers): + h, e = conv(blocks[idx], h, e) + edge_subgraph.ndata["h"] = h + + def _edge_feat(edges): + e = torch.cat([edges.src["h"], edges.dst["h"]], dim=1) + e = self.edge_score(e) + return {"e": e} + + edge_subgraph.apply_edges(_edge_feat) + + return edge_subgraph.edata["e"] + + def loss(self, pred, label): + criterion = nn.CrossEntropyLoss(weight=None) + loss = criterion(pred, label) + + return loss diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/gcn_ec.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/gcn_ec.py new file mode 100644 index 000000000..6c7ca86a6 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/gcn_ec.py @@ -0,0 +1,79 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import dgl +import dgl.nn as dglnn +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class GCNEC(nn.Module): + + @staticmethod + def add_args(parser): + return parser + + def __init__( + self, in_dim, hidden_dim, out_dim, num_classes, n_layers, **kwargs + ): + super().__init__() + self.gcn = StochasticLayerGCN(in_dim, hidden_dim, out_dim, n_layers) + self.predictor = ScorePredictor(num_classes, out_dim) + + def forward(self, blocks, edge_subgraph, input_features, *args, **kwargs): + x = self.gcn(blocks, input_features) + return self.predictor(edge_subgraph, x) + + def loss(self, pred, label): + loss = torch.nn.functional.binary_cross_entropy_with_logits( + pred, label + ) + return loss + + +class StochasticLayerGCN(nn.Module): + def __init__(self, in_feats, h_feats, out_feats, n_layers): + super().__init__() + self.layers = [] + + if n_layers <= 1: + self.layers.append(dglnn.GraphConv(in_feats, out_feats)) + else: + self.layers.append(dglnn.GraphConv(in_feats, h_feats)) + for _ in range(n_layers - 2): + self.layers.append(dglnn.GraphConv(h_feats, h_feats)) + self.layers.append(dglnn.GraphConv(h_feats, out_feats)) + self.layers = nn.ModuleList(self.layers) + + def forward(self, blocks, x): + for i, layer in enumerate(self.layers): + x = F.relu(layer(blocks[i], x)) + return x + + +class ScorePredictor(nn.Module): + def __init__(self, num_classes, in_feats): + super().__init__() + self.W = nn.Linear(2 * in_feats, num_classes) + + def apply_edges(self, edges): + data = torch.cat([edges.src["x"], edges.dst["x"]], dim=1) + return {"score": self.W(data)} + + def forward(self, edge_subgraph, x): + with edge_subgraph.local_scope(): + edge_subgraph.ndata["x"] = x + edge_subgraph.apply_edges(self.apply_edges) + return edge_subgraph.edata["score"] diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/__init__.py new file mode 100644 index 000000000..b0dbda317 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/gat_layers.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/gat_layers.py new file mode 100644 index 000000000..30e2672db --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/gat_layers.py @@ -0,0 +1,406 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import dgl +import torch +import torch.nn as nn +import torch.nn.functional as F +from dgl.nn.pytorch import GATConv + +""" + GAT: Graph Attention Network + Graph Attention Networks (Veličković et al., ICLR 2018) + https://arxiv.org/abs/1710.10903 +""" + + +class GATLayer(nn.Module): + """ + Parameters + ---------- + in_dim : + Number of input features. + out_dim : + Number of output features. + num_heads : int + Number of heads in Multi-Head Attention. + dropout : + Required for dropout of attn and feat in GATConv + batch_norm : + boolean flag for batch_norm layer. + residual : + If True, use residual connection inside this layer. Default: ``False``. + activation : callable activation function/layer or None, optional. + If not None, applies an activation function to the updated node features. + + Using dgl builtin GATConv by default: + https://github.com/graphdeeplearning/benchmarking-gnns/commit/206e888ecc0f8d941c54e061d5dffcc7ae2142fc + """ + + def __init__( + self, + in_dim, + out_dim, + num_heads, + dropout, + batch_norm, + residual=False, + activation=F.elu, + ): + super().__init__() + self.residual = residual + self.activation = activation + self.batch_norm = batch_norm + + if in_dim != (out_dim * num_heads): + self.residual = False + + if dgl.__version__ < "0.5": + self.gatconv = GATConv( + in_dim, out_dim, num_heads, dropout, dropout + ) + else: + self.gatconv = GATConv( + in_dim, + out_dim, + num_heads, + dropout, + dropout, + allow_zero_in_degree=True, + ) + + if self.batch_norm: + self.batchnorm_h = nn.BatchNorm1d(out_dim * num_heads) + + def forward(self, g, h): + h_in = h # for residual connection + + h = self.gatconv(g, h).flatten(1) + + if self.batch_norm: + h = self.batchnorm_h(h) + + if self.activation: + h = self.activation(h) + + if self.residual: + h = h_in + h # residual connection + + return h + + +############################################################## +# +# Additional layers for edge feature/representation analysis +# +############################################################## + + +class CustomGATHeadLayer(nn.Module): + def __init__(self, in_dim, out_dim, dropout, batch_norm): + super().__init__() + self.dropout = dropout + self.batch_norm = batch_norm + + self.fc = nn.Linear(in_dim, out_dim, bias=False) + self.attn_fc = nn.Linear(2 * out_dim, 1, bias=False) + self.batchnorm_h = nn.BatchNorm1d(out_dim) + + def edge_attention(self, edges): + z2 = torch.cat([edges.src["z"], edges.dst["z"]], dim=1) + a = self.attn_fc(z2) + return {"e": F.leaky_relu(a)} + + def message_func(self, edges): + return {"z": edges.src["z"], "e": edges.data["e"]} + + def reduce_func(self, nodes): + alpha = F.softmax(nodes.mailbox["e"], dim=1) + alpha = F.dropout(alpha, self.dropout, training=self.training) + h = torch.sum(alpha * nodes.mailbox["z"], dim=1) + return {"h": h} + + def forward(self, g, h): + z = self.fc(h) + g.ndata["z"] = z + g.apply_edges(self.edge_attention) + g.update_all(self.message_func, self.reduce_func) + h = g.ndata["h"] + + if self.batch_norm: + h = self.batchnorm_h(h) + + h = F.elu(h) + + h = F.dropout(h, self.dropout, training=self.training) + + return h + + +class CustomGATLayer(nn.Module): + """ + Param: [in_dim, out_dim, n_heads] + """ + + def __init__( + self, in_dim, out_dim, num_heads, dropout, batch_norm, residual=True + ): + super().__init__() + + self.in_channels = in_dim + self.out_channels = out_dim + self.num_heads = num_heads + self.residual = residual + + if in_dim != (out_dim * num_heads): + self.residual = False + + self.heads = nn.ModuleList() + for i in range(num_heads): + self.heads.append( + CustomGATHeadLayer(in_dim, out_dim, dropout, batch_norm) + ) + self.merge = "cat" + + def forward(self, g, h, e): + h_in = h # for residual connection + + head_outs = [attn_head(g, h) for attn_head in self.heads] + + if self.merge == "cat": + h = torch.cat(head_outs, dim=1) + else: + h = torch.mean(torch.stack(head_outs)) + + if self.residual: + h = h_in + h # residual connection + + return h, e + + def __repr__(self): + return "{}(in_channels={}, out_channels={}, heads={}, residual={})".format( + self.__class__.__name__, + self.in_channels, + self.out_channels, + self.num_heads, + self.residual, + ) + + +############################################################## + + +class CustomGATHeadLayerEdgeReprFeat(nn.Module): + def __init__(self, in_dim, out_dim, dropout, batch_norm): + super().__init__() + self.dropout = dropout + self.batch_norm = batch_norm + + self.fc_h = nn.Linear(in_dim, out_dim, bias=False) + self.fc_e = nn.Linear(in_dim, out_dim, bias=False) + self.fc_proj = nn.Linear(3 * out_dim, out_dim) + self.attn_fc = nn.Linear(3 * out_dim, 1, bias=False) + self.batchnorm_h = nn.BatchNorm1d(out_dim) + self.batchnorm_e = nn.BatchNorm1d(out_dim) + + def edge_attention(self, edges): + z = torch.cat( + [edges.data["z_e"], edges.src["z_h"], edges.dst["z_h"]], dim=1 + ) + e_proj = self.fc_proj(z) + attn = F.leaky_relu(self.attn_fc(z)) + return {"attn": attn, "e_proj": e_proj} + + def message_func(self, edges): + return {"z": edges.src["z_h"], "attn": edges.data["attn"]} + + def reduce_func(self, nodes): + alpha = F.softmax(nodes.mailbox["attn"], dim=1) + h = torch.sum(alpha * nodes.mailbox["z"], dim=1) + return {"h": h} + + def forward(self, g, h, e): + import pdb + + pdb.set_trace() + z_h = self.fc_h(h) + z_e = self.fc_e(e) + g.ndata["z_h"] = z_h + g.edata["z_e"] = z_e + + g.apply_edges(self.edge_attention) + + g.update_all(self.message_func, self.reduce_func) + + h = g.ndata["h"] + e = g.edata["e_proj"] + + if self.batch_norm: + h = self.batchnorm_h(h) + e = self.batchnorm_e(e) + + h = F.elu(h) + e = F.elu(e) + + h = F.dropout(h, self.dropout, training=self.training) + e = F.dropout(e, self.dropout, training=self.training) + + return h, e + + +class CustomGATLayerEdgeReprFeat(nn.Module): + """ + Param: [in_dim, out_dim, n_heads] + """ + + def __init__( + self, in_dim, out_dim, num_heads, dropout, batch_norm, residual=True + ): + super().__init__() + + self.in_channels = in_dim + self.out_channels = out_dim + self.num_heads = num_heads + self.residual = residual + + if in_dim != (out_dim * num_heads): + self.residual = False + + self.heads = nn.ModuleList() + for i in range(num_heads): + self.heads.append( + CustomGATHeadLayerEdgeReprFeat( + in_dim, out_dim, dropout, batch_norm + ) + ) + self.merge = "cat" + + def forward(self, g, h, e): + h_in = h # for residual connection + e_in = e + + head_outs_h = [] + head_outs_e = [] + for attn_head in self.heads: + h_temp, e_temp = attn_head(g, h, e) + head_outs_h.append(h_temp) + head_outs_e.append(e_temp) + + if self.merge == "cat": + h = torch.cat(head_outs_h, dim=1) + e = torch.cat(head_outs_e, dim=1) + else: + raise NotImplementedError + + if self.residual: + h = h_in + h # residual connection + e = e_in + e + + return h, e + + def __repr__(self): + return "{}(in_channels={}, out_channels={}, heads={}, residual={})".format( + self.__class__.__name__, + self.in_channels, + self.out_channels, + self.num_heads, + self.residual, + ) + + +############################################################## + + +class CustomGATHeadLayerIsotropic(nn.Module): + def __init__(self, in_dim, out_dim, dropout, batch_norm): + super().__init__() + self.dropout = dropout + self.batch_norm = batch_norm + + self.fc = nn.Linear(in_dim, out_dim, bias=False) + self.batchnorm_h = nn.BatchNorm1d(out_dim) + + def message_func(self, edges): + return {"z": edges.src["z"]} + + def reduce_func(self, nodes): + h = torch.sum(nodes.mailbox["z"], dim=1) + return {"h": h} + + def forward(self, g, h): + z = self.fc(h) + g.ndata["z"] = z + g.update_all(self.message_func, self.reduce_func) + h = g.ndata["h"] + + if self.batch_norm: + h = self.batchnorm_h(h) + + h = F.elu(h) + + h = F.dropout(h, self.dropout, training=self.training) + + return h + + +class CustomGATLayerIsotropic(nn.Module): + """ + Param: [in_dim, out_dim, n_heads] + """ + + def __init__( + self, in_dim, out_dim, num_heads, dropout, batch_norm, residual=True + ): + super().__init__() + + self.in_channels = in_dim + self.out_channels = out_dim + self.num_heads = num_heads + self.residual = residual + + if in_dim != (out_dim * num_heads): + self.residual = False + + self.heads = nn.ModuleList() + for i in range(num_heads): + self.heads.append( + CustomGATHeadLayerIsotropic( + in_dim, out_dim, dropout, batch_norm + ) + ) + self.merge = "cat" + + def forward(self, g, h, e): + h_in = h # for residual connection + + head_outs = [attn_head(g, h) for attn_head in self.heads] + + if self.merge == "cat": + h = torch.cat(head_outs, dim=1) + else: + h = torch.mean(torch.stack(head_outs)) + + if self.residual: + h = h_in + h # residual connection + + return h, e + + def __repr__(self): + return "{}(in_channels={}, out_channels={}, heads={}, residual={})".format( + self.__class__.__name__, + self.in_channels, + self.out_channels, + self.num_heads, + self.residual, + ) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/score_predictor.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/score_predictor.py new file mode 100644 index 000000000..ebed4d840 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/models/layers/score_predictor.py @@ -0,0 +1,45 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn +import torch.nn.functional as F + +""" + Predictor layer +""" + + +class ScorePredictor(nn.Module): + def __init__(self, input_dim, output_dim, L=2): + super().__init__() + list_FC_layers = [ + nn.Linear( + input_dim // 2 ** l, input_dim // 2 ** (l + 1), bias=True + ) + for l in range(L) + ] + list_FC_layers.append( + nn.Linear(input_dim // 2 ** L, output_dim, bias=True) + ) + self.FC_layers = nn.ModuleList(list_FC_layers) + self.L = L + + def forward(self, x): + y = x + for l in range(self.L): + y = self.FC_layers[l](y) + y = F.relu(y) + y = self.FC_layers[self.L](y) + return y diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/tasks/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/tasks/__init__.py new file mode 100644 index 000000000..553bad73b --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/tasks/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .ec import train_ec diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/tasks/ec.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/tasks/ec.py new file mode 100644 index 000000000..201a23eea --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/benchmark/tasks/ec.py @@ -0,0 +1,240 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +from time import perf_counter, time + +import dgl +import numpy as np +import torch +from syngen.benchmark.data_loader.datasets.edge_ds import EdgeDS +from syngen.benchmark.models import MODELS +from syngen.utils.types import MetaData +from syngen.configuration import SynGenDatasetFeatureSpec + +logger = logging.getLogger(__name__) +log = logger + +_NAME = "edge classification" + + +def train_ec( + args, + finetune_feature_spec: SynGenDatasetFeatureSpec, + *, + pretrain_feature_spec: SynGenDatasetFeatureSpec = None, +): + """Example edge classification training loop to pre-train on generated dataset + with option to further finetune on a `finetune_source` dataset. + """ + model = MODELS[args.model] + optimizer = None + out = {} + dataset = EdgeDS(**vars(args)) + + # - pre-training + if pretrain_feature_spec is not None: + # - dataset + g, edge_ids = dataset.get_graph( + pretrain_feature_spec, args.pretraining_edge_name + ) + sampler = dgl.dataloading.MultiLayerFullNeighborSampler(args.n_layers) + dataloader = dgl.dataloading.EdgeDataLoader( + g, + edge_ids, + sampler, + batch_size=args.batch_size, + shuffle=args.shuffle, + drop_last=False, + num_workers=args.num_workers, + ) + # - Model + in_feats = g.ndata.get("feat").shape[1] + in_feats_edge = g.edata.get("feat").shape[1] + model = model(in_dim=in_feats, in_dim_edge=in_feats_edge, **vars(args)) + model = model.cuda() + # - Optimizer + optimizer = torch.optim.Adam( + model.parameters(), + lr=args.learning_rate, + weight_decay=args.weight_decay, + ) + + log.info("Running pretraining ...") + losses, times = [], [] + best_val_acc, best_test_acc = 0, 0 + # - Training loop + for e in range(args.pretrain_epochs): + + if args.timeit: + t0 = time.time() + train_acc, val_acc, test_acc, losses = train_epoch( + model, dataloader, optimizer + ) + if args.timeit: + t1 = time.time() + times.append(t1 - t0) + + val_acc = np.mean(val_acc) + test_acc = np.mean(test_acc) + train_acc = np.mean(train_acc) + loss = np.mean(losses) + + if best_val_acc < val_acc: + best_val_acc = val_acc + best_test_acc = test_acc + + if e % args.log_interval == 0: + log.info( + "Pretraining epoch {}, loss: {:.3f}, val acc: {:.3f} (best {:.3f}), test acc: {:.3f} (best {:.3f})".format( + e, loss, val_acc, best_val_acc, test_acc, best_test_acc + ) + ) + + out = { + "pretrain-loss": loss, + "pretrain-val-acc": val_acc, + "pretrain-test-acc": test_acc, + **out, + } + + if args.timeit: + out["pretrain-epoch-times"] = times + + + g, edge_ids = dataset.get_graph( + finetune_feature_spec, args.edge_name, + ) + + sampler = dgl.dataloading.MultiLayerFullNeighborSampler(args.n_layers) + + dataloader = dgl.dataloading.EdgeDataLoader( + g, + edge_ids, + sampler, + batch_size=args.batch_size, + shuffle=args.shuffle, + drop_last=False, + num_workers=args.num_workers, + ) + + if optimizer is None: + in_feats = g.ndata.get("feat").shape[1] + in_feats_edge = g.edata.get("feat").shape[1] + model = model( + in_dim=in_feats, in_dim_edge=in_feats_edge, **vars(args) + ) + + model = model.cuda() + optimizer = torch.optim.Adam( + model.parameters(), + lr=args.learning_rate, + weight_decay=args.weight_decay, + ) + + # - finetune + best_val_acc, best_test_acc = 0, 0 + for e in range(args.finetune_epochs): + if args.timeit: + t0 = time.time() + train_acc, val_acc, test_acc, losses = train_epoch( + model, dataloader, optimizer + ) + if args.timeit: + t1 = time.time() + times.append(t1 - t0) + + val_acc = np.mean(val_acc) + test_acc = np.mean(test_acc) + train_acc = np.mean(train_acc) + loss = np.mean(losses) + + if best_val_acc < val_acc: + best_val_acc = val_acc + best_test_acc = test_acc + + if e % args.log_interval == 0: + log.info( + "Finetuning: In epoch {}, loss: {:.3f}, val acc: {:.3f} (best {:.3f}), test acc: {:.3f} (best {:.3f})".format( + e, loss, val_acc, best_val_acc, test_acc, best_test_acc + ) + ) + + out = { + "finetune-loss": loss, + "finetune-val-acc": val_acc, + "finetune-test-acc": test_acc, + **out, + } + + if args.timeit: + out["finetune-epoch-times"] = times + + return out + + +def train_epoch(model, dataloader, optimizer, verbose=False): + train_acc = [] + val_acc = [] + test_acc = [] + losses = [] + if verbose: + times = [] + epoch_start = perf_counter() + for input_nodes, edge_subgraph, blocks in dataloader: + blocks = [b.to(torch.device("cuda")) for b in blocks] + edge_subgraph = edge_subgraph.to(torch.device("cuda")) + input_features = blocks[0].srcdata["feat"] + edge_labels = edge_subgraph.edata["labels"] + edge_features = None + if "feat" in edge_subgraph.edata: + edge_features = edge_subgraph.edata["feat"] + edge_predictions = model( + blocks=blocks, + edge_subgraph=edge_subgraph, + input_features=input_features, + edge_features=edge_features, + ) + train_mask = edge_subgraph.edata["train_mask"] + val_mask = edge_subgraph.edata["val_mask"] + test_mask = edge_subgraph.edata["test_mask"] + loss = model.loss( + edge_predictions[train_mask], + torch.nn.functional.one_hot( + edge_labels[train_mask].long(), + num_classes=edge_predictions.shape[-1], + ).float(), + ) + # - store results + losses.append(loss.item()) + preds = edge_predictions.argmax(1) + train_acc.append( + (preds[train_mask] == edge_labels[train_mask]).float().mean().item() + ) + val_acc.append( + (preds[val_mask] == edge_labels[val_mask]).float().mean().item() + ) + test_acc.append( + (preds[test_mask] == edge_labels[test_mask]).float().mean().item() + ) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + if verbose: + times.append(perf_counter() - epoch_start) + epoch_start = perf_counter() + if verbose: + return train_acc, val_acc, test_acc, losses, times + return train_acc, val_acc, test_acc, losses diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/__init__.py new file mode 100644 index 000000000..6e61e9c06 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/__init__.py @@ -0,0 +1,36 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse + +from syngen.cli.commands.synthesize import SynthesizeCommand +from syngen.cli.commands.preprocess import PreprocessingCommand +from syngen.cli.commands.mimic_dataset import MimicDatasetCommand +from syngen.cli.commands.pretrain import PretrainCommand + + +def get_parser(): + parser = argparse.ArgumentParser( + description="Synthetic Graph Generation Tool", + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + command = parser.add_subparsers(title="command") + command.required = True + + SynthesizeCommand().init_parser(command) + PreprocessingCommand().init_parser(command) + MimicDatasetCommand().init_parser(command) + PretrainCommand().init_parser(command) + + return parser diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/__init__.py similarity index 84% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/__init__.py rename to Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/__init__.py index 8ad3be9f6..44d6e3348 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/__init__.py +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -10,4 +10,4 @@ # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and -# limitations under the License. \ No newline at end of file +# limitations under the License. diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/base_command.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/base_command.py new file mode 100644 index 000000000..535227318 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/base_command.py @@ -0,0 +1,21 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +class BaseCommand(object): + + def init_parser(self, base_parser): + raise NotImplementedError() + + def run(self, args): + raise NotImplementedError() diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/mimic_dataset.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/mimic_dataset.py new file mode 100644 index 000000000..b9beea2c6 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/mimic_dataset.py @@ -0,0 +1,159 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import argparse +import json +import logging +from collections import defaultdict + +from syngen.cli.commands.base_command import BaseCommand +from syngen.configuration import SynGenDatasetFeatureSpec, SynGenConfiguration +from syngen.generator.tabular import tabular_generators_classes + +from syngen.utils.types import MetaData + +logger = logging.getLogger(__name__) +log = logger + + +class MimicDatasetCommand(BaseCommand): + + def init_parser(self, base_parser): + mimic_parser = base_parser.add_parser( + "mimic-dataset", + help="Quickly creates a SynGen Configuration for the given dataset", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + mimic_parser.set_defaults(action=self.run) + + mimic_parser.add_argument( + "-dp", "--dataset-path", type=str, required=True, + help="Path to the dataset in SynGen format" + ) + mimic_parser.add_argument( + "-of", "--output-file", type=str, required=True, + help="Path to the generated SynGen Configuration" + ) + mimic_parser.add_argument( + "-tg", "--tab-gen", type=str, choices=list(tabular_generators_classes.keys()), default='kde', + help="Tabular Generator to mimic all tabular features" + ) + mimic_parser.add_argument( + "-rsg", "--random-struct-gen", action='http://github.com/store_true', + help="Generates random structure based on Erdos-Renyi model" + ) + mimic_parser.add_argument( + "-es", "--edge-scale", type=float, default=None, + help="Multiples the number of edges to generate by the provided number" + ) + mimic_parser.add_argument( + "-en", "--node-scale", type=float, default=None, + help="Multiples the number of nodes to generate by the provided number" + ) + mimic_parser.add_argument( + "-gdp", "--gen-dump-path", type=str, default=None, + help="Path to store the fitted generators" + ) + + def run(self, args): + + dict_args = vars(args) + feature_spec = SynGenDatasetFeatureSpec.instantiate_from_preprocessed(dict_args['dataset_path']) + + scales = { + MetaData.EDGES: dict_args['edge_scale'], + MetaData.NODES: dict_args['node_scale'], + } + + for part in [MetaData.NODES, MetaData.EDGES]: + for part_info in feature_spec[part]: + + if scales[part]: + part_info[MetaData.COUNT] = int(part_info[MetaData.COUNT] * scales[part]) + + if MetaData.FEATURES in part_info and len(part_info[MetaData.FEATURES]) > 0: + + feature_files_content = defaultdict(list) + + for feature in part_info[MetaData.FEATURES]: + if MetaData.FEATURE_FILE in feature: + feature_files_content[feature[MetaData.FEATURE_FILE]].append(feature[MetaData.NAME]) + + if feature_files_content: + part_info[MetaData.TABULAR_GENERATORS] = [ + { + MetaData.TYPE: dict_args['tab_gen'], + MetaData.FEATURES_LIST: feats_list, + MetaData.FEATURE_FILE: ff, + MetaData.DATA_SOURCE: { + MetaData.TYPE: 'rnd', + } if dict_args['tab_gen'] == 'random' + else + { + MetaData.TYPE: 'cfg', + MetaData.PATH: dict_args['dataset_path'], + MetaData.NAME: part_info[MetaData.NAME], + }, + MetaData.PARAMS: {}, + MetaData.DUMP_PATH: os.path.join(dict_args['gen_dump_path'], + f"{part}_{part_info[MetaData.NAME]}_tab_gen_{idx}.pkl") + if dict_args['gen_dump_path'] else None + } + for idx, (ff, feats_list) in enumerate(feature_files_content.items()) + ] + else: + part_info[MetaData.TABULAR_GENERATORS] = [ + { + MetaData.TYPE: dict_args['tab_gen'], + MetaData.FEATURES_LIST: -1, + MetaData.DATA_SOURCE: { + MetaData.TYPE: 'rnd', + } if dict_args['tab_gen'] == 'random' + else + { + MetaData.TYPE: 'cfg', + MetaData.PATH: dict_args['dataset_path'], + MetaData.NAME: part_info[MetaData.NAME], + }, + MetaData.PARAMS: {}, + MetaData.DUMP_PATH: os.path.join(dict_args['gen_dump_path'], + f"{part}_{part_info[MetaData.NAME]}_tab_gen_{0}.pkl") + if dict_args['gen_dump_path'] else None + } + ] + if part == MetaData.EDGES: + part_info[MetaData.STRUCTURE_GENERATOR] = { + MetaData.TYPE: 'RMAT', + MetaData.DATA_SOURCE: { + MetaData.TYPE: 'rnd', + } if dict_args['random_struct_gen'] + else + { + MetaData.TYPE: 'cfg', + MetaData.PATH: dict_args['dataset_path'], + MetaData.NAME: part_info[MetaData.NAME], + }, + MetaData.PARAMS: {}, + MetaData.DUMP_PATH: os.path.join(dict_args['gen_dump_path'], + f"{part_info[MetaData.NAME]}_struct_gen.pkl") + if dict_args['gen_dump_path'] else None + } + + config = SynGenConfiguration(feature_spec) + + with open(dict_args['output_file'], 'w') as f: + json.dump(config, f, indent=4) + + log.info(f"SynGen Configuration saved into {dict_args['output_file']}") diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/preprocess.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/preprocess.py new file mode 100644 index 000000000..6bf125357 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/preprocess.py @@ -0,0 +1,94 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import logging + +from syngen.cli.commands.base_command import BaseCommand +from syngen.preprocessing.datasets import DATASETS + +logger = logging.getLogger(__name__) +log = logger + + +class PreprocessingCommand(BaseCommand): + + def init_parser(self, base_parser): + preprocessing_parser = base_parser.add_parser( + "preprocess", + help="Run Dataset Preprocessing", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + preprocessing_parser.set_defaults(action=self.run) + + preprocessing_parser.add_argument( + "--dataset", type=str, default=None, required=True, choices=list(DATASETS.keys()), + help="Dataset to preprocess", + ) + preprocessing_parser.add_argument( + "-sp", "--source-path", type=str, default=None, required=True, + help="Path to raw data", + ) + preprocessing_parser.add_argument( + "-dp", "--destination-path", type=str, default=None, required=False, + help="Path to store the preprocessed data. Default is $source_path/syngen_preprocessed", + ) + preprocessing_parser.add_argument( + "--download", + action='http://github.com/store_true', + help="Downloads the dataset if specified", + ) + preprocessing_parser.add_argument( + "--cpu", + action='http://github.com/store_true', + help='Performs the preprocessing_parser without leveraging GPU' + ) + preprocessing_parser.add_argument( + "--use-cache", + action='http://github.com/store_true', + help='Does nothing if the target preprocessed dataset exists' + ) + + for preprocessing_class in DATASETS.values(): + preprocessing_class.add_cli_args(preprocessing_parser) + + def run(self, args): + dict_args = vars(args) + + dataset_name = dict_args.pop('dataset') + source_path = dict_args.pop('source_path') + destination_path = dict_args.pop('destination_path') + download = dict_args.pop('download') + + gpu = not dict_args.pop('cpu') + use_cache = dict_args.pop('use_cache') + + preprocessing_class = DATASETS[dataset_name] + + if download: + try: + preprocessing_class(source_path=source_path, + destination_path=destination_path, + download=download, + **dict_args) + log.info(f"{dataset_name} successfully downloaded into {source_path}") + except NotImplementedError: + log.info(f"{dataset_name} does not support automatic downloading, please download the dataset manually") + else: + preprocessing = preprocessing_class(source_path=source_path, + destination_path=destination_path, + download=download, + **dict_args) + preprocessing.transform(gpu=gpu, use_cache=use_cache) + log.info(f"{dataset_name} successfully preprocessed into {preprocessing.destination_path}") diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/pretrain.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/pretrain.py new file mode 100644 index 000000000..4b4a85c66 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/pretrain.py @@ -0,0 +1,221 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import logging + +from syngen.cli.commands.base_command import BaseCommand + +from syngen.benchmark.tasks import train_ec + +from syngen.configuration import SynGenDatasetFeatureSpec, SynGenConfiguration +from syngen.generator.tabular import tabular_generators_classes + +from syngen.utils.types import MetaData +from syngen.benchmark.models import MODELS + +logging.basicConfig() +logging.root.setLevel(logging.NOTSET) +logger = logging.getLogger(__name__) +log = logger + + +class PretrainCommand(BaseCommand): + + def init_parser(self, base_parser): + pretrain_parser = base_parser.add_parser( + "pretrain", + help="Run Synthetic Graph Data Pre-training Tool", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + pretrain_parser.set_defaults(action=self.run) + + # global + pretrain_parser.add_argument( + "--task", + type=str, + default="ec", + help=f"now the only available option is ec (edge-classification)", + ) + pretrain_parser.add_argument( + "--seed", + type=int, + default=777, + help="Set a seed globally" + ) + pretrain_parser.add_argument( + "--timeit", + action="http://github.com/store_true", + help="Measures average training time", + ) + pretrain_parser.add_argument( + "--data-path", + type=str, + required=True, + help="Path to dataset in SynGen format to train/finetune on", + ) + pretrain_parser.add_argument( + "--edge-name", + type=str, + required=True, + help="Name of the edge to be used during train/finetune", + ) + pretrain_parser.add_argument( + "--pretraining-data-path", + type=str, + default=None, + help="Path to dataset in SynGen format to pretrain on", + ) + pretrain_parser.add_argument( + "--pretraining-edge-name", + type=str, + default=None, + help="Name of the edge to be used during pretraining", + ) + + # model + pretrain_parser.add_argument( + "--model", + type=str, + default="gat_ec", + help=f"List of available models: {list(MODELS.keys())}", + ) + pretrain_parser.add_argument( + "--hidden-dim", + type=int, + default=128, + help="Hidden feature dimension" + ) + pretrain_parser.add_argument( + "--out-dim", + type=int, + default=32, + help="Output feature dimension", + ) + pretrain_parser.add_argument( + "--num-classes", + type=int, + required=True, + help="Number of classes in the target column", + ) + pretrain_parser.add_argument( + "--n-layers", + type=int, + default=1, + help="Multi-layer full neighborhood sampler layers", + ) + for key in MODELS.keys(): + MODELS[key].add_args(pretrain_parser) + + # dataset + pretrain_parser.add_argument( + "--target-col", + type=str, + required=True, + help="Target column for downstream prediction", + ) + pretrain_parser.add_argument( + "--train-ratio", + type=float, + default=0.8, + help="Ratio of data to use as train", + ) + pretrain_parser.add_argument( + "--val-ratio", + type=float, + default=0.1, + help="Ratio of data to use as val", + ) + pretrain_parser.add_argument( + "--test-ratio", + type=float, + default=0.1, + help="Ratio of data to use as test", + ) + + # training + pretrain_parser.add_argument( + "--learning-rate", + "--lr", + dest="learning_rate", + type=float, + default=1e-3, + help=f"Initial learning rate for optimizer", + ) + pretrain_parser.add_argument( + "--weight-decay", + type=float, + default=0.1, + help=f"Weight decay for optimizer", + ) + pretrain_parser.add_argument( + "--batch-size", + type=int, + default=128, + help="Pre-training and Fine-tuning dataloader batch size", + ) + pretrain_parser.add_argument( + "--num-workers", + type=int, + default=8, + help="Number of dataloading workers", + ) + pretrain_parser.add_argument( + "--shuffle", + action="http://github.com/store_true", + default=False, + help="Shuffles data each epoch" + ) + pretrain_parser.add_argument( + "--pretrain-epochs", + type=int, + default=0, + help="Number of pre-training epochs", + ) + pretrain_parser.add_argument( + "--finetune-epochs", + type=int, + default=1, + help="Number of finetuning epochs", + ) + pretrain_parser.add_argument( + "--log-interval", + type=int, + default=1, + help="logging interval" + ) + + def run(self, args): + dict_args = vars(args) + + finetune_feature_spec = SynGenDatasetFeatureSpec.instantiate_from_preprocessed( + dict_args['data_path'] + ) + pretrain_feature_spec = None + + if dict_args['pretraining_data_path']: + pretrain_feature_spec = SynGenDatasetFeatureSpec.instantiate_from_preprocessed( + dict_args['pretraining_data_path'] + ) + + if args.task == "ec": + out = train_ec( + args, + finetune_feature_spec=finetune_feature_spec, + pretrain_feature_spec=pretrain_feature_spec, + ) + else: + raise ValueError("benchmark not supported") + log.info(out) + return out diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/synthesize.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/synthesize.py new file mode 100644 index 000000000..0f6a41451 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/cli/commands/synthesize.py @@ -0,0 +1,70 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import json + +from syngen.cli.commands.base_command import BaseCommand + +from syngen.configuration.configuration import SynGenConfiguration +from syngen.synthesizer.configuration_graph_synthesizer import ConfigurationGraphSynthesizer + + +class SynthesizeCommand(BaseCommand): + + def init_parser(self, base_parser): + synthesizer = base_parser.add_parser( + "synthesize", + help="Run Graph Synthesizer", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + synthesizer.set_defaults(action=self.run) + + synthesizer.add_argument( + "-cp", "--config-path", type=str, default=None, help="Path to SynGen Configuration file" + ) + synthesizer.add_argument( + "--timer-path", type=str, default=None, + help="Saves generation process timings to the specified file" + ) + synthesizer.add_argument( + "-sp", "--save-path", type=str, default="./generated", required=False, + help="Save path to dump generated files", + ) + synthesizer.add_argument( + "--cpu", action='http://github.com/store_true', + help="Runs all operations on CPU. [Attention] Alignment is not available on CPU" + ) + synthesizer.add_argument( + "-v", "--verbose", action='http://github.com/store_true', + help="Displays generation process progress" + ) + + def run(self, args): + dict_args = vars(args) + + config_path = dict_args.pop('config_path') + gpu = not dict_args.pop('cpu') + + with open(config_path, 'r') as f: + configuration = json.load(f) + configuration = SynGenConfiguration(configuration) + + synthesizer = ConfigurationGraphSynthesizer( + configuration, + gpu=gpu, + **dict_args, + ) + synthesizer.fit() + synthesizer.generate(return_data=False) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/__init__.py new file mode 100644 index 000000000..121d7c90a --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .configuration import SynGenDatasetFeatureSpec, SynGenConfiguration diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/configuration.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/configuration.py new file mode 100644 index 000000000..85eac2962 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/configuration.py @@ -0,0 +1,285 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import json +import os +import warnings +from typing import Dict, Optional, Union + +from syngen.configuration.utils import optional_comparison, one_field_from_list_of_dicts +from syngen.utils.io_utils import load_dataframe, load_graph +from syngen.utils.types import MetaData, DataSourceInputType + + +class SynGenDatasetFeatureSpec(dict): + """ SynGenDatasetFeatureSpec is an util class to simply the work with SynGen Dataset Format + Args: + graph_metadata (Dict): dict in SynGen Format + """ + + def __init__(self, graph_metadata: Dict): + super().__init__(graph_metadata) + + @staticmethod + def instantiate_from_preprocessed(path: str): + """ Creates a SynGenDatasetFeatureSpec and checks all specified files + Args: + path: path to the directory with a dataset in SynGen Format + """ + if os.path.isfile(path): + file_path = path + dir_path = os.path.dirname(file_path) + elif os.path.isdir(path): + file_path = os.path.join(path, 'graph_metadata.json') + dir_path = path + else: + raise ValueError(f"expected path to existing file or directory. got {path}") + + with open(file_path, 'r') as f: + graph_metadata = json.load(f) + + graph_metadata[MetaData.PATH] = dir_path + config = SynGenDatasetFeatureSpec(graph_metadata) + config.validate() + return config + + def get_tabular_data(self, part, name, cache=False, absolute_path=None, return_cat_feats=False): + part_info = self.get_info(part, name) + + if MetaData.FEATURES_DATA in part_info: + return part_info[MetaData.FEATURES_DATA] + + part_features_info = part_info[MetaData.FEATURES] + part_features_path = part_info[MetaData.FEATURES_PATH] + + if part_features_path is None: + raise ValueError() + + if MetaData.PATH not in self: + if absolute_path is None: + raise ValueError("Please specify the absolute path for the feature spec: " + "by passing absolute_path argument or specifying MetaData.PATH in the Feature Spec") + else: + self[MetaData.PATH] = absolute_path + + features_df = load_dataframe(os.path.join(self[MetaData.PATH], part_features_path), + feature_info=part_features_info) + if cache: + part_info[MetaData.FEATURES_DATA] = features_df + + if return_cat_feats: + cat_features = [ + feature_info[MetaData.NAME] + for feature_info in part_info[MetaData.FEATURES] + if feature_info[MetaData.FEATURE_TYPE] == MetaData.CATEGORICAL + ] + return features_df, cat_features + return features_df + + def get_structural_data(self, edge_name, cache=False, absolute_path=None, ): + edge_info = self.get_edge_info(edge_name) + + if MetaData.STRUCTURE_DATA in edge_info: + return edge_info[MetaData.STRUCTURE_DATA] + + structure_path = edge_info[MetaData.STRUCTURE_PATH] + + if structure_path is None: + raise ValueError() + + if MetaData.PATH not in self: + if absolute_path is None: + raise ValueError("Please specify the absolute path for the feature spec: " + "by passing absolute_path argument or specifying MetaData.PATH in the Feature Spec") + else: + self[MetaData.PATH] = absolute_path + + graph = load_graph(os.path.join(self[MetaData.PATH], structure_path)) + + if cache: + edge_info[MetaData.STRUCTURE_DATA] = graph + return graph + + def get_edge_info(self, name: Union[str, list], src_node_type: Optional[str] = None, + dst_node_type: Optional[str] = None): + if isinstance(name, list): + src_node_type, name, dst_node_type = name + for edge_type in self[MetaData.EDGES]: + if edge_type[MetaData.NAME] == name \ + and optional_comparison(src_node_type, edge_type[MetaData.SRC_NODE_TYPE]) \ + and optional_comparison(dst_node_type, edge_type[MetaData.DST_NODE_TYPE]): + return edge_type + + def get_node_info(self, name: str): + for node_type in self[MetaData.NODES]: + if node_type[MetaData.NAME] == name: + return node_type + + def get_info(self, part, name): + if part == MetaData.NODES: + return self.get_node_info(name) + elif part == MetaData.EDGES: + return self.get_edge_info(name) + else: + raise ValueError(f"unsupported FeatureSpec part expected [{MetaData.NODES}, {MetaData.EDGES}], got {part}") + + def validate(self): + + for part in [MetaData.NODES, MetaData.EDGES]: + for part_info in self[part]: + if part_info[MetaData.FEATURES_PATH]: + tab_path = os.path.join(self[MetaData.PATH], part_info[MetaData.FEATURES_PATH]) + assert os.path.exists(tab_path), f"{part}-{part_info[MetaData.NAME]}: {tab_path} does not exist" + assert len(part_info[MetaData.FEATURES]) > 0, \ + f"{part}-{part_info[MetaData.NAME]}: tabular features are not specified" + + feature_files = one_field_from_list_of_dicts( + part_info[MetaData.FEATURES], MetaData.FEATURE_FILE, res_aggregator=set) + + if len(feature_files) > 1: + assert os.path.isdir(tab_path), \ + "different feature files are specified MetaData. FEATURES_PATH should be a directory" + for ff in feature_files: + ff_path = os.path.join(tab_path, ff) + assert os.path.exists(ff_path), \ + f"{part}-{part_info[MetaData.NAME]}: {ff_path} does not exist" + + if part == MetaData.EDGES: + struct_path = os.path.join(self[MetaData.PATH], part_info[MetaData.STRUCTURE_PATH]) + assert os.path.exists(struct_path), \ + f"{part}-{part_info[MetaData.NAME]}: {struct_path} does not exist" + + def copy(self): + res = {} + + keys_to_ignore = {MetaData.STRUCTURE_DATA, MetaData.FEATURES_DATA} + + for part in (MetaData.EDGES, MetaData.NODES): + res[part] = [ + { + k: copy.deepcopy(v) + for k, v in part_info.items() if k not in keys_to_ignore + } + for part_info in self[part] + ] + + return SynGenDatasetFeatureSpec(res) + + +class SynGenConfiguration(SynGenDatasetFeatureSpec): + """ SynGen Configuration + + """ + def __init__(self, configuration: Dict): + super().__init__(configuration) + self._fill_missing_values() + self.validate() + + def validate(self): + if MetaData.ALIGNERS in self: + for aligner_info in self[MetaData.ALIGNERS]: + + for edge_name in aligner_info[MetaData.EDGES]: + if not self.get_edge_info(edge_name)[MetaData.FEATURES_PATH].endswith(".parquet"): + raise ValueError("Alignment supports only .parquet files right now") + + for node_name in aligner_info[MetaData.NODES]: + if not self.get_node_info(node_name)[MetaData.FEATURES_PATH].endswith(".parquet"): + raise ValueError("Alignment supports only .parquet files right now") + + + def _process_tabular_generators(self, graph_part_info, part): + + if MetaData.TABULAR_GENERATORS not in graph_part_info: + return + + if graph_part_info[MetaData.FEATURES] == -1: + assert len(graph_part_info[MetaData.TABULAR_GENERATORS]) == 1 + tab_gen_cfg = graph_part_info[MetaData.TABULAR_GENERATORS][0] + assert tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.TYPE] == DataSourceInputType.CONFIGURATION + + cfg = SynGenConfiguration.instantiate_from_preprocessed(tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.PATH]) + data_source_part_info = cfg.get_info(part, tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.NAME]) + graph_part_info[MetaData.FEATURES] = data_source_part_info[MetaData.FEATURES] + + for tab_gen_cfg in graph_part_info[MetaData.TABULAR_GENERATORS]: + if tab_gen_cfg[MetaData.FEATURES_LIST] == -1: + assert len(graph_part_info[MetaData.TABULAR_GENERATORS]) == 1, \ + "you may use mimic value (-1) only if you specify a single tabular generator" + tab_gen_cfg[MetaData.FEATURES_LIST] = [f[MetaData.NAME] for f in graph_part_info[MetaData.FEATURES]] + + if tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.TYPE] == DataSourceInputType.RANDOM: + edge_features = [f[MetaData.NAME] for f in graph_part_info[MetaData.FEATURES]] + for feature_name in tab_gen_cfg[MetaData.FEATURES_LIST]: + if feature_name not in edge_features: + graph_part_info[MetaData.FEATURES].append( + { + MetaData.NAME: feature_name, + MetaData.DTYPE: 'float32', + MetaData.FEATURE_TYPE: MetaData.CONTINUOUS, + # Now random generator supports only continuous features + } + ) + + def _fill_missing_values(self): + for part in [MetaData.NODES, MetaData.EDGES]: + for part_info in self[part]: + + if MetaData.FEATURES not in part_info: + part_info[MetaData.FEATURES] = [] + warnings.warn( + f"{part}-{part_info[MetaData.NAME]}: no {MetaData.FEATURES} specified, default is []") + + if MetaData.FEATURES_PATH not in part_info: + part_info[MetaData.FEATURES_PATH] = None + warnings.warn( + f"{part}-{part_info[MetaData.NAME]}: no {MetaData.FEATURES_PATH} specified, default is None") + + if MetaData.COUNT not in part_info: + part_info[MetaData.COUNT] = -1 + warnings.warn( + f"{part}-{part_info[MetaData.NAME]}: no {MetaData.COUNT} specified, " + f"try to mimic based on generators data") + + self._process_tabular_generators(part_info, part) + + if part == MetaData.EDGES: + + if MetaData.DIRECTED not in part_info: + part_info[MetaData.DIRECTED] = False + + if part_info[MetaData.COUNT] == -1: + + data_source_info = part_info[MetaData.STRUCTURE_GENERATOR][MetaData.DATA_SOURCE] + + if data_source_info[MetaData.TYPE] == DataSourceInputType.CONFIGURATION: + cfg = SynGenConfiguration.instantiate_from_preprocessed(data_source_info[MetaData.PATH]) + data_source_part_info = cfg.get_info(part, data_source_info[MetaData.NAME]) + elif data_source_info[MetaData.TYPE] == DataSourceInputType.RANDOM: + raise ValueError('Can\'t fill the ') + else: + raise ValueError("unsupported structure generator datasource type") + + if part_info[MetaData.COUNT] == -1: + part_info[MetaData.COUNT] = data_source_part_info[MetaData.COUNT] + + def copy(self): + + res = super().copy() + + if MetaData.ALIGNERS in self: + res[MetaData.ALIGNERS] = copy.deepcopy(self[MetaData.ALIGNERS]) + + return SynGenConfiguration(res) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/utils.py new file mode 100644 index 000000000..83aa1bc96 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/configuration/utils.py @@ -0,0 +1,25 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Dict, Iterable + + +def optional_comparison(optional, value): + if optional is None: + return True + return optional == value + + +def one_field_from_list_of_dicts(dicts: Iterable[Dict], field: str, res_aggregator=list): + return res_aggregator(d[field] for d in dicts if field in d) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/__init__.py new file mode 100644 index 000000000..b0dbda317 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/__init__.py new file mode 100644 index 000000000..901f5a9af --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/__init__.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .base_graph_generator import BaseGenerator, BaseGraphGenerator, BaseBipartiteGraphGenerator +from .rmat import RMATGenerator +from .rmat_bipartite import RMATBipartiteGenerator +from .random import RandomGraph +from .random_bipartite import RandomBipartite + + +def get_structural_generator_class(type, is_bipartite, is_random): + if type == 'RMAT': + rmats = { + (True, True): RandomBipartite, + (True, False): RMATBipartiteGenerator, + (False, True): RandomGraph, + (False, False): RMATGenerator + } + return rmats[(is_bipartite, is_random)] + else: + raise ValueError("unsupported generator type") + diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/base_graph_generator.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/base_graph_generator.py new file mode 100644 index 000000000..38a3dc2ce --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/base_graph_generator.py @@ -0,0 +1,283 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import abc +import json +import pickle +from abc import ABC +from typing import List, Optional, Set, Tuple + +import numpy as np + +from syngen.generator.graph.utils import BaseLogger +from syngen.generator.graph.seeder import BaseSeeder + + +class BaseGenerator(abc.ABC): + """ BaseGenerator class """ + + JSON_ASSERTION = "Expected file to be json" + + @classmethod + def get_generators(cls, include_parents=True): + """ Recursively find subclasses + Args: + include_parents (bool): whether to include parents to other classes. (default: `True`) + Returns: + generators: dictionary with all the subclasses + """ + + generators = dict() + for child in cls.__subclasses__(): + children = child.get_generators(include_parents) + generators.update(children) + + if include_parents or not children: + if abc.ABC not in child.__bases__ and BaseGenerator not in child.__bases__: + generators[child.__name__] = child + return generators + + def save(self, path): + raise NotImplementedError() + + @classmethod + def load(cls, path): + raise NotImplementedError() + + +class BaseGraphGenerator(BaseGenerator, ABC): + """ Base class for all graph generators + Args: + *args: optional positional args + **kwargs: optional key-word args + """ + + def __init__( + self, + seed: Optional[int] = None, + logdir: str = "./logs", + gpu: bool = True, + verbose: bool = False, + *args, + **kwargs, + ): + self._fit_results = None + self.seeder = BaseSeeder(seed) + self.seeder.reseed() + self.logger = BaseLogger(logdir) + self.logger.log(f"Using seed: {self.seeder.seed}") + self.gpu = gpu + self.verbose = verbose + + def fit( + self, graph: List[Tuple[int, int]], is_directed: bool, *args, **kwargs + ): + """ Fits generator on the graph + Args: + graph (List[Tuple[int, int]]): graph to be fitted on + is_directed (bool): flag indicating whether the graph is directed + *args: optional positional args + **kwargs: optional key-word args + """ + raise NotImplementedError() + + def generate( + self, + num_nodes: int, + num_edges: int, + is_directed: bool, + *args, + return_node_ids: bool = False, + **kwargs, + ) -> np.ndarray: + """ Generates graph with approximately `num_nodes` and exactly `num_edges` from generator + Args: + num_nodes (int): approximate number of nodes to be generated + num_edges (int): exact number of edges to be generated + is_directed (bool): flag indicating whether the generated graph has to be directed + return_node_ids (bool): flag indicating whether the generator has to return nodes_ids as the second output + *args: optional positional args + **kwargs: optional key-word args + """ + raise NotImplementedError() + + def set_fit_results(self, fit_results): + self._fit_results = fit_results + + def get_fit_results(self): + return self._fit_results + + def save_fit_results(self, save_path: str = "./fit_results.json"): + """ Store fitted results into json file + Args: + save_path (str): path to the json file with the fitted result + """ + assert ( + self._fit_results + ), "There are no fit results to be saved, \ + call fit method first or load the results from the file" + assert save_path.endswith(".json"), self.JSON_ASSERTION + with open(save_path, "w") as fjson: + json.dump(self._fit_results, fjson) + + def load_fit_results(self, load_path: str = "./fit_results.json"): + """load fitted results from json file + Args: + load_path (str): path to the json file with the fitted result + """ + assert load_path.endswith(".json"), self.JSON_ASSERTION + with open(load_path, "r") as fjson: + self._fit_results = json.load(fjson) + + def save(self, path): + with open(path, 'wb') as file_handler: + pickle.dump(self, file_handler, protocol=pickle.HIGHEST_PROTOCOL) + + @classmethod + def load(cls, path): + with open(path, 'rb') as file_handler: + model = pickle.load(file_handler) + return model + + @staticmethod + def add_args(parser): + return parser + + +class BaseBipartiteGraphGenerator(BaseGenerator, ABC): + """ Base class for all bipartite graph generators + Args: + *args: optional positional args + **kwargs: optional key-word args + """ + + def __init__( + self, + seed: Optional[int] = None, + logdir: str = "./logs", + gpu: bool = True, + verbose: bool = False, + *args, + **kwargs, + ): + self._fit_src_dst_results = None + self._fit_dst_src_results = None + self.seeder = BaseSeeder(seed) + self.seeder.reseed() + self.logger = BaseLogger(logdir) + self.logger.log(f"Using seed: {self.seeder.seed}") + self.gpu = gpu + self.verbose = verbose + + def fit( + self, + graph: List[Tuple[int, int]], + src_set: Set[int], + dst_set: Set[int], + is_directed: bool, + transform_graph: bool, + *args, + **kwargs, + ): + """ Fits generator on the graph + + Args: + graph (List[Tuple[int, int]]): graph to be fitted on + src_set (Set[int]): set of source nodes + dst_set (Set[int]): set of destination nodes + is_directed (bool): flag indicating whether the graph is directed + *args: optional positional args + **kwargs: optional key-word args + """ + raise NotImplementedError() + + def generate( + self, + num_nodes_src_set: int, + num_nodes_dst_set: int, + num_edges_src_dst: int, + num_edges_dst_src: int, + is_directed: bool, + return_node_ids: bool = False, + transform_graph: bool = True, + *args, + **kwargs, + ): + """ Generates graph with approximately `num_nodes_src_set`/`num_nodes_dst_set` nodes + and exactly `num_edges_src_dst`/`num_edges_dst_src` edges from generator + Args: + num_nodes_src_set (int): approximate number of source nodes to be generated + num_nodes_dst_set (int): approximate number of destination nodes to be generated + num_edges_src_dst (int): exact number of source->destination edges to be generated + num_edges_dst_src (int): exact number of destination->source to be generated + is_directed (bool) flag indicating whether the generated graph has to be directed + return_node_ids (bool): flag indicating whether the generator has to return nodes_ids as the second output + *args: optional positional args + **kwargs: optional key-word args + """ + raise NotImplementedError() + + def set_fit_results(self, fit_results): + self._fit_src_dst_results, self._fit_dst_src_results = fit_results + + def get_fit_results(self): + return self._fit_src_dst_results, self._fit_dst_src_results + + def save_fit_results(self, save_path: str = "./fit_results.json"): + """ Stores fitted results into json file + Args: + save_path (str): path to the json file with the fitted result + """ + assert ( + self._fit_src_dst_results or self._fit_dst_src_results + ), "There are no fit results to be saved, \ + call fit method first or load the results from the file" + assert save_path.endswith(".json"), self.JSON_ASSERTION + + wrapped_results = { + "fit_src_dst_results": self._fit_src_dst_results, + "fit_dst_src_results": self._fit_dst_src_results, + } + + with open(save_path, "w") as fjson: + json.dump(wrapped_results, fjson) + + def load_fit_results(self, load_path: str = "./fit_results.json"): + """ Loads fitted results from json file + Args: + load_path (str): path to the json file with the fitted result + """ + assert load_path.endswith(".json"), self.JSON_ASSERTION + with open(load_path, "r") as fjson: + wrapped_results = json.load(fjson) + assert ( + "fit_src_dst_results" in wrapped_results + and "fit_dst_src_results" in wrapped_results + ), "Required keys fit_src_dst_results and fit_dst_src_results keys in the json not found" + self._fit_src_dst_results = wrapped_results["fit_src_dst_results"] + self._fit_dst_src_results = wrapped_results["fit_dst_src_results"] + + def save(self, path): + with open(path, 'wb') as file_handler: + pickle.dump(self, file_handler, protocol=pickle.HIGHEST_PROTOCOL) + + @classmethod + def load(cls, path): + with open(path, 'rb') as file_handler: + model = pickle.load(file_handler) + return model + + @staticmethod + def add_args(parser): + return parser diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/fitter.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/fitter.py new file mode 100644 index 000000000..530b8b612 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/fitter.py @@ -0,0 +1,275 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import warnings +from typing import Optional + +import numpy as np +from scipy.optimize import minimize + +from syngen.utils.types import NDArray +from syngen.generator.graph.utils import get_degree_distribution, move_ndarray_to_host +from syngen.utils.utils import infer_operator + +MAXK = 1000 + + +class RMATFitter(object): + def __init__(self, fast=True, random=False): + self._loglik = self._fast_loglik if fast else self._original_loglik + self.random = random + + def _get_p_directed_graph(self, dd, verbose=False): + num_nodes = dd[:, 1].sum() + n_exp2 = int(np.ceil(np.log2(num_nodes))) + E = (dd[:, 0] * dd[:, 1]).sum() + + mx = min(dd[-1, 0], MAXK) + + logeck = np.zeros(shape=(mx + 1), dtype=np.float64) + tmp = 0 + for k in range(1, mx + 1): + logeck[k] = tmp + np.log(E - k + 1) - np.log(k) + tmp = logeck[k] + + lognci = np.zeros(shape=(n_exp2 + 1), dtype=np.float64) + tmp = 0 + for i in range(1, n_exp2 + 1): + lognci[i] = tmp + np.log(n_exp2 - i + 1) - np.log(i) + tmp = lognci[i] + + x0 = np.array([0.5], dtype=np.float64) + + self.optimization_steps = [] + fun = lambda x: self._loglik(x, E, n_exp2, dd, logeck, lognci, MAXK) + + res = minimize( + fun, + x0, + method="Nelder-Mead", + bounds=[(1e-4, 1.0 - 1e-4)], + options={"disp": verbose, "fatol": 1e-4}, + ) + return res.x[0] + + def _original_loglik(self, p, E, n_exp, count, logeck, lognci, k_cost_threeshold): + if p <= 0.0 or p >= 1.0: + return 1e100 + + q = p + a = 0.75 * p + b = p - a + c = q - a + if (a + b + c) >= 1.0: + return 1e100 + + Sx = 0.0 + Sx2 = 0.0 + Sx3 = 0.0 + Sx4 = 0.0 + Sy = 0.0 + Sxy = 0.0 + Sx2y = 0.0 + + numX = count[-1, 0] + + totObs = 0.0 + prevY = 0.0 + + for m in range(1, numX + 1): + x = np.log(m) + if m <= MAXK: + current_sum = np.exp( + logeck[m] + + np.log(p) * (n_exp * m) + + np.log(1 - p ** n_exp) * (E - m) + ) + + for i in range(1, n_exp + 1): + current_sum = current_sum + np.exp( + logeck[m] + + lognci[i] + + np.log(p) * (m * (n_exp - i)) + + np.log(1.0 - p) * (m * i) + + np.log(1.0 - p ** (n_exp - i) * (1.0 - p) ** i) + * (E - m) + ) + else: + logecm = ( + E * np.log(E) - m * np.log(m) - (E - m) * np.log(E - m) + ) + current_sum = np.exp( + logecm + + np.log(p) * (n_exp * m) + + np.log(1 - p ** n_exp) * (E - m) + ) + for i in range(1, n_exp + 1): + current_sum = current_sum + np.exp( + logecm + + lognci[i] + + np.log(p) * (m * (n_exp - i)) + + np.log(1.0 - p) * (m * i) + + np.log(1.0 - p ** (n_exp - i) * (1.0 - p) ** i) + * (E - m) + ) + + y = np.log(current_sum) + y = max(0, y) + + interpY = y + + while interpY > 0 and (m == 1 or x > np.log(m - 1)): + Sx = Sx + x + Sx2 = Sx2 + x * x + Sx3 = Sx3 + x * x * x + Sx4 = Sx4 + x * x * x * x + Sy = Sy + interpY + Sxy = Sxy + x * interpY + Sx2y = Sx2y + x * x * interpY + + x = x - (np.log(numX) - np.log(numX - 1)) + + if prevY <= 0: + interpY = 0 + else: + interpY = interpY - (interpY - prevY) / ( + np.log(m) - np.log(m - 1) + ) * (np.log(numX) - np.log(numX - 1)) + + totObs = totObs + 1 + + prevY = y + + res = np.linalg.inv( + np.array([[totObs, Sx, Sx2], [Sx, Sx2, Sx3], [Sx2, Sx3, Sx4]]) + ) @ np.array([Sy, Sxy, Sx2y]) + + ParabolaA = res[0] + ParabolaB = res[1] + ParabolaC = res[2] + + l = np.array([0.0], dtype=np.float64) + + for m in range(1, len(count) + 1): + k = np.log(count[m - 1, 1]) + expectedLogY = ( + ParabolaA + + ParabolaB * np.log(count[m - 1, 0]) + + ParabolaC * np.log(count[m - 1, 0]) * np.log(count[m - 1, 0]) + ) + l = l + (k - expectedLogY) * (k - expectedLogY) + + self.optimization_steps.append((p[0], l[0])) + return l + + def _fast_loglik(self, p, E, n_exp, count, logeck, lognci, k_cost_threeshold): + + if p <= 0.0 or p >= 1.0: + return 1e100 + + q = p + a = 0.75 * p + b = p - a + c = q - a + if (a + b + c) >= 1.0: + return 1e100 + + l = np.array([0.0], dtype=np.float64) + for j in range(len(count)): + m = count[j, 0] + ck = np.log(count[j, 1]) + if ck > np.log(k_cost_threeshold): + if m <= MAXK: + current_sum = np.exp( + logeck[m] + + np.log(p) * (n_exp * m) + + np.log(1 - p ** n_exp) * (E - m) + ) + + for i in range(1, n_exp + 1): + current_sum = current_sum + np.exp( + logeck[m] + + lognci[i] + + np.log(p) * (m * (n_exp - i)) + + np.log(1 - p) * (m * i) + + np.log(1 - p ** (n_exp - i) * (1 - p) ** i) + * (E - m) + ) + else: + logecm = ( + E * np.log(E) - m * np.log(m) - (E - m) * np.log(E - m) + ) + current_sum = np.exp( + logecm + + np.log(p) * (n_exp * m) + + np.log(1 - p ** n_exp) * (E - m) + ) + for i in range(1, n_exp + 1): + current_sum = current_sum + np.exp( + logecm + + lognci[i] + + np.log(p) * (m * (n_exp - i)) + + np.log(1 - p) * (m * i) + + np.log(1 - p ** (n_exp - i) * (1 - p) ** i) + * (E - m) + ) + y = np.log(current_sum) + y = max(0, y) + l = l + (np.exp(ck) - np.exp(y)) * (np.exp(ck) - np.exp(y)) + self.optimization_steps.append((p[0], l[0])) + return l + + def _check_optimization_history(self): + optimization_steps = np.array(self.optimization_steps) + function_values = np.unique(optimization_steps[:, 1]) + if len(function_values) <= 1: + warnings.warn( + "the optimization function is constant for the RMATFitter(fast=True). " + "Please, use RMATFitter(fast=False) instead." + ) + self.optimization_steps = [] + + def fit(self, + graph: Optional[NDArray] = None, + is_directed=True, + ): + + if self.random: + return 0.25, 0.25, 0.25, 0.25 + + operator = infer_operator(graph) + + degree_values, degree_counts = get_degree_distribution(graph[:, 0], operator=operator) + out_dd = operator.stack([degree_values, degree_counts], axis=1) + out_dd = move_ndarray_to_host(out_dd) + + if is_directed: + degree_values, degree_counts = get_degree_distribution(graph[:, 1], operator=operator) + in_dd = operator.stack([degree_values, degree_counts], axis=1) + in_dd = move_ndarray_to_host(in_dd) + + p = self._get_p_directed_graph(out_dd) + self._check_optimization_history() + + if is_directed: + q = self._get_p_directed_graph(in_dd) + self._check_optimization_history() + else: + q = p + a = 0.75 * (p + q) / 2 + b = p - a + c = q - a + assert (a + b + c) < 1.0, "Cannot get correct RMat fit!" + d = 1.0 - (a + b + c) + return a, b, c, d diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/random.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/random.py new file mode 100644 index 000000000..8547f1f71 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/random.py @@ -0,0 +1,42 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import List, Optional, Set, Tuple + +from syngen.generator.graph.fitter import RMATFitter +from syngen.generator.graph.rmat import RMATGenerator + + +class RandomGraph(RMATGenerator): + """ Graph generator based on erdos-renyi model that generate random non-partite graphs + Args: + seed (int): + Seed to reproduce the results. If None then random seed will be used. + logdir (str): + Directory to store the logging results. + fitter (RMATFitter): + RMATFitter to be used. + """ + def __init__(self, seed: Optional[int] = None, logdir: str = "./logs", gpu: bool = True, **kwargs): + super().__init__(seed, logdir, gpu, fitter=RMATFitter(random=True)) + self.fit() + + def fit( + self, + graph: Optional[List[Tuple[int, int]]] = None, + is_directed: bool = None, + **kwargs, + ): + """ Fits generator on the graph. For random graph it's graph independent.""" + self._fit_results = self.fitter.fit(graph) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/random_bipartite.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/random_bipartite.py new file mode 100644 index 000000000..0f603fd31 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/random_bipartite.py @@ -0,0 +1,50 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Any, List, Optional, Set, Tuple + +from syngen.generator.graph.fitter import RMATFitter +from syngen.generator.graph.rmat_bipartite import RMATBipartiteGenerator + + +class RandomBipartite(RMATBipartiteGenerator): + """ Graph generator based on erdos-renyi model that generate random bipartite graphs + Args: + seed (int): + Seed to reproduce the results. If None then random seed will be used. + logdir (str): + Directory to store the logging results. + Defaults to ./logs. + fitter (RMATFitter): + RMATFitter to be used. + """ + + def __init__(self, seed: Optional[int] = None, logdir: str = "./logs", gpu: bool = True, **kwargs,): + super().__init__(seed, logdir, gpu, fitter=RMATFitter(random=True)) + self.fit() + + def fit( + self, + graph: Optional[List[Tuple[int, int]]] = None, + src_set: Optional[Set[int]] = None, + dst_set: Optional[Set[int]] = None, + is_directed: bool = False, + transform_graph: bool = True, + ): + """ Fits generator on the graph. For random graph it is graph independent.""" + + self._fit_src_dst_results = self.fitter.fit(graph) + self._fit_dst_src_results = ( + None if not is_directed else self.fitter.fit(graph) + ) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/rmat.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/rmat.py new file mode 100644 index 000000000..2ce1a41d9 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/rmat.py @@ -0,0 +1,240 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +from typing import List, Optional, Set, Tuple + +import numpy as np + +from syngen.generator.graph.fitter import RMATFitter +from syngen.generator.graph.base_graph_generator import BaseGraphGenerator +from syngen.generator.graph.utils import ( + effective_nonsquare_rmat_exact, + generate_gpu_rmat, + generate_gpu_chunked_rmat, +) + + +class RMATGenerator(BaseGraphGenerator): + """ Graph generator based on RMAT that generate non-partite graphs + Args: + seed (int): Seed to reproduce the results. If None then random seed will be used. + logdir (str): Directory to store the logging results. + fitter (RMATFitter): RMATFitter to be used. + """ + + def __init__( + self, + seed: Optional[int] = None, + logdir: str = "./logs", + gpu: bool = True, + fitter: Optional[RMATFitter] = None, + **kwargs, + ): + super().__init__(seed, logdir, gpu) + self.fitter = fitter or RMATFitter() + + def fit(self, *args, **kwargs): + """ Fits generator on the graph + Args: + + """ + self._fit_results = self.fitter.fit(*args, **kwargs) + self.logger.log(f"Fit results: {self._fit_results}") + + def _generate_part( + self, + fit_results: Tuple[float, float, float, float], + part_shape: Tuple[int, int], + num_edges: int, + has_self_loop: bool, + is_directed: bool, + noise: float, + batch_size: int, + return_node_ids: bool, + save_path: Optional[str], + ): + if self.gpu: + return self._generate_part_gpu( + fit_results=fit_results, + part_shape=part_shape, + num_edges=num_edges, + has_self_loop=has_self_loop, + is_directed=is_directed, + noise=noise, + return_node_ids=return_node_ids, + save_path=save_path, + ) + else: + return self._generate_part_cpu( + fit_results=fit_results, + part_shape=part_shape, + num_edges=num_edges, + has_self_loop=has_self_loop, + is_directed=is_directed, + noise=noise, + batch_size=batch_size, + return_node_ids=return_node_ids, + ) + + def _generate_part_cpu( + self, + fit_results: Tuple[float, float, float, float], + part_shape: Tuple[int, int], + num_edges: int, + has_self_loop: bool, + is_directed: bool, + noise: float, + batch_size: int, + return_node_ids: bool, + ): + + a, b, c, d = fit_results + theta = np.array([[a, b], [c, d]]) + theta /= a + b + c + d + + res = effective_nonsquare_rmat_exact( + theta, + num_edges, + part_shape, + noise_scaling=noise, + batch_size=batch_size, + dtype=np.int64, + custom_samplers=None, + generate_back_edges=not is_directed, + remove_selfloops=not has_self_loop, + return_node_ids=return_node_ids, + verbose=self.verbose, + ) + if return_node_ids: + return res[0], res[1] + return res[0] + + def _generate_part_gpu( + self, + fit_results: Tuple[float, float, float, float], + part_shape: Tuple[int, int], + num_edges: int, + has_self_loop: bool, + is_directed: bool, + noise: float, + return_node_ids: bool, + save_path: Optional[str], + _chunked: bool = True, + ): + + a, b, c, d = fit_results + theta = np.array([a, b, c, d]) + theta /= a + b + c + d + a, b, c, d = theta + + r_scale, c_scale = part_shape + + if _chunked: + res = generate_gpu_chunked_rmat( + a, + b, + c, + d, + r_scale=r_scale, + c_scale=c_scale, + n_edges=num_edges, + noise=noise, + is_directed=is_directed, + has_self_loop=has_self_loop, + return_node_ids=1 if return_node_ids else 0, + save_path=save_path, + verbose=self.verbose, + ) + else: + res = generate_gpu_rmat( + a, + b, + c, + d, + r_scale=r_scale, + c_scale=c_scale, + n_edges=num_edges, + noise=noise, + is_directed=is_directed, + has_self_loop=has_self_loop, + return_node_ids=1 if return_node_ids else 0, + ) + if return_node_ids: + return res[0], res[1] + return res + + def generate( + self, + num_nodes: int, + num_edges: int, + is_directed: bool, + has_self_loop: bool, + noise: float = 0.5, + batch_size: int = 1_000_000, + return_node_ids: bool = False, + save_path: Optional[str] = None, + *args, + **kwargs, + ): + """ Generates graph with approximately `num_nodes` nodes and exactly `num_edges` edges from generator + Args: + num_nodes (int): approximate number of nodes to be generated + num_edges(int): exact number of edges to be generated + is_directed (bool): flag indicating whether the generated graph has to be directed + has_self_loop (bool): flag indicating whether to generate self loops + noise (float): noise for RMAT generation to get better degree distribution + batch_size (int): size of the edge chunk that will be generated in one generation step (cpu parameter) + return_node_ids (bool): flag indicating whether the generator has to return nodes_ids as the second output + save_path (bool): path to store the graph. if specified the method return the number of edges in the graph + Returns: + new_graph (np.array[int, int]): generated graph + """ + assert num_nodes > 0, "Wrong number of nodes" + assert num_edges > 0, "Wrong number of edges" + + max_edges = ( + num_nodes * num_nodes + if has_self_loop + else num_nodes * (num_nodes - 1) + ) + if is_directed: + max_edges = max_edges / 2 + + assert ( + num_edges < max_edges + ), "Configuration of nodes and edges cannot form any graph" + + assert ( + self._fit_results + ), "There are no fit results, call fit method first or load the seeding matrix from the file" + + log2_nodes = math.ceil(math.log2(num_nodes)) + part_shape = (log2_nodes, log2_nodes) + + res = self._generate_part( + fit_results=self._fit_results, + part_shape=part_shape, + num_edges=num_edges, + has_self_loop=has_self_loop, + is_directed=is_directed, + noise=noise, + batch_size=batch_size, + return_node_ids=return_node_ids, + save_path=save_path, + ) + + if return_node_ids: + return res[0], res[1] + return res diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/rmat_bipartite.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/rmat_bipartite.py new file mode 100644 index 000000000..f17b45247 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/rmat_bipartite.py @@ -0,0 +1,333 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +import warnings +from typing import List, Optional, Set, Tuple + +import numpy as np + +from syngen.generator.graph.base_graph_generator import BaseBipartiteGraphGenerator +from syngen.generator.graph.fitter import RMATFitter +from syngen.generator.graph.utils import ( + effective_nonsquare_rmat_exact, + generate_gpu_rmat, + get_reversed_part, + rearrange_graph, + recreate_graph, generate_gpu_chunked_rmat, +) + + +class RMATBipartiteGenerator(BaseBipartiteGraphGenerator): + """ Graph generator based on RMAT that generate bipartite graphs + Args: + seed (int): Seed to reproduce the results. If None then random seed will be used. + logdir (str): Directory to store the logging results. + fitter (RMATFitter): RMATFitter to be used. + """ + + def __init__( + self, + seed: Optional[int] = None, + logdir: str = "./logs", + gpu: bool = True, + fitter: Optional[RMATFitter] = None, + **kwargs, + ): + super().__init__(seed, logdir, gpu) + self.fitter = fitter or RMATFitter() + + def fit( + self, + graph: List[Tuple[int, int]], + src_set: Optional[Set[int]], + dst_set: Optional[Set[int]], + is_directed: bool, + transform_graph: bool = True, + ): + """ Fits generator on the graph + Args: + graph (List[Tuple[int, int]]): graph to be fitted on + transform_graph (bool): defines if the generator should transform the input graph using src and dst node sets + src_set (Set[int]): set of source nodes + dst_set (Set[int]): set of destination nodes + is_directed (bool): flag indicating whether the graph is directed + + """ + assert graph is not None, "Wrong graph" + + if transform_graph: + lower, upper = rearrange_graph(graph, src_set, dst_set, assume_unique=True) + else: + assert not is_directed + upper = graph + lower = [] + + if ( + len(lower) and is_directed + ): # No need to fit lower part for undirected graph + self._fit_dst_src_results = self.fitter.fit(lower) + + if len(upper): + self._fit_src_dst_results = self.fitter.fit(upper) + + self.logger.log(f"Fit results dst_src: {self._fit_dst_src_results}") + self.logger.log(f"Fit results src_dst: {self._fit_src_dst_results}") + + def _generate_part( + self, + fit_results: Tuple[float, float, float, float], + part_shape: Tuple[int, int], + num_edges: int, + noise: float, + batch_size: int, + return_node_ids: bool, + save_path: Optional[str], + ): + if self.gpu: + return self._generate_part_gpu( + fit_results=fit_results, + part_shape=part_shape, + num_edges=num_edges, + noise=noise, + return_node_ids=return_node_ids, + save_path=save_path, + ) + else: + return self._generate_part_cpu( + fit_results=fit_results, + part_shape=part_shape, + num_edges=num_edges, + noise=noise, + batch_size=batch_size, + return_node_ids=return_node_ids, + ) + + def _generate_part_cpu( + self, + fit_results: Tuple[float, float, float, float], + part_shape: Tuple[int, int], + num_edges: int, + noise: float, + batch_size: int, + return_node_ids: bool, + ): + + a, b, c, d = fit_results + theta = np.array([[a, b], [c, d]]) + theta /= a + b + c + d + + res = effective_nonsquare_rmat_exact( + theta, + num_edges, + part_shape, + noise_scaling=noise, + batch_size=batch_size, + dtype=np.int64, + custom_samplers=None, + generate_back_edges=False, + remove_selfloops=False, + return_node_ids=2 if return_node_ids else 0, + verbose=self.verbose, + ) + if return_node_ids: + return res[0], res[1], res[2] + return res[0] + + def _generate_part_gpu( + self, + fit_results: Tuple[float, float, float, float], + part_shape: Tuple[int, int], + num_edges: int, + noise: float, + return_node_ids: bool, + save_path: Optional[str] = None, + _chunked: bool = True, + ): + + a, b, c, d = fit_results + theta = np.array([a, b, c, d]) + theta /= a + b + c + d + a, b, c, d = theta + r_scale, c_scale = part_shape + + if _chunked: + res = generate_gpu_chunked_rmat( + a, + b, + c, + d, + r_scale=r_scale, + c_scale=c_scale, + n_edges=num_edges, + noise=noise, + is_directed=True, + has_self_loop=True, + return_node_ids=2 if return_node_ids else 0, + save_path=save_path, + verbose=self.verbose, + ) + else: + res = generate_gpu_rmat( + a, + b, + c, + d, + r_scale=r_scale, + c_scale=c_scale, + n_edges=num_edges, + noise=noise, + is_directed=True, + has_self_loop=True, + return_node_ids=2 if return_node_ids else 0 + ) + if return_node_ids: + return res[0], res[1], res[2] + return res + + def generate( + self, + num_nodes_src_set: int, + num_nodes_dst_set: int, + num_edges_src_dst: int, + num_edges_dst_src: int, + is_directed: bool, + apply_edge_mirroring = True, + transform_graph: bool = True, + noise: float = 0.5, + batch_size: int = 1_000_000, + return_node_ids=False, + save_path: Optional[str] = None, + ): + """ Generates graph with approximately `num_nodes_src_set`/`num_nodes_dst_set` nodes + and exactly `num_edges_src_dst`/`num_edges_dst_src` edges from generator + Args: + num_nodes_src_set (int): approximate number of source nodes to be generated + num_nodes_dst_set (int): approximate number of destination nodes to be generated + num_edges_src_dst (int): exact number of source->destination edges to be generated + num_edges_dst_src (int): exact number of destination->source to be generated + is_directed (bool): flag indicating whether the generated graph has to be directed + transform_graph (bool): defines if the generator should transform the output graph to avoid node id conflict between src and dst nodes + noise (float): noise for RMAT generation to get better degree distribution + batch_size (int): size of the edge chunk that will be generated in one generation step + return_node_ids (bool): flag indicating whether the generator has to return nodes_ids as the second output + save_path (bool): path to store the graph. if specified the method return the number of edges in the graph + Returns: + new_graph (np.array[int, int]): generated graph + """ + assert ( + num_nodes_src_set > 0 and num_nodes_dst_set > 0 + ), "Wrong number of nodes" + + assert ( + num_edges_src_dst >= 0 and num_edges_dst_src >= 0 + ), "Wrong number of edges" + + max_edges = num_nodes_src_set * num_nodes_dst_set + + assert ( + num_edges_src_dst < max_edges and num_edges_dst_src < max_edges + ), "Configuration of nodes nad edges cannot form any graph" + + assert ( + self._fit_src_dst_results or self._fit_dst_src_results + ), "There are no fit results, \ + call fit method first or load the seeding matrix from the file" + + if (self._fit_dst_src_results is not None) != is_directed: + requested = "directed" if is_directed else "undirected" + fitted = "undirected" if requested == "directed" else "directed" + raise RuntimeError( + f"Fitted {fitted} graph but requested to generate {requested} one" + ) + + if apply_edge_mirroring and is_directed: + warnings.warn('edge mirroring works only for undirected graphs') + + if not is_directed: + assert ( + num_edges_src_dst == num_edges_dst_src + ), "For undirected graph expected the same number of edges for each side" + + assert ( + self._fit_dst_src_results is None + ), "For undirected graph expected only src->dst results to be present" + + log2_row = math.ceil(math.log2(num_nodes_src_set)) + log2_col = math.ceil(math.log2(num_nodes_dst_set)) + part_shape_upper = (log2_row, log2_col) + part_shape_lower = (log2_col, log2_row) + + offset = int(2 ** log2_row) + + if self._fit_src_dst_results and num_edges_src_dst: + upper_part_res = self._generate_part( + self._fit_src_dst_results, + part_shape_upper, + num_edges_src_dst, + noise, + batch_size, + return_node_ids=return_node_ids, + save_path=save_path, + ) + if return_node_ids: + upper_part, upper_part_src_node_ids, upper_part_dst_node_ids = upper_part_res + else: + upper_part = upper_part_res + else: + upper_part = [] + + if self._fit_dst_src_results: + if save_path is not None: + raise NotImplementedError('save_path works only for undirected bipartite graphs') + if num_edges_dst_src: + lower_part_res = self._generate_part( + self._fit_dst_src_results, + part_shape_lower, + num_edges_dst_src, + noise, + batch_size, + save_path=save_path, + return_node_ids=return_node_ids, + ) + if return_node_ids: + lower_part, lower_part_src_node_ids, lower_part_dst_node_ids = lower_part_res + else: + lower_part = lower_part_res + else: + lower_part = [] + elif not is_directed and apply_edge_mirroring: # Recreate lower part for undirected graph + if return_node_ids: + lower_part_src_node_ids, lower_part_dst_node_ids = upper_part_dst_node_ids, upper_part_src_node_ids + lower_part = get_reversed_part(upper_part) + else: + lower_part = [] + + if transform_graph: + new_graph = recreate_graph(lower_part, upper_part, offset) + if return_node_ids: + lower_part_src_node_ids = lower_part_src_node_ids + offset + upper_part_dst_node_ids = upper_part_dst_node_ids + offset + src_node_ids = np.union1d(upper_part_src_node_ids, lower_part_dst_node_ids) + dst_node_ids = np.union1d(upper_part_dst_node_ids, lower_part_src_node_ids) + else: + if apply_edge_mirroring: + raise NotImplementedError('apply edge mirroring works only with `transform_graph=True`') + new_graph = upper_part + if return_node_ids: + src_node_ids, dst_node_ids = upper_part_src_node_ids, upper_part_dst_node_ids + + if return_node_ids: + return new_graph, src_node_ids, dst_node_ids + return new_graph diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/seeder.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/seeder.py new file mode 100644 index 000000000..a7031e2e8 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/seeder.py @@ -0,0 +1,41 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Optional + +import cupy as cp +import numpy as np + + +class BaseSeeder: + """ Base seeder + Args: + seed (int): optional global seed + """ + + def __init__(self, seed: Optional[int] = None): + self.seed = seed + + @property + def seed(self): + return self._seed + + @seed.setter + def seed(self, value): + self._seed = value if value is not None else np.random.randint(0, 100) + + def reseed(self): + """Sets the seed for the project""" + np.random.seed(self.seed) + cp.random.seed(self.seed) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/utils.py new file mode 100644 index 000000000..73a90b1b8 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/graph/utils.py @@ -0,0 +1,1060 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import logging +import math +import multiprocessing +from datetime import datetime +from functools import partial +from typing import Tuple, Union, Optional + +import cupy as cp +import matplotlib.pyplot as plt +import numpy as np +from tqdm import tqdm +from pylibraft.random import rmat +from scipy import stats + +from syngen.utils import NDArray, infer_operator +from syngen.utils.utils import infer_operator +from syngen.utils.io_utils import dump_generated_graph +from syngen.utils.memory_manager import MemoryManager +from syngen.utils.types import NDArray + +logger = logging.getLogger(__name__) + + +def move_ndarray_to_host(ndarray: NDArray): + if isinstance(ndarray, np.ndarray): + return ndarray + elif isinstance(ndarray, cp.ndarray): + return cp.asnumpy(ndarray) + else: + raise ValueError('supports only numpy and cupy ndarrays') + + +def rearrange_graph( + edge_list: NDArray, + src_nodes: NDArray, + dst_nodes: NDArray, + assume_unique: bool = False, +) -> Tuple[NDArray, NDArray]: + """ + Transforms a bipartite graph from edge list format to lower_left and upper_right adjacency matrices. + + Returned matrices are in coordinate list format. + + """ + operator = infer_operator(edge_list) + + if not isinstance(src_nodes, (np.ndarray, cp.ndarray)): + raise ValueError('src_nodes: expected type NDArray, but %s was passed', type(src_nodes)) + if not isinstance(dst_nodes, (np.ndarray, cp.ndarray)): + raise ValueError('dst_nodes: expected type NDArray, but %s was passed', type(dst_nodes)) + + if not assume_unique: + src_nodes = operator.unique(src_nodes) + dst_nodes = operator.unique(dst_nodes) + + if operator.intersect1d(src_nodes, dst_nodes, assume_unique=True).size != 0: + raise ValueError('node sets cannot intersect') + + edge_list = edge_list.flatten() + + node_set = operator.hstack([src_nodes, dst_nodes]) + pos_to_new_id = operator.argsort(node_set) + sorted_node_set = node_set[pos_to_new_id] + + pos_in_sorted_nodeset = operator.searchsorted(sorted_node_set, edge_list) + + # need to validate since errors could be ignored + # https://docs.cupy.dev/en/stable/user_guide/difference.html#out-of-bounds-indices + message = 'all ids in a graph should be in one of the node sets' + if operator.any(pos_in_sorted_nodeset == len(sorted_node_set)): + raise ValueError(message) + if operator.any(sorted_node_set[pos_in_sorted_nodeset] != edge_list): + raise ValueError(message) + + edge_list_mapped = pos_to_new_id[pos_in_sorted_nodeset].reshape(-1, 2) + + upper_right = edge_list_mapped[edge_list_mapped[:, 0] < len(src_nodes)] + upper_right[:, 1] -= len(src_nodes) + + lower_left = edge_list_mapped[edge_list_mapped[:, 0] >= len(src_nodes)] + lower_left[:, 0] -= len(src_nodes) + + return lower_left, upper_right + + +def reindex_graph( + edge_list: NDArray, + return_counts: bool = False, +) -> Union[NDArray, Tuple[NDArray, int, int]]: + """ + Reindexes a graph by assigning node ids starting from 0. + + Returns the processed graph and, optionally, number of nodes and number of edges. + + """ + operator = infer_operator(edge_list) + + nodes, inverse_flat = operator.unique(edge_list, return_inverse=True) + edge_list_reindexed = inverse_flat.reshape(edge_list.shape) + + if return_counts: + return edge_list_reindexed, len(nodes), len(edge_list) + else: + return edge_list_reindexed + + +def get_reversed_part(part, gpu=False, operator=None): + operator = operator or (cp if gpu else np) + new_part = operator.empty_like(part) + new_part[:, 0] = part[:, 1] + new_part[:, 1] = part[:, 0] + return new_part + + +# Postprocessing +def recreate_graph(lower: NDArray, upper: NDArray, offset: int, gpu=False): + assert ( + lower is not None and upper is not None + ), "Upper and lower cannot be None" + operator = cp if gpu else np + lower[:, 0] = lower[:, 0] + offset + upper[:, 1] = upper[:, 1] + offset + new_graph = operator.concatenate((lower, upper), axis=0) + + return new_graph + + +def recreate_bipartite_nondirected(graph, row_shape): + upper = [(row, col + row_shape) for row, col in graph] + lower = [(col, row) for row, col in upper] + new_graph = upper + lower + return new_graph + + +def to_adj_matrix(graph, shape): + matrix = np.zeros(shape=shape, dtype=np.bool) + arr_indicies = np.array(graph) + matrix[arr_indicies[:, 0], arr_indicies[:, 1]] = 1 + return matrix + + +def plot_graph_adj(graph, shape): + graph_adj = to_adj_matrix(graph, shape=shape) + return plt.imshow(graph_adj, cmap="binary", interpolation="nearest") + + +def graph_to_snap_file(A, filename): + np.savetxt(filename, A, fmt="%i", delimiter="\t") + + +def effective_nonsquare_rmat_approximate( + theta, + E, + A_shape, + noise_scaling=1.0, + batch_size=1000, + dtype=np.int64, + custom_samplers=None, + generate_back_edges=False, + verbose=False, +): + """ This function generates list of edges using modified RMat approach + Args: + theta (np.array): seeding matrix, needs to be shape 2x2 + E (int): number of edges to be generated + A_shape (tuple): shape of resulting adjacency matrix. numbers has to be powers of 2 + A_shape should be equal to (ceil(log2(X)),ceil(log2(Y))) X,Y are + dimensions of original adjacency + noise_scaling (float 0..1): noise scaling factor for good degree distribution + batch_size (int): edges are generated in batches of batch_size size + dtype (numpy dtype np.int32/np.int64): dtype of nodes id's + custom_samplers (List[scipy.stats.rv_discrete]): samplers for each step of genration + process + generate_back_edges (bool): if True then generated edges will also have "back" edges. Not + that setting to True for partite graphs makes no sense. + Returns: + A (np.array 2 x E): matrix containing in every row a signle edge. Edge is always directed + 0'th column is FROM edge 1st is TO edge + mtx_shape (tuple) - shape of adjecency matrix (A contains list of edges, this is Adjecency + metrix shape) + custom_samplers (List[scipy.stats.rv_discrete]) - list of samplers needed to generate edges + from the same disctribution for multiple runs of the function + Description: + The generation will consist of theta^[n] (x) theta_p^[m] (x) theta_q^[l] + ^[n] is kronecker power + (x) is matrix kronecker product + theta_p (2x1) and theta_q(1x2) are marginals of theta + + This way we can generate rectangular shape of adjecency matrix e.g. for bipatrite + graphs + """ + + def get_row_col_addres(thetas_n): + thetas_r = [t.shape[0] for t in thetas_n] + thetas_c = [t.shape[1] for t in thetas_n] + row_n = np.prod(thetas_r) # theta_r**quadrant_sequence.shape[1] + col_n = np.prod(thetas_c) # theta_c**quadrant_sequence.shape[1] + row_adders = np.array( + [ + int(row_n / thetas_r[i] ** (i + 1)) % row_n + for i in range(len(thetas_n)) + ] + ) # there has to be % as we can have thetas_r[i]==1 + col_adders = np.array( + [ + int(col_n / thetas_c[i] ** (i + 1)) % col_n + for i in range(len(thetas_n)) + ] + ) + return row_adders, col_adders, thetas_r, thetas_c, row_n, col_n + + def parse_quadrants( + quadrant_sequence, + thetas_n, + row_adders, + col_addres, + thetas_r, + thetas_c, + row_n, + col_n, + dtype=np.int64, + ): + N = len(thetas_n) + new_edges = np.zeros( + shape=(quadrant_sequence.shape[0], 2) + ) # 2 because 0 col=rows_addresses, 1st col = columns + row_addr = np.array(quadrant_sequence // thetas_c, dtype=dtype) + col_addr = np.array(quadrant_sequence % thetas_c, dtype=dtype) + row_adders = np.array( + [int(row_n / thetas_r[i] ** (i + 1)) % row_n for i in range(N)] + ) # there has to be % as we can have thetas_r[i]==1 + col_adders = np.array( + [int(col_n / thetas_c[i] ** (i + 1)) % col_n for i in range(N)] + ) + new_edges[:, 0] = np.sum(np.multiply(row_addr, row_adders), axis=1) + new_edges[:, 1] = np.sum(np.multiply(col_addr, col_adders), axis=1) + return new_edges + + if batch_size > E: # if bs>E + batch_size = int(E // 2 * 2) + if generate_back_edges: + assert ( + batch_size % 2 == 0 and batch_size >= 2 + ), "batch size has to be odd and >1" + assert ( + np.abs((np.sum(theta) - 1.0)) < 1e-6 + ), "Theta probabilities has to sum to 1.0" + assert (theta.shape[0] == 2) and ( + theta.shape[1] == 2 + ), "Only 2x2 seeding matrixes are acceptable" + assert len(A_shape) == 2, "A_shape needs to be of len 2" + + # get appropriate number of n,m,l always m=0 or l=0 (or both for rectangular adjecency) + r = A_shape[0] + c = A_shape[1] + n = min(r, c) # theta^[n] (x) theta_p^[m] (x) theta_q^[l] + m = max(0, r - c) + # flake8: noqa + l = max(0, c - r) + # calc values of marginal theta matrixes + theta_p = theta.sum(axis=1).reshape((2, -1)) # 2x1 + theta_q = theta.sum(axis=0).reshape((1, -1)) # 1x2 + # get all thetas + thetas_n = [theta] * n + [theta_p] * m + [theta_q] * l + # prepare samplers for each of n+m+l steps + if custom_samplers is None: + custom_samplers = [] + for i in range(n + m + l): + theta_n = thetas_n[ + i + ] # each of n+m+l steps have their own theta_n which can be theta/theta_p or theta_q + + # noise + noise = noise_scaling * np.random.uniform( + -1, 1, size=theta_n.shape + ) + noise_to_add = np.multiply(theta_n, noise) + theta_n = theta_n + noise_to_add + theta_n = theta_n / np.sum(theta_n) + cstm_n = "step_" + str(i) + theta_r = theta_n.shape[0] + theta_c = theta_n.shape[1] + xk = tuple(range(theta_r * theta_c)) + pk = theta_n.reshape(-1) + cstm_s = stats.rv_discrete(name=cstm_n, values=(xk, pk)) + custom_samplers.append(cstm_s) + # Prepare all batch sizes needed for generation + if batch_size == 0: + batch_count = 0 # XXX: why does this happen anyways? + else: + batch_count = E // batch_size + last_batch_size = E - batch_count * batch_size + if last_batch_size % 2 > 0 and generate_back_edges: + last_batch_size -= 1 + A = np.zeros((E, 2), dtype=np.int64) + num_sequences = batch_size + last_num_sequences = last_batch_size + if ( + generate_back_edges + ): # in case of generating back edges we need to sample just E/2 + last_num_sequences = last_batch_size // 2 + num_sequences = batch_size // 2 + new_back_edges = np.zeros(shape=(num_sequences, 2)) + quadrant_sequence = np.zeros(shape=(num_sequences, n + m + l), dtype=dtype) + ( + row_adders, + col_addres, + thetas_r, + thetas_c, + row_n, + col_n, + ) = get_row_col_addres(thetas_n) + # generate sequences of quadrants from previously prepared samplers + + batch_itr = range(batch_count) + if verbose: + batch_itr = tqdm(batch_itr) + + for e in batch_itr: + for i in range( + n + m + l + ): # each steps in generation has its own sampler + smpl = custom_samplers[i].rvs(size=num_sequences) + quadrant_sequence[:, i] = smpl + # produce new edges + new_edges = parse_quadrants( + quadrant_sequence, + thetas_n, + row_adders, + col_addres, + thetas_r, + thetas_c, + row_n, + col_n, + dtype=dtype, + ) + if generate_back_edges: + new_back_edges[:, [0, 1]] = new_edges[:, [1, 0]] # swap columns + A[ + e * batch_size: (e + 1) * batch_size: 2, : + ] = new_edges # we need interleave so that back edges are "right after" normal edges + A[ + e * batch_size + 1: (e + 1) * batch_size: 2, : + ] = new_back_edges + else: + A[e * batch_size: (e + 1) * batch_size, :] = new_edges + + # generate last batch + if last_batch_size > 0: + for i in range(n + m + l): + smpl = custom_samplers[i].rvs(size=last_num_sequences) + quadrant_sequence[:last_num_sequences, i] = smpl + new_edges = parse_quadrants( + quadrant_sequence[:last_num_sequences, :], + thetas_n, + row_adders, + col_addres, + thetas_r, + thetas_c, + row_n, + col_n, + dtype=dtype, + ) + if generate_back_edges: + new_back_edges[:last_num_sequences, [0, 1]] = new_edges[ + :last_num_sequences, [1, 0] + ] + # we need interleave so that back edges are "right after" normal edges + A[ + batch_count * batch_size: batch_count * batch_size + + last_batch_size: 2, + :, + ] = new_edges + # np.concatenate((new_edges,new_back_edges[:last_num_sequences,:]),axis=0) + A[ + batch_count * batch_size + + 1: batch_count * batch_size + + last_batch_size: 2, + :, + ] = new_back_edges[:last_num_sequences, :] + else: + A[ + batch_count * batch_size: batch_count * batch_size + + last_batch_size, + :, + ] = new_edges + mtx_shape = ( + np.prod([t.shape[0] for t in thetas_n]), + np.prod([t.shape[1] for t in thetas_n]), + ) # shape of resulting adjacency matrix + return A, mtx_shape, custom_samplers + + +def effective_nonsquare_rmat_exact( + theta, + E, + A_shape, + noise_scaling=1.0, + batch_size=1000, + dtype=np.int64, + custom_samplers=None, + remove_selfloops=False, + generate_back_edges=False, + return_node_ids=0, + verbose=False, +): + """ This function generates list of edges using modified RMat approach based on effective_nonsuqare_rmat_approximate + Args: + theta (np.array): seeding matrix, needs to be shape 2x2 + E (int): number of edges to be generated + A_shape (tuple): shape of resulting adjacency matrix. numbers has to be powers of 2 + A_shape should be equal to (ceil(log2(X)),ceil(log2(Y))) X,Y are + dimensions of original adjacency + noise_scaling (float 0..1): noise scaling factor for good degree distribution + batch_size (int): edges are generated in batches of batch_size size + dtype (numpy dtype np.int32/np.int64): dtype of nodes id's + remove_selfloops (bool): If true edges n->n will not be generated. Note that for partite + graphs this makes no sense + generate_back_edges (bool): if True then generated edges will also have "back" edges. Not + that setting to True for partite graphs makes no sense. + Returns: + A (np.array 2 x E) - matrix containing in every row a signle edge. Edge is always directed + 0'th column is FROM edge 1st is TO edge + mtx_shape (tuple) - shape of adjecency matrix (A contains list of edges, this is Adjecency + metrix shape) + custom_samplers (List[scipy.stats.rv_discrete]) - list of samplers needed to generate edges + from the same disctribution for multiple runs of the function + Description: + see effective_nonsuqare_rmat_approximate + """ + heuristics = 1.5 + if verbose: + print("Getting egdes") + A, mtx_shape, cs = effective_nonsquare_rmat_approximate( + theta, + int(heuristics * E), + A_shape, + noise_scaling=noise_scaling, + batch_size=batch_size, + dtype=dtype, + custom_samplers=custom_samplers, + generate_back_edges=generate_back_edges, + verbose=verbose, + ) + if generate_back_edges: + A = A[ + np.sort(np.unique(A, return_index=True, axis=0)[1]) + ] # permutation is not needed here + else: + if verbose: + print("Getting unique egdes") + A = np.unique(A, axis=0) + if verbose: + print("Permuting edges") + perm = np.random.permutation( + A.shape[0] + ) # we need to permute it as othervise unique returns edges in order + A = A[perm] + if remove_selfloops: + if verbose: + print("Removing selfloops") + A = np.delete(A, np.where(A[:, 0] == A[:, 1]), axis=0) + E_already_generated = A.shape[0] + if E_already_generated >= E: + if return_node_ids == 2: + return A[:E, :], np.unique(A[:E, :][:, 0]), np.unique(A[:E, :][:, 1]), mtx_shape, cs + if return_node_ids == 1: + return A[:E, :], np.unique(A[:E, :]), mtx_shape, cs + return A[:E, :], mtx_shape, cs + else: + while E_already_generated < E: + if verbose: + print("Generating some additional edges") + E_to_generate = int(heuristics * (E - E_already_generated)) + A_next, mtx_shape, cs = effective_nonsquare_rmat_approximate( + theta, + E_to_generate, + A_shape, + noise_scaling=noise_scaling, + batch_size=batch_size, + dtype=dtype, + custom_samplers=cs, + verbose=verbose, + ) + if remove_selfloops: + A_next = np.delete( + A_next, np.where(A_next[:, 0] == A_next[:, 1]), axis=0 + ) + A = np.concatenate((A, A_next), axis=0) + if generate_back_edges: + A = A[np.sort(np.unique(A, return_index=True, axis=0)[1])] + else: + A = np.unique(A, axis=0) + perm = np.random.permutation(A.shape[0]) + A = A[perm] + E_already_generated = A.shape[0] + + if return_node_ids == 2: + return A[:E, :], np.unique(A[:E, :][:, 0]), np.unique(A[:E, :][:, 1]), mtx_shape, cs + if return_node_ids == 1: + return A[:E, :], np.unique(A[:E, :]), mtx_shape, cs + return A[:E, :], mtx_shape, cs + + +def cupy_unique_axis0(array): + # https://stackoverflow.com/questions/58662085/is-there-a-cupy-version-supporting-axis-option-in-cupy-unique-function-any + sortarr = array[cp.lexsort(array.T[::-1])] + mask = cp.empty(array.shape[0], dtype=cp.bool_) + mask[0] = True + mask[1:] = cp.any(sortarr[1:] != sortarr[:-1], axis=1) + return sortarr[mask] + + +def unique_axis0(ar: NDArray) -> NDArray: + """ + Uniform way of calling operator.unique(ar, axis=0). + + axis != None is not supported in cupy yet. + This function provides a workaround for one of the cases. + + """ + operator = infer_operator(ar) + + if operator == cp: + return cupy_unique_axis0(ar) + else: + return np.unique(ar, axis=0) + + +def generate_gpu_rmat( + a, + b, + c, + d, + r_scale, + c_scale, + n_edges, + noise=0.5, + is_directed=False, + has_self_loop=False, + return_node_ids=0, +): + if not is_directed and r_scale != c_scale: + raise ValueError('undirected generation works only for square adj matrix') + + if not is_directed: + n_edges = n_edges // 2 + gen_graph = None + HEURISTIC = 1.2 + edges_to_generate = int(HEURISTIC * n_edges) + theta_len = max(r_scale, c_scale) + + base_theta = [a, b, c, d] + if noise > 0: + full_theta = [] + for i in range(theta_len): + noise_uniform = noise * np.random.uniform( + -1, 1, size=len(base_theta) + ) + noise_to_add = np.multiply(base_theta, noise_uniform) + theta_n = base_theta + noise_to_add + theta_n = theta_n / np.sum(theta_n) + full_theta.append(theta_n) + else: + full_theta = base_theta * theta_len + + theta_cpu = np.array(full_theta, dtype=np.float32) + theta = cp.asarray(theta_cpu) + + while gen_graph is None or gen_graph.shape[0] < n_edges: + tmp = cp.empty((edges_to_generate, 2), dtype=cp.int32) + seed = cp.random.randint(0, high=1_000_000, size=None, dtype=int) + rmat(tmp, theta, r_scale, c_scale, seed=seed) + + # Remove self loops + if not has_self_loop: + tmp = tmp[tmp[:, 0] != tmp[:, 1]] + + # Keep only one sided edges + if not is_directed: + tmp = tmp[tmp[:, 0] <= tmp[:, 1]] + + if gen_graph is None: + # Remove duplicates + gen_graph = cupy_unique_axis0(tmp) + else: + gen_graph = cp.concatenate((gen_graph, tmp), axis=0) + # Remove duplicates + gen_graph = cupy_unique_axis0(gen_graph) + + gen_graph = gen_graph[:n_edges] + if not is_directed: + gen_graph_backward = cp.empty((n_edges, 2), dtype=cp.int32) + gen_graph_backward[:, 0] = gen_graph[:, 1] + gen_graph_backward[:, 1] = gen_graph[:, 0] + gen_graph = cp.concatenate((gen_graph, gen_graph_backward), axis=0) + + gen_graph = cupy_unique_axis0( + gen_graph + ) + + if not has_self_loop: + gen_graph = gen_graph[gen_graph[:, 0] != gen_graph[:, 1]] + + if return_node_ids == 2: + return cp.asnumpy(gen_graph), cp.asnumpy(cp.unique(gen_graph[:, 0])), cp.asnumpy(cp.unique(gen_graph[:, 1])) + if return_node_ids == 1: + return cp.asnumpy(gen_graph), cp.asnumpy(cp.unique(gen_graph)) + return cp.asnumpy(gen_graph) + + +def generate_theta(base_theta, noise, theta_len, is_directed): + if noise > 0: + full_theta = [] + for i in range(theta_len): + noise_uniform = noise * np.random.uniform( + -1, 1, size=len(base_theta) + ) + noise_to_add = np.multiply(base_theta, noise_uniform) + theta_n = base_theta + noise_to_add + if not is_directed: + theta_n[2] = theta_n[1] + theta_n = theta_n / np.sum(theta_n) + full_theta.append(theta_n) + else: + full_theta = [base_theta] * theta_len + return full_theta + + +def prepare_chunks(full_theta, r_scale, c_scale, gpu_bytes_to_use, edges_to_generate): + if r_scale > 32 or c_scale > 32: + bytes_per_edge = 8 + max_id = 9223372036854775807 # int64 max + else: + bytes_per_edge = 4 + max_id = 2147483647 # int32 max + bytes_to_generate = edges_to_generate * 2 * bytes_per_edge + skip_theta = 0 + + # approximation + while (bytes_to_generate >> 2 * skip_theta) > gpu_bytes_to_use \ + or (bytes_to_generate >> 2 * skip_theta) > max_id: + skip_theta += 1 + + if skip_theta == 0: + return [], np.array([edges_to_generate]), full_theta, 0, r_scale, c_scale + + # chunk size is limited by the smaller side of the rectangular graph + while abs(r_scale - c_scale) > skip_theta: + skip_theta += 1 + + def repeat(a, scale): + if scale == 1: + return a + return np.repeat(np.repeat(a, scale, axis=0), scale, axis=1) + + def tile(a, scale): + if scale == 1: + return a + return np.tile(a, (scale, scale)) + + def prepare_prefixes(skip_theta): + if skip_theta > 0: + prefix_theta = full_theta[:skip_theta] + gen_theta_len = max(r_scale, c_scale) - skip_theta + prefix_edges = np.ones((1 << skip_theta, 1 << skip_theta), dtype=np.float64) + prefixes = np.zeros((2, 1 << skip_theta, 1 << skip_theta), dtype=np.int32) + + for theta_idx, theta in enumerate(prefix_theta): + pref_src = np.array([[0, 0], [1, 1]]) << theta_idx + pref_dst = np.array([[0, 1], [0, 1]]) << theta_idx + + theta = np.array(theta, dtype=np.float64).reshape(2, 2) + repeat_scale = 1 << (skip_theta - theta_idx - 1) + tile_scale = 1 << theta_idx + prefix_edges = prefix_edges * tile(repeat(theta, repeat_scale), tile_scale) + + prefixes[0] = prefixes[0] + tile(repeat(pref_src, repeat_scale), tile_scale) + prefixes[1] = prefixes[1] + tile(repeat(pref_dst, repeat_scale), tile_scale) + + if r_scale != c_scale: # probabilities in the rectangular matrix should sum up to 1.0 + r_len = 2 ** (r_scale - gen_theta_len) + c_len = 2 ** (c_scale - gen_theta_len) + prefix_edges[:r_len, :c_len] = prefix_edges[:r_len, :c_len] / prefix_edges[:r_len, :c_len].sum() + + prefixes[int(r_scale > c_scale), :r_len, :c_len] = \ + prefixes[int(r_scale > c_scale), :r_len, :c_len] >> abs(r_scale - c_scale) + + prefix_edges = np.ceil(prefix_edges * edges_to_generate).astype(np.int32).reshape(-1) + prefixes = prefixes.reshape(2, -1) + else: + prefixes = [] + prefix_edges = np.array([edges_to_generate]) + return prefixes, prefix_edges + + prefixes, prefix_edges = prepare_prefixes(skip_theta) + + while prefix_edges.max() * 2 * bytes_per_edge > gpu_bytes_to_use: + skip_theta += 1 + prefixes, prefix_edges = prepare_prefixes(skip_theta) + + generation_theta = full_theta[skip_theta:] + + return prefixes, prefix_edges, generation_theta, skip_theta, len(generation_theta), len(generation_theta) + + +def _generate_gpu_chunk_rmat( + chunk_info, + prefixes, + prefix_edges, + has_self_loop, + is_directed, + generation_theta, + r_log2_nodes, + c_log2_nodes, + r_pref_len, + c_pref_len, + row_len, + gpus, + dtype='int32', + return_node_ids=0, + memmap_kwargs: Optional = None, + chunk_save_path_format: Optional[str] = None): + + chunk_id, chunk_end = chunk_info + chunk_size = prefix_edges[chunk_id] + + if gpus > 1: + gpu_id = int(multiprocessing.current_process()._identity[0]) % gpus + else: + gpu_id = 0 + theta_cpu = np.array(generation_theta, dtype=np.float32) + edge_list = None + + is_diagonal_chunk = ((chunk_id // row_len) == (chunk_id % row_len)) + + use_memmap = memmap_kwargs is not None + if use_memmap: + memmap_outfile = np.load(file=memmap_kwargs['filename'], mmap_mode='r+') + + with cp.cuda.Device(gpu_id): + theta = cp.asarray(theta_cpu) + while edge_list is None or edge_list.shape[0] < prefix_edges[chunk_id]: + tmp = cp.empty((prefix_edges[chunk_id], 2), dtype=dtype) + seed = cp.random.randint(0, high=1_000_000, size=None, dtype=int) + rmat(tmp, theta, r_log2_nodes, c_log2_nodes, seed=seed) + + if not has_self_loop and is_diagonal_chunk: + tmp = tmp[tmp[:, 0] != tmp[:, 1]] + + # undirected diagonal_case + if not is_directed and is_diagonal_chunk: + tmp = tmp[tmp[:, 0] <= tmp[:, 1]] + tmp = cupy_unique_axis0(tmp) + + if edge_list is None: + edge_list = tmp + else: + edge_list = cp.concatenate((edge_list, tmp), axis=0) + del tmp + edge_list = cupy_unique_axis0(edge_list) + + if len(prefix_edges) > 1: + edge_list[:, 0] = (edge_list[:, 0] << r_pref_len) + prefixes[0][chunk_id] + edge_list[:, 1] = (edge_list[:, 1] << c_pref_len) + prefixes[1][chunk_id] + + edge_list = edge_list[:prefix_edges[chunk_id]] + if return_node_ids == 2: + src_nodes_ids = cp.asnumpy(cp.unique(edge_list[:, 0])) + dst_nodes_ids = cp.asnumpy(cp.unique(edge_list[:, 1])) + if return_node_ids == 1: + nodes_ids = cp.asnumpy(cp.unique(edge_list)) + result = cp.asnumpy(edge_list) + + if use_memmap: + memmap_outfile[chunk_end-chunk_size:chunk_end] = result + + del edge_list + + if chunk_save_path_format is not None: + dump_generated_graph(chunk_save_path_format.format(chunk_id=chunk_id), result) + result = len(result) + + if use_memmap: + result = None + + if return_node_ids == 2: + return result, src_nodes_ids, dst_nodes_ids + if return_node_ids == 1: + return result, nodes_ids + return result + + +def generate_gpu_chunked_rmat( + a, + b, + c, + d, + r_scale, + c_scale, + n_edges, + noise=0.5, + is_directed=False, + has_self_loop=False, + gpus=None, + return_node_ids=0, + save_path: Optional[str] = None, + verbose: bool = False, +): + if not is_directed and r_scale != c_scale: + raise ValueError('undirected generation works only for square adj matrix') + + base_theta = [a, b, c, d] + + theta_len = max(r_scale, c_scale) + + full_theta = generate_theta(base_theta, noise, theta_len, is_directed) + if gpus is None: + gpus = MemoryManager().get_available_gpus() + gpu_bytes_to_use = MemoryManager().get_min_available_across_gpus_memory(gpus=gpus) + + gpu_bytes_to_use = math.floor(gpu_bytes_to_use * 0.10) + prefixes, prefix_edges, generation_theta, prefix_len, r_log2_nodes, c_log2_nodes = \ + prepare_chunks(full_theta, r_scale, c_scale, gpu_bytes_to_use, n_edges) + + chunk_ids = list(range(len(prefix_edges))) + + row_len = 1 << prefix_len + r_pref_len = r_scale - len(generation_theta) + c_pref_len = c_scale - len(generation_theta) + + if not is_directed: # generate a triangular adj matrix + chunk_ids = [i for i in chunk_ids if (i // row_len) <= (i % row_len)] + # reduce the diagonal chunks + for i in range(prefix_len * 2): + prefix_edges[i * row_len + i] = prefix_edges[i * row_len + i] // 2 + + if r_scale != c_scale: + chunk_ids = [i for i in chunk_ids if (i // row_len) < 2 ** r_pref_len and (i % row_len) < 2 ** c_pref_len] + + is_single_chunk = len(chunk_ids) == 1 + + memmap_kwargs = None + chunk_save_path_format = None + use_memmap = False + + if save_path and os.path.isdir(save_path): + chunk_save_path_format = os.path.join(save_path, 'chunk_{chunk_id}.npy') + elif save_path and save_path.endswith('.npy'): + use_memmap = True + memmap_shape = (sum(prefix_edges[chunk_ids]), 2) + memmap_dtype = np.uint64 if theta_len > 32 else np.uint32 + memmap_kwargs = dict( + filename=save_path, + ) + memmap_outfile = np.lib.format.open_memmap(save_path, dtype=memmap_dtype, shape=memmap_shape, mode='w+') + + dtype = cp.int64 if theta_len > 32 else cp.int32 + + _generate_gpu_chunk_rmat_p = partial( + _generate_gpu_chunk_rmat, + prefixes=prefixes, + prefix_edges=prefix_edges, + has_self_loop=has_self_loop, + is_directed=is_directed, + generation_theta=generation_theta, + r_log2_nodes=r_log2_nodes, + c_log2_nodes=c_log2_nodes, + r_pref_len=r_pref_len, + c_pref_len=c_pref_len, + row_len=row_len, + dtype=dtype, + return_node_ids=return_node_ids, + chunk_save_path_format=chunk_save_path_format, + memmap_kwargs=memmap_kwargs, + gpus=1 if is_single_chunk else gpus, + ) + + if is_single_chunk: + chunk_res = _generate_gpu_chunk_rmat_p((chunk_ids[0], prefix_edges[chunk_ids[0]])) + if return_node_ids == 2: + result, src_node_ids, dst_node_ids = chunk_res + elif return_node_ids == 1: + result, node_ids = chunk_res + else: + result = chunk_res + if use_memmap: + result = memmap_outfile + else: + multiprocessing.set_start_method('spawn', force=True) + + sub_res_lists = [] + if return_node_ids == 2: + src_node_ids_presence = np.full(2**r_scale, False) + dst_node_ids_presence = np.full(2**c_scale, False) + elif return_node_ids == 1: + node_ids_presence = np.full(2**theta_len, False) + + with multiprocessing.Pool(processes=gpus) as pool: + + chunk_res = pool.imap_unordered(_generate_gpu_chunk_rmat_p, + zip(chunk_ids, np.cumsum(prefix_edges[chunk_ids])), + chunksize=(len(chunk_ids)+gpus-1) // gpus ) + if verbose: + chunk_res = tqdm(chunk_res, total=len(chunk_ids)) + + if return_node_ids == 2: + for res, src_n_ids, dst_n_ids in chunk_res: + sub_res_lists.append(res) + src_node_ids_presence[src_n_ids] = True + dst_node_ids_presence[dst_n_ids] = True + elif return_node_ids == 1: + for res, n_ids in chunk_res: + sub_res_lists.append(res) + node_ids_presence[n_ids] = True + else: + sub_res_lists = list(chunk_res) + + if use_memmap: + result = memmap_outfile + elif chunk_save_path_format is None: + result = np.concatenate(sub_res_lists) + else: + result = int(np.sum(sub_res_lists)) + + if return_node_ids == 2: + src_node_ids, = np.where(src_node_ids_presence) + dst_node_ids, = np.where(dst_node_ids_presence) + elif return_node_ids == 1: + node_ids, = np.where(node_ids_presence) + + if return_node_ids == 2: + return result, src_node_ids, dst_node_ids + if return_node_ids == 1: + return result, node_ids + return result + + +def get_degree_distribution(vertices, gpu=False, operator=None): + operator = operator or (cp if gpu else np) + _, degrees = operator.unique(vertices, return_counts=True) + degree_values, degree_counts = operator.unique(degrees, return_counts=True) + return degree_values, degree_counts + + +class BaseLogger: + """ Base logger class + Args: + logdir (str): path to the logging directory + """ + + def __init__(self, logdir: str = "tmp"): + self.logdir = logdir + os.makedirs(self.logdir, exist_ok=True) + currentDateAndTime = datetime.now() + self.logname = ( + f'{currentDateAndTime.strftime("%Y_%m_%d_%H_%M_%S")}.txt' + ) + self.logpath = os.path.join(self.logdir, self.logname) + self.setup_logger() + self.log("Initialized logger") + + def setup_logger(self): + """ This function setups logger """ + logging.basicConfig( + filename=self.logpath, + filemode="a", + format="%(asctime)s| %(message)s", + datefmt="%Y/%m/%d %H:%M:%S", + level=logging.DEBUG, + ) + + def log(self, msg: str): + """ This function logs messages in debug mode + Args: + msg (str): message to be printed + """ + + logging.debug(msg) + + +def _reshuffle(X: NDArray, mask: NDArray, max_node_id: int) -> None: + """ + Shuffles dst nodes of edges specified by idx. + + Preserves degree distribution and keeps edge list sorted. + + """ + operator = infer_operator(X) + + if not operator.any(mask): + return + + target = X[mask, 1] + operator.random.shuffle(target) + X[mask, 1] = target + + src_node_mask = operator.zeros(max_node_id + 1, dtype=operator.bool_) + src_node_mask[X[mask, 0]] = True + + to_sort_mask = operator.zeros(X.shape[0], dtype=operator.bool_) + to_sort_mask = src_node_mask[X[:, 0]] + + to_sort = X[to_sort_mask] + to_sort = to_sort[operator.lexsort(to_sort.T[::-1])] + X[to_sort_mask] = to_sort + + +def _find_correct_edges( + X: NDArray, + self_loops: bool = False, + assume_sorted: bool = False, +) -> Tuple[NDArray, NDArray]: + """ Finds duplicates and self loops in an edge list. """ + operator = infer_operator(X) + + if not assume_sorted: + X = X[operator.lexsort(X.T[::-1])] + + mask = operator.empty(X.shape[0], dtype=operator.bool_) + mask[0] = True + mask[1:] = operator.any(X[1:] != X[:-1], axis=1) + + if not self_loops: + mask &= X[:, 0] != X[:, 1] + + return X, mask + + +def postprocess_edge_list(X: NDArray, n_reshuffle: int = 0, self_loops: bool = False) -> NDArray: + """ + Removes multi-edges and (optionally) self-loops. + + If n_reshuffle > 0 is specified, edges are shuffled between nodes + so that the degree distribution is preserved and less edges will be removed. + Assumes node set is reindexed from min_id > 0 to max_id ~ N. + + """ + max_node_id = X.max().item() + X, mask = _find_correct_edges(X, self_loops=self_loops) + + for _ in range(n_reshuffle): + _reshuffle(X, ~mask, max_node_id) + X, mask = _find_correct_edges(X, self_loops=self_loops, assume_sorted=True) + + return X[mask] diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/__init__.py new file mode 100644 index 000000000..0f28d8d4a --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/__init__.py @@ -0,0 +1,37 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .base_tabular_generator import BaseTabularGenerator +from .chunked_tabular_generator import ChunkedBaseTabularGenerator +from .ctgan import CTGANGenerator +from .gaussian_generator import GaussianGenerator +from .kde_generator import KDEGenerator +from .random import RandomMVGenerator +from .uniform_generator import UniformGenerator + +# Does not include CTGAN +tabular_generators_classes = { + 'kde': KDEGenerator, + 'random': RandomMVGenerator, + 'gaussian': GaussianGenerator, + 'uniform': UniformGenerator, + 'ctgan': CTGANGenerator, +} + +tabular_generators_types_to_classes = { + cls.__class__.__name__: k + for k, cls in tabular_generators_classes + .items() +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/base_tabular_generator.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/base_tabular_generator.py new file mode 100644 index 000000000..6a3bc2fb3 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/base_tabular_generator.py @@ -0,0 +1,76 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import abc + +import torch + + +class BaseTabularGenerator(abc.ABC): + """Base class for all tabular generators""" + + def __init__(self, **kwargs): + pass + + @classmethod + def get_generators(cls, include_parents=True): + """Recursively find subclasses of `BaseTabularGenerator` + + Args: + include_parents (bool): whether to include parents to other classes. (default: `True`) + """ + + generators = dict() + for child in cls.__subclasses__(): + children = child.get_generators(include_parents) + generators.update(children) + + if include_parents or not children: + if abc.ABC not in child.__bases__: + generators[child.__name__] = child + return generators + + def fit(self, *args, **kwargs): + """fit function for the generator + + Args: + *args: optional positional args + **kwargs: optional key-word arguments + """ + raise NotImplementedError() + + def sample(self, num_samples, *args, **kwargs): + """generate `num_samples` from generator + + Args: + num_samples (int): number of samples to generate + *args: optional positional args + **kwargs: optional key-word arguments + """ + raise NotImplementedError() + + def save(self, path): + raise NotImplementedError() + + @property + def supports_memmap(self) -> bool: + return False + + @classmethod + def load(cls, path): + raise NotImplementedError() + + @staticmethod + def add_args(parser): + return parser diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/chunked_tabular_generator.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/chunked_tabular_generator.py new file mode 100644 index 000000000..cf62ed541 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/chunked_tabular_generator.py @@ -0,0 +1,140 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os.path +from abc import ABC + +import tqdm +import cupy as cp +import numpy as np + +import multiprocessing +from functools import partial + +from syngen.utils.io_utils import dump_dataframe +from syngen.utils.types.dataframe_type import DataFrameType +from syngen.utils.memory_manager import MemoryManager +from syngen.generator.tabular import BaseTabularGenerator + + +class ChunkedBaseTabularGenerator(BaseTabularGenerator, ABC): + + """ A Chunked Base Tabular Generator contains the base functionality of the multiprocess (Multi-GPU) data generation. + + """ + def chunked_sampling(self, n_samples: int, save_path: str, fname: str, n_workers: int = 0, gpus: int = -1, + use_memmap=False, memory_threshold=0.8, verbose=True): + memory_manager = MemoryManager() + + if gpus < 0: + gpus = memory_manager.get_available_gpus() + + emp_n = 1000 + est_samples = self.sample(emp_n, gpu=False) + mem_usage = est_samples.memory_usage(index=True, deep=True).sum() + est_sample_mem = int(np.ceil(mem_usage / emp_n * self._space_complexity_factor())) + est_mem = est_sample_mem * n_samples + + memmap_kwargs = None + chunk_save_path = None + + if use_memmap: + assert fname.endswith(".npy") + memmap_shape = list(est_samples.shape) + memmap_shape[0] = n_samples + memmap_shape = tuple(memmap_shape) + memmap_dtype = est_samples.dtypes.iloc[0] + memmap_filename = os.path.join(save_path, fname) + memmap_kwargs = dict( + filename=memmap_filename, + ) + memmap_outfile = np.lib.format.open_memmap(memmap_filename, dtype=memmap_dtype, shape=memmap_shape, mode='w+') + else: + chunk_format = '{chunk_id}' + chunk_save_path = os.path.join(save_path, f'{fname}_{chunk_format}') + + if gpus > 0: + mem_avail = memory_manager.get_min_available_across_gpus_memory(gpus=gpus) + n_workers = gpus + chunk_partial = partial(self._generate_chunk, + chunk_save_path=chunk_save_path, gpu=True, gpus=gpus, memmap_kwargs=memmap_kwargs) + else: + mem_avail = memory_manager.get_available_virtual_memory() + chunk_partial = partial(self._generate_chunk, + chunk_save_path=chunk_save_path, gpu=False, memmap_kwargs=memmap_kwargs) + + if mem_avail * memory_threshold > est_mem: + df = self.sample(n_samples, gpu=True, memmap_kwargs=memmap_kwargs, start_idx=0, end_idx=n_samples) + if chunk_save_path: + chunk_save_path = chunk_save_path.format(chunk_id=0) + dump_dataframe(df, save_path=chunk_save_path, format='parquet') + res = [chunk_save_path] + else: + mem_avail = int(mem_avail * memory_threshold) # to avoid OOM + max_samples_per_chunk = int(mem_avail // est_sample_mem) + n_chunks = n_samples//max_samples_per_chunk + (1 if n_samples % max_samples_per_chunk > 0 else 0) + + samples_per_chunk = n_samples // n_chunks + chunk_sizes = [samples_per_chunk] * n_chunks + + if n_samples % n_chunks > 0: + chunk_sizes.append(n_samples % n_chunks) + + multiprocessing.set_start_method('spawn', force=True) + with multiprocessing.Pool(processes=n_workers) as pool: + res = pool.imap_unordered(chunk_partial, enumerate(zip(chunk_sizes, np.cumsum(chunk_sizes))), + chunksize=(len(chunk_sizes)+n_workers-1)//n_workers) + + if verbose: + res = tqdm.tqdm(res, total=len(chunk_sizes)) + + res = list(res) + + return res + + def _generate_chunk(self, chunk_info, chunk_save_path, gpu, memmap_kwargs, gpus=0): + chunk_id, (chunk_size, chunk_end) = chunk_info + + if gpu: + gpu_id = int(multiprocessing.current_process()._identity[0]) % gpus + with cp.cuda.Device(gpu_id): + df = self.sample(chunk_size, gpu=True, memmap_kwargs=memmap_kwargs, + start_idx=chunk_end-chunk_size, end_idx=chunk_end) + else: + df = self.sample(chunk_size, gpu=False, memmap_kwargs=memmap_kwargs, + start_idx=chunk_end-chunk_size, end_idx=chunk_end) + + if chunk_save_path: + chunk_save_path = chunk_save_path.format(chunk_id=chunk_id) + dump_dataframe(df, save_path=chunk_save_path, format='parquet') + + return chunk_save_path + + def _space_complexity_factor(self): + return 2.0 # we support float16 but it requires intermediate float32 + + @property + def supports_memmap(self) -> bool: + return True + + def sample(self, num_samples, *args, gpu=False, **kwargs) -> DataFrameType: + """generate `num_samples` from generator + + Args: + num_samples (int): number of samples to generate + gpu (bool): whether to use cpu or gpu implementation (default: False) + *args: optional positional args + **kwargs: optional key-word arguments + """ + raise NotImplementedError() diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/ctab.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/ctab.py new file mode 100644 index 000000000..1a30b8e1e --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/ctab.py @@ -0,0 +1,837 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Dict, List, Tuple + +import numpy as np +import pandas as pd +import torch +import torch.optim as optim +import torch.utils.data +from torch.nn import ( + BatchNorm2d, + BCELoss, + Conv2d, + ConvTranspose2d, + CrossEntropyLoss, + Dropout, + LeakyReLU, + Linear, + Module, + ReLU, + Sequential, + Sigmoid, + SmoothL1Loss, +) +from torch.nn import functional as F +from torch.nn import init +from torch.optim import Adam +from sklearn import model_selection, preprocessing + +from syngen.generator.tabular.base_tabular_generator import BaseTabularGenerator +from syngen.generator.tabular.data_transformer.ctab_data_transformer import ( + CTABDataTransformer, + ImageTransformer, +) +from syngen.utils.types import ColumnType + + +class CTABGenerator(BaseTabularGenerator): + """ + Adopted from: https://github.com/Team-TUD/CTAB-GAN + Args: + + embedding_dim (int): Size of the random sample passed to the Generator. Defaults to 128. + classifier_dim (tuple or list of ints): Size of the output samples for each one of the classifier Layers. + A Linear Layer will be created for each one of the values provided. + Defaults to (256, 256). + l2scale (float): L2 regularization scaling. Defaults to 1e-5. + batch_size (int): Number of data samples to process in each step. + epochs (int): Number of training epochs. Defaults to 300. + """ + + def __init__( + self, + classifier_dim: Tuple[int] = (256, 256, 256, 256), + embedding_dim: int = 100, + num_channels: int = 64, + l2scale: float = 1e-5, + batch_size: int = 500, + epochs: int = 1, + test_ratio: float = 0.1, + **kwargs, + ): + + self.embedding_dim = embedding_dim + self.classifier_dim = classifier_dim + self.num_channels = num_channels + self.dside = None + self.gside = None + self.l2scale = l2scale + self.batch_size = batch_size + self.epochs = epochs + self._device = torch.device( + "cuda:0" if torch.cuda.is_available() else "cpu" + ) + self.test_ratio = test_ratio + + def column_check(self, data: pd.DataFrame, columns: list): + data_cols = data.columns + invalid_cols = [] + for c in columns: + if c not in data_cols: + invalid_cols.append(c) + return invalid_cols + + def set_device(self, device): + self._device = device + if self._generator is not None: + self._generator.to(self._device) + + def fit( + self, + train_data: pd.DataFrame, + categorical_columns: List[str] = [], + log_columns: List[str] = [], + integer_columns: List[str] = [], + mixed_columns: Dict = {}, + problem_type: Dict = {}, + ): + + specified_cols = ( + list(categorical_columns) + + list(log_columns) + + list(mixed_columns) + + list(integer_columns) + ) + target_col = None + target_index = None + if problem_type: # - supports only single problem type + target_col = list(problem_type.values())[0] + specified_cols += [target_col] + + # - check for invalid columns + invalid_cols = self.column_check(train_data, specified_cols) + if len(invalid_cols): + raise ValueError(f"invalid columns: {invalid_cols}") + + if target_col is not None: + target_index = train_data.columns.get_loc(target_col) + + self.data_prep = DataPreprocessing( + categorical_columns=categorical_columns, + log_columns=log_columns, + mixed_columns=mixed_columns, + integer_columns=integer_columns, + test_ratio=self.test_ratio, + target_col=target_col, + ) + train_data = self.data_prep.transform(train_data) + categorical_columns = self.data_prep.column_types[ + ColumnType.CATEGORICAL + ] + mixed_columns = self.data_prep.column_types[ColumnType.MIXED] + self.transformer = CTABDataTransformer( + categorical_columns=categorical_columns, mixed_dict=mixed_columns + ) + self.transformer.fit(train_data) + + train_data = self.transformer.transform(train_data.values) + + data_sampler = Sampler(train_data, self.transformer.output_info) + data_dim = self.transformer.output_dim + self.cond_generator = Cond(train_data, self.transformer.output_info) + sides = [4, 8, 16, 24, 32, 64, 128] + col_size_d = data_dim + self.cond_generator.n_opt + for i in sides: + if i * i >= col_size_d: + self.dside = i + break + + sides = [4, 8, 16, 24, 32, 64, 128] + col_size_g = data_dim + for i in sides: + if i * i >= col_size_g: + self.gside = i + break + + layers_G = determine_layers_gen( + self.gside, + self.embedding_dim + self.cond_generator.n_opt, + self.num_channels, + ) + layers_D = determine_layers_disc(self.dside, self.num_channels) + + self._generator = Generator(self.gside, layers_G).to(self._device) + discriminator = Discriminator(self.dside, layers_D).to(self._device) + optimizer_params = dict( + lr=2e-4, betas=(0.5, 0.9), eps=1e-3, weight_decay=self.l2scale + ) + optimizerG = Adam(self._generator.parameters(), **optimizer_params) + optimizerD = Adam(discriminator.parameters(), **optimizer_params) + + st_ed = None + classifier = None + optimizerC = None + if target_index is not None: + st_ed = get_st_ed(target_index, self.transformer.output_info) + classifier = Classifier(data_dim, self.classifier_dim, st_ed).to( + self._device + ) + optimizerC = optim.Adam( + classifier.parameters(), **optimizer_params + ) + + self._generator.apply(weights_init) + discriminator.apply(weights_init) + + self.Gtransformer = ImageTransformer(self.gside) + self.Dtransformer = ImageTransformer(self.dside) + + steps_per_epoch = max(1, len(train_data) // self.batch_size) + for i in range(self.epochs): + for _ in range(steps_per_epoch): + + noisez = torch.randn( + self.batch_size, self.embedding_dim, device=self._device + ) + condvec = self.cond_generator.sample_train(self.batch_size) + + c, m, col, opt = condvec + c = torch.from_numpy(c).to(self._device) + m = torch.from_numpy(m).to(self._device) + noisez = torch.cat([noisez, c], dim=1) + noisez = noisez.view( + self.batch_size, + self.embedding_dim + self.cond_generator.n_opt, + 1, + 1, + ) + + perm = np.arange(self.batch_size) + np.random.shuffle(perm) + real = data_sampler.sample( + self.batch_size, col[perm], opt[perm] + ) + c_perm = c[perm] + + real = torch.from_numpy(real.astype("float32")).to( + self._device + ) + fake = self._generator(noisez) + faket = self.Gtransformer.inverse_transform(fake) + fakeact = apply_activate(faket, self.transformer.output_info) + + fake_cat = torch.cat([fakeact, c], dim=1) + real_cat = torch.cat([real, c_perm], dim=1) + + real_cat_d = self.Dtransformer.transform(real_cat) + fake_cat_d = self.Dtransformer.transform(fake_cat) + + optimizerD.zero_grad() + y_real, _ = discriminator(real_cat_d) + y_fake, _ = discriminator(fake_cat_d) + loss_d = -(torch.log(y_real + 1e-4).mean()) - ( + torch.log(1.0 - y_fake + 1e-4).mean() + ) + loss_d.backward() + optimizerD.step() + + noisez = torch.randn( + self.batch_size, self.embedding_dim, device=self._device + ) + + condvec = self.cond_generator.sample_train(self.batch_size) + + c, m, col, opt = condvec + c = torch.from_numpy(c).to(self._device) + m = torch.from_numpy(m).to(self._device) + noisez = torch.cat([noisez, c], dim=1) + noisez = noisez.view( + self.batch_size, + self.embedding_dim + self.cond_generator.n_opt, + 1, + 1, + ) + + optimizerG.zero_grad() + + fake = self._generator(noisez) + faket = self.Gtransformer.inverse_transform(fake) + fakeact = apply_activate(faket, self.transformer.output_info) + + fake_cat = torch.cat([fakeact, c], dim=1) + fake_cat = self.Dtransformer.transform(fake_cat) + + y_fake, info_fake = discriminator(fake_cat) + + cross_entropy = cond_loss( + faket, self.transformer.output_info, c, m + ) + + _, info_real = discriminator(real_cat_d) + + g = -(torch.log(y_fake + 1e-4).mean()) + cross_entropy + g.backward(retain_graph=True) + loss_mean = torch.norm( + torch.mean(info_fake.view(self.batch_size, -1), dim=0) + - torch.mean(info_real.view(self.batch_size, -1), dim=0), + 1, + ) + loss_std = torch.norm( + torch.std(info_fake.view(self.batch_size, -1), dim=0) + - torch.std(info_real.view(self.batch_size, -1), dim=0), + 1, + ) + loss_info = loss_mean + loss_std + loss_info.backward() + optimizerG.step() + + if problem_type: + fake = self._generator(noisez) + faket = self.Gtransformer.inverse_transform(fake) + fakeact = apply_activate( + faket, self.transformer.output_info + ) + + real_pre, real_label = classifier(real) + fake_pre, fake_label = classifier(fakeact) + + c_loss = CrossEntropyLoss() + + if (st_ed[1] - st_ed[0]) == 1: + c_loss = SmoothL1Loss() + real_label = real_label.type_as(real_pre) + fake_label = fake_label.type_as(fake_pre) + real_label = torch.reshape(real_label, real_pre.size()) + fake_label = torch.reshape(fake_label, fake_pre.size()) + + elif (st_ed[1] - st_ed[0]) == 2: + c_loss = BCELoss() + real_label = real_label.type_as(real_pre) + fake_label = fake_label.type_as(fake_pre) + + loss_cc = c_loss(real_pre, real_label) + loss_cg = c_loss(fake_pre, fake_label) + + optimizerG.zero_grad() + loss_cg.backward() + optimizerG.step() + + optimizerC.zero_grad() + loss_cc.backward() + optimizerC.step() + + def sample(self, n, **kwargs): + assert hasattr(self, "_generator"), "`fit` function must be called prior to `sample`" + + self._generator.eval() + + output_info = self.transformer.output_info + steps = n // self.batch_size + 1 + + data = [] + + for i in range(steps): + noisez = torch.randn( + self.batch_size, self.embedding_dim, device=self._device + ) + condvec = self.cond_generator.sample(self.batch_size) + c = condvec + c = torch.from_numpy(c).to(self._device) + noisez = torch.cat([noisez, c], dim=1) + noisez = noisez.view( + self.batch_size, + self.embedding_dim + self.cond_generator.n_opt, + 1, + 1, + ) + + fake = self._generator(noisez) + faket = self.Gtransformer.inverse_transform(fake) + fakeact = apply_activate(faket, output_info) + data.append(fakeact.detach().cpu().numpy()) + + data = np.concatenate(data, axis=0) + result = self.transformer.inverse_transform(data) + output = self.data_prep.inverse_prep(result) + return output.iloc[:n] + + +class Classifier(Module): + def __init__(self, input_dim, dis_dims, st_ed): + super(Classifier, self).__init__() + dim = input_dim - (st_ed[1] - st_ed[0]) + seq = [] + self.str_end = st_ed + for item in list(dis_dims): + seq += [Linear(dim, item), LeakyReLU(0.2), Dropout(0.5)] + dim = item + + if (st_ed[1] - st_ed[0]) == 1: + seq += [Linear(dim, 1)] + + elif (st_ed[1] - st_ed[0]) == 2: + seq += [Linear(dim, 1), Sigmoid()] + else: + seq += [Linear(dim, (st_ed[1] - st_ed[0]))] + + self.seq = Sequential(*seq) + + def forward(self, input): + + label = None + + if (self.str_end[1] - self.str_end[0]) == 1: + label = input[:, self.str_end[0] : self.str_end[1]] + else: + label = torch.argmax( + input[:, self.str_end[0] : self.str_end[1]], axis=-1 + ) + + new_imp = torch.cat( + (input[:, : self.str_end[0]], input[:, self.str_end[1] :]), 1 + ) + + if ((self.str_end[1] - self.str_end[0]) == 2) | ( + (self.str_end[1] - self.str_end[0]) == 1 + ): + return self.seq(new_imp).view(-1), label + else: + return self.seq(new_imp), label + + +def apply_activate(data, output_info): + data_t = [] + st = 0 + for item in output_info: + if item[1] == "tanh": + ed = st + item[0] + data_t.append(torch.tanh(data[:, st:ed])) + st = ed + elif item[1] == "softmax": + ed = st + item[0] + data_t.append(F.gumbel_softmax(data[:, st:ed], tau=0.2)) + st = ed + return torch.cat(data_t, dim=1) + + +def get_st_ed(target_col_index, output_info): + st = 0 + c = 0 + tc = 0 + for item in output_info: + if c == target_col_index: + break + if item[1] == "tanh": + st += item[0] + elif item[1] == "softmax": + st += item[0] + c += 1 + tc += 1 + ed = st + output_info[tc][0] + return (st, ed) + + +def random_choice_prob_index_sampling(probs, col_idx): + option_list = [] + for i in col_idx: + pp = probs[i] + option_list.append(np.random.choice(np.arange(len(probs[i])), p=pp)) + + return np.array(option_list).reshape(col_idx.shape) + + +def random_choice_prob_index(a, axis=1): + r = np.expand_dims(np.random.rand(a.shape[1 - axis]), axis=axis) + return (a.cumsum(axis=axis) > r).argmax(axis=axis) + + +def maximum_interval(output_info): + max_interval = 0 + for item in output_info: + max_interval = max(max_interval, item[0]) + return max_interval + + +class Cond(object): + def __init__(self, data, output_info): + + self.model = [] + st = 0 + counter = 0 + for item in output_info: + + if item[1] == "tanh": + st += item[0] + elif item[1] == "softmax": + ed = st + item[0] + counter += 1 + self.model.append(np.argmax(data[:, st:ed], axis=-1)) + st = ed + + self.interval = [] + self.n_col = 0 + self.n_opt = 0 + st = 0 + self.p = np.zeros((counter, maximum_interval(output_info))) + self.p_sampling = [] + for item in output_info: + if item[1] == "tanh": + st += item[0] + elif item[1] == "softmax": + ed = st + item[0] + tmp = np.sum(data[:, st:ed], axis=0) + tmp_sampling = np.sum(data[:, st:ed], axis=0) + tmp = np.log(tmp + 1) + tmp = tmp / np.sum(tmp) + tmp_sampling = tmp_sampling / np.sum(tmp_sampling) + self.p_sampling.append(tmp_sampling) + self.p[self.n_col, : item[0]] = tmp + self.interval.append((self.n_opt, item[0])) + self.n_opt += item[0] + self.n_col += 1 + st = ed + + self.interval = np.asarray(self.interval) + + def sample_train(self, batch): + if self.n_col == 0: + return None + idx = np.random.choice(np.arange(self.n_col), batch) + + vec = np.zeros((batch, self.n_opt), dtype="float32") + mask = np.zeros((batch, self.n_col), dtype="float32") + mask[np.arange(batch), idx] = 1 + opt1prime = random_choice_prob_index(self.p[idx]) + for i in np.arange(batch): + vec[i, self.interval[idx[i], 0] + opt1prime[i]] = 1 + + return vec, mask, idx, opt1prime + + def sample(self, batch): + if self.n_col == 0: + return None + idx = np.random.choice(np.arange(self.n_col), batch) + + vec = np.zeros((batch, self.n_opt), dtype="float32") + opt1prime = random_choice_prob_index_sampling(self.p_sampling, idx) + + for i in np.arange(batch): + vec[i, self.interval[idx[i], 0] + opt1prime[i]] = 1 + + return vec + + +def cond_loss(data, output_info, c, m): + loss = [] + st = 0 + st_c = 0 + for item in output_info: + if item[1] == "tanh": + st += item[0] + + elif item[1] == "softmax": + ed = st + item[0] + ed_c = st_c + item[0] + tmp = F.cross_entropy( + data[:, st:ed], + torch.argmax(c[:, st_c:ed_c], dim=1), + reduction="none", + ) + loss.append(tmp) + st = ed + st_c = ed_c + + loss = torch.stack(loss, dim=1) + return (loss * m).sum() / data.size()[0] + + +class Sampler(object): + def __init__(self, data, output_info): + super(Sampler, self).__init__() + self.data = data + self.model = [] + self.n = len(data) + st = 0 + for item in output_info: + if item[1] == "tanh": + st += item[0] + elif item[1] == "softmax": + ed = st + item[0] + tmp = [] + for j in range(item[0]): + tmp.append(np.nonzero(data[:, st + j])[0]) + self.model.append(tmp) + st = ed + + def sample(self, n, col, opt): + if col is None: + idx = np.random.choice(np.arange(self.n), n) + return self.data[idx] + idx = [] + for c, o in zip(col, opt): + idx.append(np.random.choice(self.model[c][o])) + return self.data[idx] + + +class Discriminator(Module): + def __init__(self, side, layers): + super(Discriminator, self).__init__() + self.side = side + info = len(layers) - 2 + self.seq = Sequential(*layers) + self.seq_info = Sequential(*layers[:info]) + + def forward(self, input): + return (self.seq(input)), self.seq_info(input) + + +class Generator(Module): + def __init__(self, side, layers): + super(Generator, self).__init__() + self.side = side + self.seq = Sequential(*layers) + + def forward(self, input_): + return self.seq(input_) + + +def determine_layers_disc(side, num_channels): + layer_dims = [(1, side), (num_channels, side // 2)] + + while layer_dims[-1][1] > 3 and len(layer_dims) < 4: + layer_dims.append((layer_dims[-1][0] * 2, layer_dims[-1][1] // 2)) + + layers_D = [] + for prev, curr in zip(layer_dims, layer_dims[1:]): + layers_D += [ + Conv2d(prev[0], curr[0], 4, 2, 1, bias=False), + BatchNorm2d(curr[0]), + LeakyReLU(0.2, inplace=True), + ] + print() + layers_D += [ + Conv2d(layer_dims[-1][0], 1, layer_dims[-1][1], 1, 0), + Sigmoid(), + ] + + return layers_D + + +def determine_layers_gen(side, embedding_dim, num_channels): + + layer_dims = [(1, side), (num_channels, side // 2)] + + while layer_dims[-1][1] > 3 and len(layer_dims) < 4: + layer_dims.append((layer_dims[-1][0] * 2, layer_dims[-1][1] // 2)) + + layers_G = [ + ConvTranspose2d( + embedding_dim, + layer_dims[-1][0], + layer_dims[-1][1], + 1, + 0, + output_padding=0, + bias=False, + ) + ] + + for prev, curr in zip(reversed(layer_dims), reversed(layer_dims[:-1])): + layers_G += [ + BatchNorm2d(prev[0]), + ReLU(True), + ConvTranspose2d( + prev[0], curr[0], 4, 2, 1, output_padding=0, bias=True + ), + ] + return layers_G + + +def weights_init(m): + classname = m.__class__.__name__ + + if classname.find("Conv") != -1: + init.normal_(m.weight.data, 0.0, 0.02) + + elif classname.find("BatchNorm") != -1: + init.normal_(m.weight.data, 1.0, 0.02) + init.constant_(m.bias.data, 0) + + +class DataPreprocessing(object): + def __init__( + self, + categorical_columns: list, + log_columns: list, + mixed_columns: dict, + integer_columns: list, + test_ratio: float, + target_col: str = None, + ): + self.categorical_columns = categorical_columns + self.log_columns = log_columns + self.mixed_columns = mixed_columns + self.integer_columns = integer_columns + self.column_types = dict() + self.column_types[ColumnType.CATEGORICAL] = [] + self.column_types[ColumnType.MIXED] = {} + self.lower_bounds = {} + self.label_encoder_list = [] + self.CONSTANT_INT = -9999999 + + if target_col is not None: + self.target_col = target_col + + self.test_ratio = test_ratio + super().__init__() + + def transform(self, raw_df: pd.DataFrame): + + if hasattr(self, "target_col"): + y_real = raw_df[self.target_col] + X_real = raw_df.drop(columns=[self.target_col]) + ( + X_train_real, + _, + y_train_real, + _, + ) = model_selection.train_test_split( + X_real, + y_real, + test_size=self.test_ratio, + stratify=y_real, + random_state=42, + ) + X_train_real.loc[:, self.target_col] = y_train_real + else: + X_train_real = raw_df + self.df = X_train_real + self.df = self.df.replace(r" ", np.nan) + self.df = self.df.fillna("empty") + + all_columns = set(self.df.columns) + irrelevant_missing_columns = set(self.categorical_columns) + relevant_missing_columns = list( + all_columns - irrelevant_missing_columns + ) + + for i in relevant_missing_columns: + if i in self.log_columns: + if "empty" in list(self.df[i].values): + self.df[i] = self.df[i].apply( + lambda x: self.CONSTANT_INT if x == "empty" else x + ) + self.mixed_columns[i] = [self.CONSTANT_INT] + elif i in list(self.mixed_columns.keys()): + if "empty" in list(self.df[i].values): + self.df[i] = self.df[i].apply( + lambda x: self.CONSTANT_INT if x == "empty" else x + ) + self.mixed_columns[i].append(self.CONSTANT_INT) + else: + if "empty" in list(self.df[i].values): + self.df[i] = self.df[i].apply( + lambda x: self.CONSTANT_INT if x == "empty" else x + ) + self.mixed_columns[i] = [self.CONSTANT_INT] + + if self.log_columns: + for log_column in self.log_columns: + valid_indices = [] + for idx, val in enumerate(self.df[log_column].values): + if val != self.CONSTANT_INT: + valid_indices.append(idx) + eps = 1 + lower = np.min(self.df[log_column].iloc[valid_indices].values) + self.lower_bounds[log_column] = lower + if lower > 0: + self.df[log_column] = self.df[log_column].apply( + lambda x: np.log(x) if x != self.CONSTANT_INT else self.CONSTANT_INT + ) + elif lower == 0: + self.df[log_column] = self.df[log_column].apply( + lambda x: np.log(x + eps) + if x != self.CONSTANT_INT + else self.CONSTANT_INT + ) + else: + self.df[log_column] = self.df[log_column].apply( + lambda x: np.log(x - lower + eps) + if x != self.CONSTANT_INT + else self.CONSTANT_INT + ) + + for column_index, column in enumerate(self.df.columns): + if column in self.categorical_columns: + label_encoder = preprocessing.LabelEncoder() + self.df[column] = self.df[column].astype(str) + label_encoder.fit(self.df[column]) + current_label_encoder = dict() + current_label_encoder["column"] = column + current_label_encoder["label_encoder"] = label_encoder + transformed_column = label_encoder.transform(self.df[column]) + self.df[column] = transformed_column + self.label_encoder_list.append(current_label_encoder) + self.column_types[ColumnType.CATEGORICAL].append(column_index) + + elif column in self.mixed_columns: + self.column_types[ColumnType.MIXED][ + column_index + ] = self.mixed_columns[column] + + return self.df + + def inverse_prep(self, data, eps=1): + + df_sample = pd.DataFrame(data, columns=self.df.columns) + + for i in range(len(self.label_encoder_list)): + le = self.label_encoder_list[i]["label_encoder"] + df_sample[self.label_encoder_list[i]["column"]] = df_sample[ + self.label_encoder_list[i]["column"] + ].astype(int) + df_sample[ + self.label_encoder_list[i]["column"] + ] = le.inverse_transform( + df_sample[self.label_encoder_list[i]["column"]] + ) + + if self.log_columns: + for i in df_sample: + if i in self.log_columns: + lower_bound = self.lower_bounds[i] + if lower_bound > 0: + df_sample[i].apply(lambda x: np.exp(x)) + elif lower_bound == 0: + df_sample[i] = df_sample[i].apply( + lambda x: np.ceil(np.exp(x) - eps) + if (np.exp(x) - eps) < 0 + else (np.exp(x) - eps) + ) + else: + df_sample[i] = df_sample[i].apply( + lambda x: np.exp(x) - eps + lower_bound + ) + + if self.integer_columns: + for column in self.integer_columns: + df_sample[column] = np.round(df_sample[column].values) + df_sample[column] = df_sample[column].astype(int) + + df_sample.replace(self.CONSTANT_INT, np.nan, inplace=True) + df_sample.replace("empty", np.nan, inplace=True) + + return df_sample \ No newline at end of file diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/ctgan.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/ctgan.py new file mode 100644 index 000000000..380234074 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/ctgan.py @@ -0,0 +1,734 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import sys +import warnings +from typing import Optional, List + +import cudf +import numpy as np +import pandas as pd +import torch +from packaging import version +from torch import optim +from torch.nn import ( + BatchNorm1d, + Dropout, + LeakyReLU, + Linear, + Module, + ReLU, + Sequential, + functional, +) + +from syngen.generator.tabular.base_tabular_generator import BaseTabularGenerator +from syngen.generator.tabular.data_transformer.ctgan_data_transformer import ( + CTGANDataTransformer, +) + + +class CTGANGenerator(BaseTabularGenerator): + """Conditional Table GAN Generator. + For more details about the process, please check the + [Modeling Tabular data using Conditional GAN](https://arxiv.org/abs/1907.00503) paper. + Adopted from: https://github.com/sdv-dev/CTGAN + Args: + + embedding_dim (int): Size of the random sample passed to the Generator. Defaults to 128. + generator_dim (tuple or list of ints): Size of the output samples for each one of the Residuals. A Residual Layer + will be created for each one of the values provided. Defaults to (256, 256). + discriminator_dim (tuple or list of ints): Size of the output samples for each one of the Discriminator Layers. A Linear Layer + will be created for each one of the values provided. Defaults to (256, 256). + generator_lr (float):Learning rate for the generator. Defaults to 2e-4. + generator_decay (float):Generator weight decay for the Adam Optimizer. Defaults to 1e-6. + discriminator_lr (float):Learning rate for the discriminator. Defaults to 2e-4. + discriminator_decay (float):Discriminator weight decay for the Adam Optimizer. Defaults to 1e-6. + batch_size (int):Number of data samples to process in each step. + discriminator_steps (int):Number of discriminator updates to do for each generator update. + From the WGAN paper: https://arxiv.org/abs/1701.07875. WGAN paper + default is 5. Default used is 1 to match original CTGAN implementation. + log_frequency (boolean):Whether to use log frequency of categorical levels in conditional + sampling. Defaults to ``True``. + verbose (boolean):Whether to have print statements for progress results. Defaults to ``False``. + epochs (int):Number of training epochs. Defaults to 300. + pac (int):Number of samples to group together when applying the discriminator. + Defaults to 10. + gpu (bool):Whether to attempt to use cuda for GPU computation. + If this is False or CUDA is not available, CPU will be used. + Defaults to ``True``. + """ + + def __init__( + self, + embedding_dim=128, + generator_dim=(256, 256), + discriminator_dim=(256, 256), + generator_lr=2e-4, + generator_decay=1e-6, + discriminator_lr=2e-4, + discriminator_decay=1e-6, + batch_size=500, + discriminator_steps=1, + log_frequency=True, + verbose=False, + epochs=300, + pac=10, + gpu=True, + **kwargs, + ): + super(CTGANGenerator, self).__init__(**kwargs) + assert batch_size % 2 == 0 + + logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) + logger = logging.getLogger(__name__) + self.log = logger + self._embedding_dim = embedding_dim + self._generator_dim = generator_dim + self._discriminator_dim = discriminator_dim + + self._generator_lr = generator_lr + self._generator_decay = generator_decay + self._discriminator_lr = discriminator_lr + self._discriminator_decay = discriminator_decay + + self._batch_size = int(batch_size) + self._discriminator_steps = discriminator_steps + self._log_frequency = log_frequency + self._verbose = verbose + self._epochs = epochs + self.pac = pac + + if not gpu or not torch.cuda.is_available(): + device = "cpu" + elif isinstance(gpu, str): + device = gpu + else: + device = "cuda" + + self._device = torch.device(device) + + self._transformer = None + self._data_sampler = None + self._generator = None + + @staticmethod + def _gumbel_softmax(logits, tau=1, hard=False, eps=1e-10, dim=-1): + """Deals with the instability of the gumbel_softmax for older versions of torch. + + For more details about the issue: + https://drive.google.com/file/d/1AA5wPfZ1kquaRtVruCd6BiYZGcDeNxyP/view?usp=sharing + Parameters + ********** + logits: + […, num_features] unnormalized log probabilities + tau: + non-negative scalar temperature + hard: + if True, the returned samples will be discretized as one-hot vectors, + but will be differentiated as if it is the soft sample in autograd + dim (int): + a dimension along which softmax will be computed. Default: -1. + Returns + ******* + Sampled tensor of same shape as logits from the Gumbel-Softmax distribution. + """ + if version.parse(torch.__version__) < version.parse("1.2.0"): + for i in range(10): + transformed = functional.gumbel_softmax( + logits, tau=tau, hard=hard, eps=eps, dim=dim + ) + if not torch.isnan(transformed).any(): + return transformed + raise ValueError("gumbel_softmax returning NaN.") + + return functional.gumbel_softmax( + logits, tau=tau, hard=hard, eps=eps, dim=dim + ) + + def _apply_activate(self, data): + """Apply proper activation function to the output of the generator.""" + data_t = [] + st = 0 + for column_info in self._transformer.output_info_list: + for span_info in column_info: + if span_info.activation_fn == "tanh": + ed = st + span_info.dim + data_t.append(torch.tanh(data[:, st:ed])) + st = ed + elif span_info.activation_fn == "softmax": + ed = st + span_info.dim + transformed = self._gumbel_softmax(data[:, st:ed], tau=0.2) + data_t.append(transformed) + st = ed + else: + assert 0 + + return torch.cat(data_t, dim=1) + + def _cond_loss(self, data, c, m): + """Compute the cross entropy loss on the fixed discrete column.""" + loss = [] + st = 0 + st_c = 0 + for column_info in self._transformer.output_info_list: + for span_info in column_info: + if ( + len(column_info) != 1 + or span_info.activation_fn != "softmax" + ): + # not discrete column + st += span_info.dim + else: + ed = st + span_info.dim + ed_c = st_c + span_info.dim + tmp = functional.cross_entropy( + data[:, st:ed], + torch.argmax(c[:, st_c:ed_c], dim=1), + reduction="none", + ) + loss.append(tmp) + st = ed + st_c = ed_c + + loss = torch.stack(loss, dim=1) + + return (loss * m).sum() / data.size()[0] + + def _validate_discrete_columns(self, train_data, categorical_columns): + """Check whether ``categorical_columns`` exists in ``train_data``. + + Args: + + train_data (numpy.ndarray or pandas.DataFrame): + Training Data. It must be a 2-dimensional numpy array or a pandas.DataFrame. + categorical_columns (list-like): + List of discrete columns to be used to generate the Conditional + Vector. If ``train_data`` is a Numpy array, this list should + contain the integer indices of the columns. Otherwise, if it is + a ``pandas.DataFrame``, this list should contain the column names. + """ + if isinstance(train_data, (pd.DataFrame, cudf.DataFrame)): + invalid_columns = set(categorical_columns) - set( + train_data.columns + ) + elif isinstance(train_data, np.ndarray): + invalid_columns = [] + for column in categorical_columns: + if column < 0 or column >= train_data.shape[1]: + invalid_columns.append(column) + else: + raise TypeError( + "``train_data`` should be either pd.DataFrame or np.array." + ) + + if invalid_columns: + raise ValueError( + "Invalid columns found: {}".format(invalid_columns) + ) + + def fit(self, train_data, categorical_columns=tuple(), epochs=None, **kwargs): + """Fit the CTGAN Synthesizer models to the training data. + + Args: + + train_data (numpy.ndarray or pandas.DataFrame): + Training Data. It must be a 2-dimensional numpy array or a pandas.DataFrame. + categorical_columns (list-like): + List of discrete columns to be used to generate the Conditional + Vector. If ``train_data`` is a Numpy array, this list should + contain the integer indices of the columns. Otherwise, if it is + a ``pandas.DataFrame``, this list should contain the column names. + """ + self._validate_discrete_columns(train_data, categorical_columns) + + if epochs is None: + epochs = self._epochs + else: + warnings.warn( + ( + "`epochs` argument in `fit` method has been deprecated and will be removed " + "in a future version. Please pass `epochs` to the constructor instead" + ), + DeprecationWarning, + ) + + self._transformer = CTGANDataTransformer() + self._transformer.fit(train_data, categorical_columns) + train_data = self._transformer.transform(train_data) + + self._data_sampler = DataSampler( + train_data, self._transformer.output_info_list, self._log_frequency + ) + + data_dim = self._transformer.output_dimensions + + self._generator = Generator( + self._embedding_dim + self._data_sampler.dim_cond_vec(), + self._generator_dim, + data_dim, + ).to(self._device) + + discriminator = Discriminator( + data_dim + self._data_sampler.dim_cond_vec(), + self._discriminator_dim, + pac=self.pac, + ).to(self._device) + + optimizerG = optim.Adam( + self._generator.parameters(), + lr=self._generator_lr, + betas=(0.5, 0.9), + weight_decay=self._generator_decay, + ) + + optimizerD = optim.Adam( + discriminator.parameters(), + lr=self._discriminator_lr, + betas=(0.5, 0.9), + weight_decay=self._discriminator_decay, + ) + mean = torch.zeros( + self._batch_size, self._embedding_dim, device=self._device + ) + std = mean + 1 + + steps_per_epoch = max(len(train_data) // self._batch_size, 1) + for i in range(epochs): + for id_ in range(steps_per_epoch): + + for n in range(self._discriminator_steps): + fakez = torch.normal(mean=mean, std=std) + + condvec = self._data_sampler.sample_condvec( + self._batch_size + ) + if condvec is None: + c1, m1, col, opt = None, None, None, None + real = self._data_sampler.sample_data( + self._batch_size, col, opt + ) + else: + c1, m1, col, opt = condvec + c1 = torch.from_numpy(c1).to(self._device) + m1 = torch.from_numpy(m1).to(self._device) + fakez = torch.cat([fakez, c1], dim=1) + + perm = np.arange(self._batch_size) + np.random.shuffle(perm) + real = self._data_sampler.sample_data( + self._batch_size, col[perm], opt[perm] + ) + c2 = c1[perm] + + fake = self._generator(fakez) + fakeact = self._apply_activate(fake) + + real = torch.from_numpy(real.astype("float32")).to( + self._device + ) + + if c1 is not None: + fake_cat = torch.cat([fakeact, c1], dim=1) + real_cat = torch.cat([real, c2], dim=1) + else: + real_cat = real + fake_cat = fakeact + + y_fake = discriminator(fake_cat) + y_real = discriminator(real_cat) + + pen = discriminator.calc_gradient_penalty( + real_cat, fake_cat, self._device, self.pac + ) + loss_d = -(torch.mean(y_real) - torch.mean(y_fake)) + + optimizerD.zero_grad() + pen.backward(retain_graph=True) + loss_d.backward() + optimizerD.step() + + fakez = torch.normal(mean=mean, std=std) + condvec = self._data_sampler.sample_condvec(self._batch_size) + + if condvec is None: + c1, m1, col, opt = None, None, None, None + else: + c1, m1, col, opt = condvec + c1 = torch.from_numpy(c1).to(self._device) + m1 = torch.from_numpy(m1).to(self._device) + fakez = torch.cat([fakez, c1], dim=1) + + fake = self._generator(fakez) + fakeact = self._apply_activate(fake) + + if c1 is not None: + y_fake = discriminator(torch.cat([fakeact, c1], dim=1)) + else: + y_fake = discriminator(fakeact) + + if condvec is None: + cross_entropy = 0 + else: + cross_entropy = self._cond_loss(fake, c1, m1) + + loss_g = -torch.mean(y_fake) + cross_entropy + + optimizerG.zero_grad() + loss_g.backward() + optimizerG.step() + + if self._verbose: + self.log.info( + f"Epoch {i + 1}, Loss G: {loss_g.detach().cpu(): .4f}, " + f"Loss D: {loss_d.detach().cpu(): .4f}" + ) + + def sample(self, n, gpu=False, condition_column=None, condition_value=None, ): + """Sample data similar to the training data. + + Choosing a condition_column and condition_value will increase the probability of the + discrete condition_value happening in the condition_column. + Args: + n (int): + Number of rows to sample. + condition_column (string): + Name of a discrete column. + condition_value (string): + Name of the category in the condition_column which we wish to increase the + probability of happening. + Returns: + numpy.ndarray or pandas.DataFrame + """ + + if gpu: + self.set_device('cuda') + else: + self.set_device('cpu') + + if condition_column is not None and condition_value is not None: + condition_info = self._transformer.convert_column_name_value_to_id( + condition_column, condition_value + ) + global_condition_vec = self._data_sampler.generate_cond_from_condition_column_info( + condition_info, self._batch_size + ) + else: + global_condition_vec = None + + steps = n // self._batch_size + 1 + data = [] + for i in range(steps): + mean = torch.zeros(self._batch_size, self._embedding_dim) + std = mean + 1 + fakez = torch.normal(mean=mean, std=std).to(self._device) + + if global_condition_vec is not None: + condvec = global_condition_vec.copy() + else: + condvec = self._data_sampler.sample_original_condvec( + self._batch_size + ) + + if condvec is not None: + c1 = condvec + c1 = torch.from_numpy(c1).to(self._device) + fakez = torch.cat([fakez, c1], dim=1) + + fake = self._generator(fakez) + fakeact = self._apply_activate(fake) + data.append(fakeact.detach().cpu().numpy()) + + data = np.concatenate(data, axis=0) + data = data[:n] + + return self._transformer.inverse_transform(data) + + def set_device(self, device): + self._device = device + if self._generator is not None: + self._generator.to(self._device) + + def save(self, path): + """save the trained model""" + device_backup = self._device + self.set_device(torch.device("cpu")) + torch.save(self, path) + self.set_device(device_backup) + + @classmethod + def load(cls, path): + """load model from `path`""" + device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") + model = torch.load(path) + model.set_device(device) + return model + + +class Discriminator(Module): + def __init__(self, input_dim, discriminator_dim, pac=10): + super(Discriminator, self).__init__() + dim = input_dim * pac + self.pac = pac + self.pacdim = dim + seq = [] + for item in list(discriminator_dim): + seq += [Linear(dim, item), LeakyReLU(0.2), Dropout(0.5)] + dim = item + + seq += [Linear(dim, 1)] + self.seq = Sequential(*seq) + + def calc_gradient_penalty( + self, real_data, fake_data, device="cpu", pac=10, lambda_=10 + ): + alpha = torch.rand(real_data.size(0) // pac, 1, 1, device=device) + alpha = alpha.repeat(1, pac, real_data.size(1)) + alpha = alpha.view(-1, real_data.size(1)) + + interpolates = alpha * real_data + ((1 - alpha) * fake_data) + + disc_interpolates = self(interpolates) + + gradients = torch.autograd.grad( + outputs=disc_interpolates, + inputs=interpolates, + grad_outputs=torch.ones(disc_interpolates.size(), device=device), + create_graph=True, + retain_graph=True, + only_inputs=True, + )[0] + + gradient_penalty = ( + (gradients.view(-1, pac * real_data.size(1)).norm(2, dim=1) - 1) + ** 2 + ).mean() * lambda_ + + return gradient_penalty + + def forward(self, input): + assert input.size()[0] % self.pac == 0, f'generator batch size ({input.size()[0]}) ' \ + f'should be divisible by pac ({self.pac})' + return self.seq(input.view(-1, self.pacdim)) + + +class Residual(Module): + def __init__(self, i, o): + super(Residual, self).__init__() + self.fc = Linear(i, o) + self.bn = BatchNorm1d(o) + self.relu = ReLU() + + def forward(self, input): + out = self.fc(input) + out = self.bn(out) + out = self.relu(out) + return torch.cat([out, input], dim=1) + + +class Generator(Module): + def __init__(self, embedding_dim, generator_dim, data_dim): + super(Generator, self).__init__() + dim = embedding_dim + seq = [] + for item in list(generator_dim): + seq += [Residual(dim, item)] + dim += item + seq.append(Linear(dim, data_dim)) + self.seq = Sequential(*seq) + + def forward(self, input): + data = self.seq(input) + return data + + +class DataSampler(object): + """DataSampler samples the conditional vector and corresponding data for CTGAN.""" + + def __init__(self, data, output_info, log_frequency): + self._data = data + + def is_discrete_column(column_info): + return ( + len(column_info) == 1 + and column_info[0].activation_fn == "softmax" + ) + + n_discrete_columns = sum( + [ + 1 + for column_info in output_info + if is_discrete_column(column_info) + ] + ) + + self._discrete_column_matrix_st = np.zeros( + n_discrete_columns, dtype="int32" + ) + + # Store the row id for each category in each discrete column. + # For example _rid_by_cat_cols[a][b] is a list of all rows with the + # a-th discrete column equal value b. + self._rid_by_cat_cols = [] + + # Compute _rid_by_cat_cols + st = 0 + for column_info in output_info: + if is_discrete_column(column_info): + span_info = column_info[0] + ed = st + span_info.dim + + rid_by_cat = [] + for j in range(span_info.dim): + rid_by_cat.append(np.nonzero(data[:, st + j])[0]) + self._rid_by_cat_cols.append(rid_by_cat) + st = ed + else: + st += sum([span_info.dim for span_info in column_info]) + assert st == data.shape[1] + + # Prepare an interval matrix for efficiently sample conditional vector + max_category = max( + [ + column_info[0].dim + for column_info in output_info + if is_discrete_column(column_info) + ], + default=0, + ) + + self._discrete_column_cond_st = np.zeros( + n_discrete_columns, dtype="int32" + ) + self._discrete_column_n_category = np.zeros( + n_discrete_columns, dtype="int32" + ) + self._discrete_column_category_prob = np.zeros( + (n_discrete_columns, max_category) + ) + self._n_discrete_columns = n_discrete_columns + self._n_categories = sum( + [ + column_info[0].dim + for column_info in output_info + if is_discrete_column(column_info) + ] + ) + + st = 0 + current_id = 0 + current_cond_st = 0 + for column_info in output_info: + if is_discrete_column(column_info): + span_info = column_info[0] + ed = st + span_info.dim + category_freq = np.sum(data[:, st:ed], axis=0) + if log_frequency: + category_freq = np.log(category_freq + 1) + category_prob = category_freq / np.sum(category_freq) + self._discrete_column_category_prob[ + current_id, : span_info.dim + ] = category_prob + self._discrete_column_cond_st[current_id] = current_cond_st + self._discrete_column_n_category[current_id] = span_info.dim + current_cond_st += span_info.dim + current_id += 1 + st = ed + else: + st += sum([span_info.dim for span_info in column_info]) + + def _random_choice_prob_index(self, discrete_column_id): + probs = self._discrete_column_category_prob[discrete_column_id] + r = np.expand_dims(np.random.rand(probs.shape[0]), axis=1) + return (probs.cumsum(axis=1) > r).argmax(axis=1) + + def sample_condvec(self, batch): + """Generate the conditional vector for training. + + Returns: + cond (batch x #categories): + The conditional vector. + mask (batch x #discrete columns): + A one-hot vector indicating the selected discrete column. + discrete column id (batch): + Integer representation of mask. + category_id_in_col (batch): + Selected category in the selected discrete column. + """ + if self._n_discrete_columns == 0: + return None + + discrete_column_id = np.random.choice( + np.arange(self._n_discrete_columns), batch + ) + + cond = np.zeros((batch, self._n_categories), dtype="float32") + mask = np.zeros((batch, self._n_discrete_columns), dtype="float32") + mask[np.arange(batch), discrete_column_id] = 1 + category_id_in_col = self._random_choice_prob_index(discrete_column_id) + category_id = ( + self._discrete_column_cond_st[discrete_column_id] + + category_id_in_col + ) + cond[np.arange(batch), category_id] = 1 + + return cond, mask, discrete_column_id, category_id_in_col + + def sample_original_condvec(self, batch): + """Generate the conditional vector for generation use original frequency.""" + if self._n_discrete_columns == 0: + return None + + cond = np.zeros((batch, self._n_categories), dtype="float32") + + for i in range(batch): + row_idx = np.random.randint(0, len(self._data)) + col_idx = np.random.randint(0, self._n_discrete_columns) + matrix_st = self._discrete_column_matrix_st[col_idx] + matrix_ed = matrix_st + self._discrete_column_n_category[col_idx] + pick = np.argmax(self._data[row_idx, matrix_st:matrix_ed]) + cond[i, pick + self._discrete_column_cond_st[col_idx]] = 1 + + return cond + + def sample_data(self, n, col, opt): + """Sample data from original training data satisfying the sampled conditional vector. + + Returns: + n rows of matrix data. + """ + if col is None: + idx = np.random.randint(len(self._data), size=n) + return self._data[idx] + + idx = [] + for c, o in zip(col, opt): + idx.append(np.random.choice(self._rid_by_cat_cols[c][o])) + + return self._data[idx] + + def dim_cond_vec(self): + return self._n_categories + + def generate_cond_from_condition_column_info(self, condition_info, batch): + vec = np.zeros((batch, self._n_categories), dtype="float32") + vec_id = ( + self._discrete_column_matrix_st[ + condition_info["discrete_column_id"] + ] + + condition_info["value_id"] + ) + vec[:, vec_id] = 1 + return vec diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/__init__.py new file mode 100644 index 000000000..b0dbda317 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/base_data_transformer.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/base_data_transformer.py new file mode 100644 index 000000000..909fe7fd8 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/base_data_transformer.py @@ -0,0 +1,75 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from abc import ABC + + +class BaseDataTransformer(ABC): + """Base class for all data transformers. + The `BaseDataTransformer` provides the transformation required by + generators to transform (encode) and inverse_transform (decode) data. + It contains the `fit`, `transform`, `inverse_transform`, + and `get_metadata` functions that must be implemented by specific data + transformer objects. + """ + + def fit(self, data): + """Fits the data transform to the data. This is optional + + Args: + data (pandas.Series or cudf.Series or numpy.array or cupy.array): + Data to transform. + + Returns: + None + + """ + pass + + def transform(self, data): + """Transform the data. + + Args: + data (pandas.Series or cudf.Series or numpy.array or cupy.array): + Data to transform. + + Returns: + numpy.array: Transformed data. + """ + raise NotImplementedError() + + def fit_transform(self, data): + """Fit to the data and then return the transformed data. + + Args: + data (pandas.Series or cudf.Series or numpy.array or cupy.array): + Data to fit and transform + + Returns: + Transformed data. + """ + self.fit(data) + return self.transform(data) + + def inverse_transform(self, data): + """Reverses the transformation done on the data back to original values. + + Args: + data (pandas.Series or cudf.Series or numpy.array or cupy.array): + Data to inverse-transform. + Returns: + raw_data: inverse transformed data + + """ + raise NotImplementedError() diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/ctab_data_transformer.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/ctab_data_transformer.py new file mode 100644 index 000000000..5ec4adcb6 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/ctab_data_transformer.py @@ -0,0 +1,433 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import pandas as pd +import torch +from sklearn.mixture import BayesianGaussianMixture + +from syngen.utils.types import ColumnType +from syngen.generator.tabular.data_transformer.base_data_transformer import ( + BaseDataTransformer, +) + + +class CTABDataTransformer(BaseDataTransformer): + """ Data transformer for CTAB generator. + Adopted from: https://github.com/zhao-zilong/CTAB-GAN + + """ + def __init__( + self, categorical_columns=(), mixed_dict={}, n_clusters=10, eps=0.005 + ): + self.meta = None + self.n_clusters = n_clusters + self.eps = eps + self.categorical_columns = categorical_columns + self.mixed_columns = mixed_dict + + def get_metadata(self, train_data): + meta = [] + for index, column_name in enumerate(train_data.columns): + column = train_data.iloc[:, index] + if index in self.categorical_columns: + mapper = column.value_counts().index.tolist() + meta.append( + { + "name": index, + "type": ColumnType.CATEGORICAL, + "size": len(mapper), + "i2s": mapper, + } + ) + elif index in self.mixed_columns.keys(): + meta.append( + { + "name": index, + "type": ColumnType.MIXED, + "min": column.min(), + "max": column.max(), + "modal": self.mixed_columns[index], + } + ) + else: + meta.append( + { + "name": index, + "type": ColumnType.CONTINUOUS, + "min": column.min(), + "max": column.max(), + } + ) + return meta + + def fit(self, train_data: pd.DataFrame): + data = train_data.values + + self.meta = self.get_metadata(train_data) + model = [] + self.ordering = [] + self.output_info = [] + self.output_dim = 0 + self.components = [] + self.filter_arr = [] + for id_, info in enumerate(self.meta): + if info["type"] == ColumnType.CONTINUOUS: + gm = BayesianGaussianMixture( + self.n_clusters, + weight_concentration_prior_type="dirichlet_process", + weight_concentration_prior=0.001, + max_iter=100, + n_init=1, + random_state=42, + ) + gm.fit(data[:, id_].reshape([-1, 1])) + mode_freq = ( + pd.Series(gm.predict(data[:, id_].reshape([-1, 1]))) + .value_counts() + .keys() + ) + model.append(gm) + old_comp = gm.weights_ > self.eps + comp = [] + for i in range(self.n_clusters): + if (i in (mode_freq)) & old_comp[i]: + comp.append(True) + else: + comp.append(False) + self.components.append(comp) + self.output_info += [(1, "tanh"), (np.sum(comp), "softmax")] + self.output_dim += 1 + np.sum(comp) + + elif info["type"] == ColumnType.MIXED: + + gm1 = BayesianGaussianMixture( + self.n_clusters, + weight_concentration_prior_type="dirichlet_process", + weight_concentration_prior=0.001, + max_iter=100, + n_init=1, + random_state=42, + ) + gm2 = BayesianGaussianMixture( + self.n_clusters, + weight_concentration_prior_type="dirichlet_process", + weight_concentration_prior=0.001, + max_iter=100, + n_init=1, + random_state=42, + ) + + gm1.fit(data[:, id_].reshape([-1, 1])) + + filter_arr = [] + for element in data[:, id_]: + if element not in info["modal"]: + filter_arr.append(True) + else: + filter_arr.append(False) + + gm2.fit(data[:, id_][filter_arr].reshape([-1, 1])) + mode_freq = ( + pd.Series( + gm2.predict(data[:, id_][filter_arr].reshape([-1, 1])) + ) + .value_counts() + .keys() + ) + self.filter_arr.append(filter_arr) + model.append((gm1, gm2)) + + old_comp = gm2.weights_ > self.eps + + comp = [] + + for i in range(self.n_clusters): + if (i in (mode_freq)) & old_comp[i]: + comp.append(True) + else: + comp.append(False) + + self.components.append(comp) + + self.output_info += [ + (1, "tanh"), + (np.sum(comp) + len(info["modal"]), "softmax"), + ] + self.output_dim += 1 + np.sum(comp) + len(info["modal"]) + + else: + model.append(None) + self.components.append(None) + self.output_info += [(info["size"], "softmax")] + self.output_dim += info["size"] + + self.model = model + + def transform(self, data, ispositive=False, positive_list=None): + values = [] + mixed_counter = 0 + for id_, info in enumerate(self.meta): + current = data[:, id_] + if info["type"] == ColumnType.CONTINUOUS: + current = current.reshape([-1, 1]) + means = self.model[id_].means_.reshape((1, self.n_clusters)) + stds = np.sqrt(self.model[id_].covariances_).reshape( + (1, self.n_clusters) + ) + features = np.empty(shape=(len(current), self.n_clusters)) + if ispositive: + if id_ in positive_list: + features = np.abs(current - means) / (4 * stds) + else: + features = (current - means) / (4 * stds) + + probs = self.model[id_].predict_proba(current.reshape([-1, 1])) + n_opts = sum(self.components[id_]) + features = features[:, self.components[id_]] + probs = probs[:, self.components[id_]] + + opt_sel = np.zeros(len(data), dtype="int") + for i in range(len(data)): + pp = probs[i] + 1e-6 + pp = pp / sum(pp) + opt_sel[i] = np.random.choice(np.arange(n_opts), p=pp) + + idx = np.arange((len(features))) + features = features[idx, opt_sel].reshape([-1, 1]) + features = np.clip(features, -0.99, 0.99) + probs_onehot = np.zeros_like(probs) + probs_onehot[np.arange(len(probs)), opt_sel] = 1 + + re_ordered_phot = np.zeros_like(probs_onehot) + + col_sums = probs_onehot.sum(axis=0) + + n = probs_onehot.shape[1] + largest_indices = np.argsort(-1 * col_sums)[:n] + self.ordering.append(largest_indices) + for id, val in enumerate(largest_indices): + re_ordered_phot[:, id] = probs_onehot[:, val] + + values += [features, re_ordered_phot] + + elif info["type"] == "mixed": + + means_0 = self.model[id_][0].means_.reshape([-1]) + stds_0 = np.sqrt(self.model[id_][0].covariances_).reshape([-1]) + + zero_std_list = [] + means_needed = [] + stds_needed = [] + + for mode in info["modal"]: + if mode != -9999999: + dist = [] + for idx, val in enumerate(list(means_0.flatten())): + dist.append(abs(mode - val)) + index_min = np.argmin(np.array(dist)) + zero_std_list.append(index_min) + else: + continue + + for idx in zero_std_list: + means_needed.append(means_0[idx]) + stds_needed.append(stds_0[idx]) + + mode_vals = [] + + for i, j, k in zip(info["modal"], means_needed, stds_needed): + this_val = np.abs(i - j) / (4 * k) + mode_vals.append(this_val) + + if -9999999 in info["modal"]: + mode_vals.append(0) + + current = current.reshape([-1, 1]) + filter_arr = self.filter_arr[mixed_counter] + current = current[filter_arr] + + means = self.model[id_][1].means_.reshape((1, self.n_clusters)) + stds = np.sqrt(self.model[id_][1].covariances_).reshape( + (1, self.n_clusters) + ) + features = np.empty(shape=(len(current), self.n_clusters)) + if ispositive: + if id_ in positive_list: + features = np.abs(current - means) / (4 * stds) + else: + features = (current - means) / (4 * stds) + + probs = self.model[id_][1].predict_proba( + current.reshape([-1, 1]) + ) + + n_opts = sum(self.components[id_]) # 8 + features = features[:, self.components[id_]] + probs = probs[:, self.components[id_]] + + opt_sel = np.zeros(len(current), dtype="int") + for i in range(len(current)): + pp = probs[i] + 1e-6 + pp = pp / sum(pp) + opt_sel[i] = np.random.choice(np.arange(n_opts), p=pp) + idx = np.arange((len(features))) + features = features[idx, opt_sel].reshape([-1, 1]) + features = np.clip(features, -0.99, 0.99) + probs_onehot = np.zeros_like(probs) + probs_onehot[np.arange(len(probs)), opt_sel] = 1 + extra_bits = np.zeros([len(current), len(info["modal"])]) + temp_probs_onehot = np.concatenate( + [extra_bits, probs_onehot], axis=1 + ) + final = np.zeros( + [len(data), 1 + probs_onehot.shape[1] + len(info["modal"])] + ) + features_curser = 0 + for idx, val in enumerate(data[:, id_]): + if val in info["modal"]: + category_ = list(map(info["modal"].index, [val]))[0] + final[idx, 0] = mode_vals[category_] + final[idx, (category_ + 1)] = 1 + + else: + final[idx, 0] = features[features_curser] + final[ + idx, (1 + len(info["modal"])) : + ] = temp_probs_onehot[features_curser][ + len(info["modal"]) : + ] + features_curser = features_curser + 1 + + just_onehot = final[:, 1:] + re_ordered_jhot = np.zeros_like(just_onehot) + n = just_onehot.shape[1] + col_sums = just_onehot.sum(axis=0) + largest_indices = np.argsort(-1 * col_sums)[:n] + self.ordering.append(largest_indices) + for id, val in enumerate(largest_indices): + re_ordered_jhot[:, id] = just_onehot[:, val] + final_features = final[:, 0].reshape([-1, 1]) + values += [final_features, re_ordered_jhot] + mixed_counter = mixed_counter + 1 + + else: + self.ordering.append(None) + col_t = np.zeros([len(data), info["size"]]) + idx = list(map(info["i2s"].index, current)) + col_t[np.arange(len(data)), idx] = 1 + values.append(col_t) + + return np.concatenate(values, axis=1) + + def inverse_transform(self, data): + data_t = np.zeros([len(data), len(self.meta)]) + st = 0 + for id_, info in enumerate(self.meta): + if info["type"] == ColumnType.CONTINUOUS: + u = data[:, st] + v = data[:, st + 1 : st + 1 + np.sum(self.components[id_])] + order = self.ordering[id_] + v_re_ordered = np.zeros_like(v) + + for id, val in enumerate(order): + v_re_ordered[:, val] = v[:, id] + + v = v_re_ordered + + u = np.clip(u, -1, 1) + v_t = np.ones((data.shape[0], self.n_clusters)) * -100 + v_t[:, self.components[id_]] = v + v = v_t + st += 1 + np.sum(self.components[id_]) + means = self.model[id_].means_.reshape([-1]) + stds = np.sqrt(self.model[id_].covariances_).reshape([-1]) + p_argmax = np.argmax(v, axis=1) + std_t = stds[p_argmax] + mean_t = means[p_argmax] + tmp = u * 4 * std_t + mean_t + data_t[:, id_] = tmp + + elif info["type"] == "mixed": + + u = data[:, st] + full_v = data[ + :, + (st + 1) : (st + 1) + + len(info["modal"]) + + np.sum(self.components[id_]), + ] + order = self.ordering[id_] + full_v_re_ordered = np.zeros_like(full_v) + + for id, val in enumerate(order): + full_v_re_ordered[:, val] = full_v[:, id] + + full_v = full_v_re_ordered + mixed_v = full_v[:, : len(info["modal"])] + v = full_v[:, -np.sum(self.components[id_]) :] + + u = np.clip(u, -1, 1) + v_t = np.ones((data.shape[0], self.n_clusters)) * -100 + v_t[:, self.components[id_]] = v + v = np.concatenate([mixed_v, v_t], axis=1) + + st += 1 + np.sum(self.components[id_]) + len(info["modal"]) + means = self.model[id_][1].means_.reshape([-1]) + stds = np.sqrt(self.model[id_][1].covariances_).reshape([-1]) + p_argmax = np.argmax(v, axis=1) + + result = np.zeros_like(u) + + for idx in range(len(data)): + if p_argmax[idx] < len(info["modal"]): + argmax_value = p_argmax[idx] + result[idx] = float( + list( + map(info["modal"].__getitem__, [argmax_value]) + )[0] + ) + else: + std_t = stds[(p_argmax[idx] - len(info["modal"]))] + mean_t = means[(p_argmax[idx] - len(info["modal"]))] + result[idx] = u[idx] * 4 * std_t + mean_t + + data_t[:, id_] = result + + else: + current = data[:, st : st + info["size"]] + st += info["size"] + idx = np.argmax(current, axis=1) + data_t[:, id_] = list(map(info["i2s"].__getitem__, idx)) + + return data_t + + +class ImageTransformer(BaseDataTransformer): + def __init__(self, side): + self.height = side + + def transform(self, data): + if self.height * self.height > len(data[0]): + padding = torch.zeros( + (len(data), self.height * self.height - len(data[0])) + ).to(data.device) + data = torch.cat([data, padding], axis=1) + + return data.view(-1, 1, self.height, self.height) + + def inverse_transform(self, data): + data = data.view(-1, self.height * self.height) + + return data diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/ctgan_data_transformer.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/ctgan_data_transformer.py new file mode 100644 index 000000000..dd8b89702 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/data_transformer/ctgan_data_transformer.py @@ -0,0 +1,302 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from collections import namedtuple + +import cudf +import numpy as np +import pandas as pd +from sklearn.mixture import BayesianGaussianMixture + +from syngen.generator.tabular.transforms import OneHotEncoding +from syngen.generator.tabular.data_transformer.base_data_transformer import ( + BaseDataTransformer, +) + +SpanInfo = namedtuple("SpanInfo", ["dim", "activation_fn"]) +ColumnTransformInfo = namedtuple( + "ColumnTransformInfo", + [ + "column_name", + "column_type", + "transform", + "transform_aux", + "output_info", + "output_dimensions", + ], +) + + +class CTGANDataTransformer(BaseDataTransformer): + """Data Transformer for CTGAN. Adopted from: https://github.com/sdv-dev/CTGAN + + Model continuous columns with a BayesianGMM and normalized to a scalar + [0, 1] and a vector. + Discrete columns are encoded using a scikit-learn OneHotEncoder. + """ + + def __init__(self, max_clusters=10, weight_threshold=0.005): + """Create a data transformer. + + Args: + max_clusters (int): Maximum number of Gaussian distributions in Bayesian GMM. + weight_threshold (float): Weight threshold for a Gaussian distribution to be kept. + """ + self._max_clusters = max_clusters + self._weight_threshold = weight_threshold + + def _fit_continuous(self, column_name, raw_column_data): + """Train Bayesian GMM for continuous column.""" + gm = BayesianGaussianMixture( + n_components=self._max_clusters, + weight_concentration_prior_type="dirichlet_process", + weight_concentration_prior=0.001, + n_init=1, + ) + + gm.fit(raw_column_data.reshape(-1, 1)) + valid_component_indicator = gm.weights_ > self._weight_threshold + num_components = valid_component_indicator.sum() + + return ColumnTransformInfo( + column_name=column_name, + column_type="continuous", + transform=gm, + transform_aux=valid_component_indicator, + output_info=[ + SpanInfo(1, "tanh"), + SpanInfo(num_components, "softmax"), + ], + output_dimensions=1 + num_components, + ) + + def _fit_discrete(self, column_name, raw_column_data): + """Fit one hot encoder for discrete column.""" + ohe = OneHotEncoding() + ohe.fit(raw_column_data) + num_categories = len(ohe.dummies) + + return ColumnTransformInfo( + column_name=column_name, + column_type="discrete", + transform=ohe, + transform_aux=None, + output_info=[SpanInfo(num_categories, "softmax")], + output_dimensions=num_categories, + ) + + def get_metadata(self): + if hasattr(self, "_column_transform_info_list"): + return self._column_transform_info_list + return [] + + def fit(self, raw_data, discrete_columns=tuple()): + """Fit GMM for continuous columns and + One hot encoder for discrete columns. + + This step also counts the #columns in matrix data, + and span information. + """ + self.output_info_list = [] + self.output_dimensions = 0 + + if not isinstance(raw_data, (pd.DataFrame, cudf.DataFrame)): + self.dataframe = False + raw_data = pd.DataFrame(raw_data) + else: + self.dataframe = True + + self._column_raw_dtypes = raw_data.dtypes + + self._column_transform_info_list = [] + for column_name in raw_data.columns: + raw_column_data = raw_data[column_name].values + if not isinstance(raw_column_data, np.ndarray): + raw_column_data = raw_column_data.get() # cupy to numpy + if column_name in discrete_columns: + column_transform_info = self._fit_discrete( + column_name, raw_column_data + ) + else: + column_transform_info = self._fit_continuous( + column_name, raw_column_data + ) + + self.output_info_list.append(column_transform_info.output_info) + self.output_dimensions += column_transform_info.output_dimensions + self._column_transform_info_list.append(column_transform_info) + + def _transform_continuous(self, column_transform_info, raw_column_data): + gm = column_transform_info.transform + + valid_component_indicator = column_transform_info.transform_aux + num_components = valid_component_indicator.sum() + + means = gm.means_.reshape((1, self._max_clusters)) + stds = np.sqrt(gm.covariances_).reshape((1, self._max_clusters)) + normalized_values = ((raw_column_data - means) / (4 * stds))[ + :, valid_component_indicator + ] + component_probs = gm.predict_proba(raw_column_data)[ + :, valid_component_indicator + ] + + selected_component = np.zeros(len(raw_column_data), dtype="int") + for i in range(len(raw_column_data)): + component_porb_t = component_probs[i] + 1e-6 + component_porb_t = component_porb_t / component_porb_t.sum() + selected_component[i] = np.random.choice( + np.arange(num_components), p=component_porb_t + ) + + selected_normalized_value = normalized_values[ + np.arange(len(raw_column_data)), selected_component + ].reshape([-1, 1]) + selected_normalized_value = np.clip( + selected_normalized_value, -0.99, 0.99 + ) + + selected_component_onehot = np.zeros_like(component_probs) + selected_component_onehot[ + np.arange(len(raw_column_data)), selected_component + ] = 1 + return [selected_normalized_value, selected_component_onehot] + + def _transform_discrete(self, column_transform_info, raw_column_data): + ohe = column_transform_info.transform + return [ohe.transform(raw_column_data)] + + def transform(self, raw_data): + """Take raw data and output a matrix data.""" + if not isinstance(raw_data, (pd.DataFrame, cudf.DataFrame)): + raw_data = pd.DataFrame(raw_data) + + column_data_list = [] + for column_transform_info in self._column_transform_info_list: + column_data = raw_data[[column_transform_info.column_name]].values + if not isinstance(column_data, np.ndarray): + column_data = column_data.get() # cupy to numpy + if column_transform_info.column_type == "continuous": + column_data_list += self._transform_continuous( + column_transform_info, column_data + ) + else: + assert column_transform_info.column_type == "discrete" + column_data_list += self._transform_discrete( + column_transform_info, column_data + ) + + return np.concatenate(column_data_list, axis=1).astype(float) + + def _inverse_transform_continuous( + self, column_transform_info, column_data, sigmas, st + ): + gm = column_transform_info.transform + valid_component_indicator = column_transform_info.transform_aux + + selected_normalized_value = column_data[:, 0] + selected_component_probs = column_data[:, 1:] + + if sigmas is not None: + sig = sigmas[st] + selected_normalized_value = np.random.normal( + selected_normalized_value, sig + ) + + selected_normalized_value = np.clip(selected_normalized_value, -1, 1) + component_probs = ( + np.ones((len(column_data), self._max_clusters)) * -100 + ) + component_probs[ + :, valid_component_indicator + ] = selected_component_probs + + means = gm.means_.reshape([-1]) + stds = np.sqrt(gm.covariances_).reshape([-1]) + selected_component = np.argmax(component_probs, axis=1) + + std_t = stds[selected_component] + mean_t = means[selected_component] + column = selected_normalized_value * 4 * std_t + mean_t + + return column + + def _inverse_transform_discrete(self, column_transform_info, column_data): + ohe = column_transform_info.transform + return ohe.inverse_transform(column_data) + + def inverse_transform(self, data, sigmas=None): + """Take matrix data and output raw data. + + Output uses the same type as input to the transform function. + Either np array or pd dataframe. + """ + st = 0 + recovered_column_data_list = [] + column_names = [] + for column_transform_info in self._column_transform_info_list: + dim = column_transform_info.output_dimensions + column_data = data[:, st : st + dim] + + if column_transform_info.column_type == "continuous": + recovered_column_data = self._inverse_transform_continuous( + column_transform_info, column_data, sigmas, st + ) + else: + assert column_transform_info.column_type == "discrete" + recovered_column_data = self._inverse_transform_discrete( + column_transform_info, column_data + ) + + recovered_column_data_list.append(recovered_column_data) + column_names.append(column_transform_info.column_name) + st += dim + + recovered_data = np.column_stack(recovered_column_data_list) + recovered_data = pd.DataFrame( + recovered_data, columns=column_names + ).astype(self._column_raw_dtypes) + if not self.dataframe: + recovered_data = recovered_data.values + + return recovered_data + + def convert_column_name_value_to_id(self, column_name, value): + discrete_counter = 0 + column_id = 0 + for column_transform_info in self._column_transform_info_list: + if column_transform_info.column_name == column_name: + break + if column_transform_info.column_type == "discrete": + discrete_counter += 1 + column_id += 1 + else: + raise ValueError( + f"The column_name `{column_name}` doesn't exist in the data." + ) + + one_hot = column_transform_info.transform.transform(np.array([value]))[ + 0 + ] + + if sum(one_hot) == 0: + raise ValueError( + f"The value `{value}` doesn't exist in the column `{column_name}`." + ) + + return { + "discrete_column_id": discrete_counter, + "column_id": column_id, + "value_id": np.argmax(one_hot), + } diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/gaussian_generator.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/gaussian_generator.py new file mode 100644 index 000000000..8f74f2ce8 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/gaussian_generator.py @@ -0,0 +1,147 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pickle +from typing import Optional, List + +import cupy as cp + +import numpy as np +import pandas as pd + +from tqdm import tqdm +from pandas.api.types import is_integer_dtype +from sklearn.preprocessing import OrdinalEncoder + +from syngen.generator.tabular.chunked_tabular_generator import ChunkedBaseTabularGenerator +from syngen.generator.utils import cuda_repeat + + +class GaussianGenerator(ChunkedBaseTabularGenerator): + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def ordinal_encoder(self, cat_col): + encoder = OrdinalEncoder() + encoder.fit(cat_col) + return encoder + + def fit( + self, + data, + categorical_columns=(), + columns: Optional[List[str]] = None, + verbose: bool = False, + ): + self.column_order = columns or list(data.columns) + self.cat_fit = {} + self.categorical_columns = set(categorical_columns) + self.continuous_columns = set(self.column_order) - self.categorical_columns + num_samples = len(data) + + # - multinomial distribution + cat_cols = tqdm(self.categorical_columns) if verbose else self.categorical_columns + for column in cat_cols: + enc = self.ordinal_encoder(data[column].values.reshape(-1, 1)) + pvals = data[column].value_counts() / num_samples + pvals = pvals.values + self.cat_fit[column] = { + "encoder": enc, + "pvals": pvals, + 'dtype': data[column].dtype, + } + + self.cont_fit = {} + self.integer_continuous_columns = [] + # - gaussian distribution + cont_cols = tqdm(self.continuous_columns) if verbose else self.continuous_columns + for column in cont_cols: + mean, std = data[column].mean(), data[column].std() + self.cont_fit[column] = { + "mean": mean, + "std": std, + 'dtype': data[column].dtype, + } + if is_integer_dtype(data[column].dtype): + self.integer_continuous_columns.append(column) + self.fits = {**self.cat_fit, **self.cont_fit} + + def sample(self, n, gpu=False, memmap_kwargs=None, start_idx=0, end_idx=None, **kwargs): + + use_memmap = memmap_kwargs is not None + + if use_memmap: + memmap_outfile = np.load(memmap_kwargs['filename'], mmap_mode='r+') + + if gpu: + cont_means = [] + cont_stds = [] + + for column in self.continuous_columns: + cont_means.append(self.fits[column]['mean']) + cont_stds.append(self.fits[column]['std']) + + cont_data = cp.random.normal( + cp.array(cont_means), + cp.array(cont_stds), + size=(n, len(self.continuous_columns)), + dtype=cp.float32 + ) + cont_data = cp.asnumpy(cont_data) + df = pd.DataFrame(cont_data, columns=list(self.continuous_columns)) + if self.integer_continuous_columns: + df[self.integer_continuous_columns] = \ + df[self.integer_continuous_columns].astype(np.int32) + + for column in self.categorical_columns: + sampled_data = cp.random.multinomial(n, self.fits[column]["pvals"]) + sampled_data = cuda_repeat(sampled_data) + cp.random.shuffle(sampled_data) + sampled_data = cp.asnumpy(sampled_data.reshape(-1, 1)) + encoder = self.fits[column]["encoder"] + sampled_data = encoder.inverse_transform(sampled_data) + df[column] = sampled_data.reshape(-1).astype(self.fits[column]["dtype"]) + else: + df = pd.DataFrame() + for column in self.column_order: + if column in self.categorical_columns: + sampled_data = np.random.multinomial(n, + self.fits[column]["pvals"]) + sampled_data = np.repeat(np.arange(len(sampled_data)), sampled_data) + np.random.shuffle(sampled_data) + sampled_data = sampled_data.reshape(-1, 1) + encoder = self.fits[column]["encoder"] + sampled_data = encoder.inverse_transform(sampled_data) + else: + sampled_data = np.random.normal( + self.fits[column]['mean'], + self.fits[column]['std'], n) + df[column] = sampled_data.reshape(-1).astype(self.fits[column]["dtype"]) + + df = df[self.column_order] + + if use_memmap: + memmap_outfile[start_idx:end_idx] = df.values + return None + return df + + def save(self, path): + with open(path, 'wb') as file_handler: + pickle.dump(self, file_handler, protocol=pickle.HIGHEST_PROTOCOL) + + @classmethod + def load(cls, path): + with open(path, 'rb') as file_handler: + model = pickle.load(file_handler) + return model diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/kde_generator.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/kde_generator.py new file mode 100644 index 000000000..eb2bb59d8 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/kde_generator.py @@ -0,0 +1,161 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from tqdm import tqdm +from typing import Union, List, Optional +import pickle +import cupy as cp +import numpy as np +import pandas as pd +from sklearn.neighbors import KernelDensity +from cuml.neighbors import KernelDensity as KernelDensityGPU +from sklearn.preprocessing import OrdinalEncoder + +from syngen.generator.tabular.chunked_tabular_generator import ChunkedBaseTabularGenerator + +import warnings +warnings.simplefilter(action='http://github.com/ignore', category=pd.errors.PerformanceWarning) + + +class KDEGenerator(ChunkedBaseTabularGenerator): + def __init__(self, **kwargs): + """ + A tabular generator based on kernel density estimation. + + Categorical and continuous columns are modeled + using gaussian KDE + """ + super().__init__(**kwargs) + + def ordinal_encoder(self, cat_col): + encoder = OrdinalEncoder() + encoder.fit(cat_col) + return encoder + + def fit( + self, + data: pd.DataFrame, + categorical_columns: list = (), + samples: Union[float, int] = 0.1, + columns: Optional[List[str]] = None, + verbose: bool = False, + ): + if samples > 0: + num_samples = len(data) + if 0.0 <= samples <= 1.0: + num_samples = samples * num_samples + else: + num_samples = samples + num_samples = min(int(num_samples), 10_000_000) + data = data.sample(n=num_samples) + + self.column_order = columns or list(data.columns) + self.cat_fit = {} + self.categorical_columns = set(categorical_columns) + self.continuous_columns = set(self.column_order) - self.categorical_columns + + # - kde distribution + cat_cols = tqdm(self.categorical_columns) if verbose else self.categorical_columns + for column in cat_cols: + col_data = data[column].dropna().values.reshape(-1, 1) + enc = self.ordinal_encoder(col_data) + col_data = enc.transform(col_data).reshape(-1, 1) + kde = KernelDensity(kernel="gaussian") + kde = kde.fit(col_data) + self.cat_fit[column] = { + "encoder": enc, + "n_categories": len(enc.categories_[0]), + "sampler": kde, + 'dtype': data[column].dtype, + } + self.cont_fit = {} + # - gaussian distribution + cont_cols = tqdm(self.continuous_columns) if verbose else self.continuous_columns + for column in cont_cols: + col_data = data[column].values.reshape(-1, 1) + kde = KernelDensity(kernel="gaussian") + kde = kde.fit(col_data) + self.cont_fit[column] = { + "sampler": kde, + 'dtype': data[column].dtype, + } + self.fits = {**self.cat_fit, **self.cont_fit} + + def sample(self, n, gpu=False, memmap_kwargs=None, start_idx=0, end_idx=None, **kwargs): + + use_memmap = memmap_kwargs is not None + + if use_memmap: + memmap_outfile = np.load(memmap_kwargs['filename'], mmap_mode='r+') + + df = pd.DataFrame() + if gpu: + for column_id, column in enumerate(self.column_order): + sampler = self.fits[column]["sampler"] + + gpu_sampler = KernelDensityGPU(kernel="gaussian") + gpu_sampler.fit(np.asarray(sampler.tree_.data)) + + if "encoder" in self.fits[column]: + # - must be categorical + encoder = self.fits[column]["encoder"] + n_categories = self.fits[column]["n_categories"] + sampled_data = gpu_sampler.sample(n) + sampled_data = cp.abs(sampled_data.reshape(-1, 1)) + sampled_data = cp.round(sampled_data) + sampled_data = cp.clip(sampled_data, 0, n_categories - 1) + sampled_data = cp.asnumpy(sampled_data) + sampled_data = encoder.inverse_transform(sampled_data).reshape(-1) + else: + sampled_data = gpu_sampler.sample(n) + sampled_data = cp.asnumpy(sampled_data.reshape(-1)) + sampled_data = sampled_data.astype(self.fits[column]["dtype"]) + if use_memmap: + memmap_outfile[start_idx:end_idx, column_id] = sampled_data + else: + df[column] = sampled_data + else: + for column_id, column in enumerate(self.column_order): + sampler = self.fits[column]["sampler"] + if "encoder" in self.fits[column]: + # - must be categorical + encoder = self.fits[column]["encoder"] + n_categories = self.fits[column]["n_categories"] + sampled_data = sampler.sample(n) + sampled_data = np.abs(sampled_data.reshape(-1, 1)) + sampled_data = np.round(sampled_data) + sampled_data = np.clip(sampled_data, 0, n_categories - 1) + sampled_data = encoder.inverse_transform(sampled_data).reshape(-1) + else: + sampled_data = sampler.sample(n).reshape(-1) + sampled_data = sampled_data.astype(self.fits[column]["dtype"]) + if use_memmap: + memmap_outfile[start_idx:end_idx, column_id] = sampled_data + else: + df[column] = sampled_data + + if use_memmap: + return None + return df + + + def save(self, path): + with open(path, 'wb') as file_handler: + pickle.dump(self, file_handler, protocol=pickle.HIGHEST_PROTOCOL) + + @classmethod + def load(cls, path): + with open(path, 'rb') as file_handler: + model = pickle.load(file_handler) + return model diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/random.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/random.py new file mode 100644 index 000000000..71cbe5945 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/random.py @@ -0,0 +1,100 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Optional, List + +import cupy as cp +import pickle +import numpy as np +import pandas as pd + + +from syngen.generator.tabular.chunked_tabular_generator import ChunkedBaseTabularGenerator + +import warnings +warnings.simplefilter(action="http://github.com/ignore", category=FutureWarning) + + +class RandomMVGenerator(ChunkedBaseTabularGenerator): + """Random Multivariate Gaussian generator + """ + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.ndims = None + self.column_order = None + + def fit(self, data: Optional[pd.DataFrame] = None, ndims: Optional[int] = None, + columns: Optional[List[str]] = None, + categorical_columns=(), verbose=False): + """ + random ignores categorical columns at the moment + + """ + + assert ndims is not None or data is not None or self.ndims is not None or columns is not None + + if data is not None: + ndims = len(data.columns) + self.column_order = list(data.columns) + + if columns is not None: + self.column_order = columns + ndims = len(columns) + + if ndims is None: + ndims = self.ndims + + self.mu = np.random.randn(ndims).astype(np.float32) + self.cov = np.eye(ndims) * np.abs( + np.random.randn(ndims).reshape(-1, 1) + ).astype(np.float32) + self.ndims = ndims + + def _space_complexity_factor(self): + return 2.0 + + def sample(self, n, gpu=False, memmap_kwargs=None, start_idx=0, end_idx=None, **kwargs): + + use_memmap = memmap_kwargs is not None + + if use_memmap: + memmap_outfile = np.load(memmap_kwargs['filename'], mmap_mode='r+') + + if gpu: + samples = cp.random.multivariate_normal(self.mu, self.cov, size=n, dtype=cp.float32) + samples = cp.asnumpy(samples) + else: + samples = np.random.multivariate_normal(self.mu, self.cov, size=n).astype(np.float32) + + if use_memmap: + memmap_outfile[start_idx:end_idx] = samples + return None + else: + df = pd.DataFrame(samples) + if self.column_order is None: + df.columns = df.columns.astype(str) + else: + df.columns = self.column_order + return df + + def save(self, path): + with open(path, 'wb') as file_handler: + pickle.dump(self, file_handler, protocol=pickle.HIGHEST_PROTOCOL) + + @classmethod + def load(cls, path): + with open(path, 'rb') as file_handler: + model = pickle.load(file_handler) + return model diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/__init__.py new file mode 100644 index 000000000..dca6cca59 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .one_hot_encoding import OneHotEncoding diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/base_transform.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/base_transform.py new file mode 100644 index 000000000..adcea6de2 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/base_transform.py @@ -0,0 +1,73 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from abc import ABC + + +class BaseTransform(ABC): + """Base class for all transforms. + The `BaseTransform` class contains methods that must be implemented + by specific transforms objects. The `fit` method is optional. + """ + + def fit(self, data): + """Fits the transform on the data. + Args: + + data (pandas.Series or cudf.Series or numpy.array or cupy.array): + Data to transform. + + Returns: + None + + """ + pass + + def transform(self, data): + """Transform the data. + + Args: + + data (pandas.Series or cudf.Series or numpy.array or cupy.array): + Data to transform. + + Returns: + numpy.array: Transformed data. + """ + raise NotImplementedError() + + def fit_transform(self, data): + """Fit to the data and then return the transformed data. + + Args: + data (pandas.Series or cudf.Series or numpy.array or cupy.array): + Data to fit and transform + + Returns: + Transformed data. + """ + self.fit(data) + return self.transform(data) + + def inverse_transform(self, data): + """Reverses the transformation done on the data back to original values. + + Args: + data (pandas.Series or cudf.Series or numpy.array or cupy.array): Data to inverse-transform. + + Returns: + Inverse transformed data. + + """ + raise NotImplementedError() diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/one_hot_encoding.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/one_hot_encoding.py new file mode 100644 index 000000000..06a6e7769 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/transforms/one_hot_encoding.py @@ -0,0 +1,155 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import pandas as pd + +from syngen.generator.tabular.transforms.base_transform import BaseTransform + + +class OneHotEncoding(BaseTransform): + """OneHotEncoding for categorical data. + Adopted from: https://github.com/sdv-dev/CTGAN + + This transformer replaces a single vector with N unique categories in it + with N vectors which have 1s on the rows where the corresponding category + is found and 0s on the rest. + + Null values are considered just another category. + + Args: + error_on_unknown (bool): + If a value that was not seen during the fit stage is passed to + transform, then an error will be raised if this is True. + """ + + dummies = None + _dummy_na = None + _num_dummies = None + _dummy_encoded = False + _indexer = None + _uniques = None + + def __init__(self, error_on_unknown=True): + self.error_on_unknown = error_on_unknown + + @staticmethod + def _prepare_data(data): + """Convert data to appropriate format. + + If data is a valid list or a list of lists, + transforms it into an np.array, otherwise returns it. + + Args: + data (pandas.Series, numpy.ndarray, list or list of lists): + Data to prepare. + + Returns: + pandas.Series or numpy.ndarray + """ + if isinstance(data, list): + data = np.array(data) + + if len(data.shape) > 2: + raise ValueError("Unexpected format.") + if len(data.shape) == 2: + if data.shape[1] != 1: + raise ValueError("Unexpected format.") + + data = data[:, 0] + + return data + + def _transform(self, data): + if self._dummy_encoded: + coder = self._indexer + codes = pd.Categorical(data, categories=self._uniques).codes + else: + coder = self._uniques + codes = data + + rows = len(data) + dummies = np.broadcast_to(coder, (rows, self._num_dummies)) + coded = np.broadcast_to(codes, (self._num_dummies, rows)).T + array = (coded == dummies).astype(int) + + if self._dummy_na: + null = np.zeros((rows, 1), dtype=int) + null[pd.isnull(data)] = 1 + array = np.append(array, null, axis=1) + + return array + + def fit(self, data): + """Fit the transformer to the data. + + Get the pandas `dummies` which will be used later on for OneHotEncoding. + + Args: + data (pandas.Series, numpy.ndarray, list or list of lists): + Data to fit the transformer to. + """ + data = self._prepare_data(data) + + null = pd.isnull(data) + self._uniques = list(pd.unique(data[~null])) + self._dummy_na = null.any() + self._num_dummies = len(self._uniques) + self._indexer = list(range(self._num_dummies)) + self.dummies = self._uniques.copy() + + if not np.issubdtype(data.dtype, np.number): + self._dummy_encoded = True + + if self._dummy_na: + self.dummies.append(np.nan) + + def transform(self, data): + """Replace each category with the OneHot vectors. + + Args: + data (pandas.Series, numpy.ndarray, list or list of lists): + Data to transform. + + Returns: + numpy.ndarray: + """ + data = self._prepare_data(data) + array = self._transform(data) + + if self.error_on_unknown: + unknown = array.sum(axis=1) == 0 + if unknown.any(): + raise ValueError( + f"Attempted to transform {list(data[unknown])} ", + "that were not seen during fit stage.", + ) + + return array + + def inverse_transform(self, data): + """Convert float values back to the original categorical values. + + Args: + data (numpy.ndarray): + Data to revert. + + Returns: + pandas.Series + """ + if data.ndim == 1: + data = data.reshape(-1, 1) + + indices = np.argmax(data, axis=1) + return pd.Series(indices).map(self.dummies.__getitem__) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/uniform_generator.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/uniform_generator.py new file mode 100644 index 000000000..870387b7c --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/uniform_generator.py @@ -0,0 +1,160 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from functools import partial +import pickle +from typing import Optional, List, Union +from tqdm import tqdm + +import cupy as cp +import numpy as np +import pandas as pd +from sklearn.preprocessing import OrdinalEncoder +from pandas.api.types import is_integer_dtype + +from syngen.generator.tabular.chunked_tabular_generator import ChunkedBaseTabularGenerator + + +class UniformGenerator(ChunkedBaseTabularGenerator): + """Uniform random feature generator. + """ + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + def ordinal_encoder(self, cat_col): + encoder = OrdinalEncoder() + encoder.fit(cat_col) + return encoder + + def fit( + self, + data, + categorical_columns=(), + samples: Union[float, int] = 0.1, + columns: Optional[List[str]] = None, + verbose: bool = False, + ): + """Computes the min and max ranges of the columns. + + Args: + data: input data to use for extracting column statistics + categorical_columns (list): list of columns that should be treated as categorical. + verbose (bool): print intermediate results (default: False) + """ + + if samples > 0: + num_samples = len(data) + if 0.0 <= samples <= 1.0: + num_samples = samples * num_samples + else: + num_samples = samples + num_samples = min(int(num_samples), 10_000_000) + data = data.sample(n=num_samples) + + self.column_order = columns or list(data.columns) + self.cat_fit = {} + self.categorical_columns = set(categorical_columns) + self.continuous_columns = set(self.column_order) - self.categorical_columns + + cat_cols = tqdm(self.categorical_columns) if verbose else self.categorical_columns + for column in cat_cols: + enc = self.ordinal_encoder(data[column].values.reshape(-1, 1)) + n_unique = len(enc.categories_[0]) + self.cat_fit[column] = { + "encoder": enc, + "n_unique": n_unique, + "sampler": partial(np.random.randint, 0, n_unique), + 'dtype': data[column].dtype, + } + + self.cont_fit = {} + self.integer_continuous_columns = [] + cont_cols = tqdm(self.continuous_columns) if verbose else self.continuous_columns + for column in cont_cols: + min_, max_ = data[column].min(), data[column].max() + self.cont_fit[column] = { + "min": min_, + "max": max_, + "sampler": partial(np.random.uniform, min_, max_), + 'dtype': data[column].dtype, + } + if is_integer_dtype(data[column].dtype): + self.integer_continuous_columns.append(column) + self.fits = {**self.cat_fit, **self.cont_fit} + + def sample(self, n, gpu=False, memmap_kwargs=None, start_idx=0, end_idx=None, **kwargs): + + use_memmap = memmap_kwargs is not None + + if use_memmap: + memmap_outfile = np.load(memmap_kwargs['filename'], mmap_mode='r+') + + if gpu: + cont_min = [] + cont_max = [] + + for column in self.continuous_columns: + cont_min.append(self.fits[column]['min']) + cont_max.append(self.fits[column]['max']) + + cont_data = cp.random.uniform( + cp.array(cont_min), + cp.array(cont_max), + size=(n, len(self.continuous_columns)), + dtype=cp.float32 + ) + cont_data = cp.asnumpy(cont_data) + df = pd.DataFrame(cont_data, columns=list(self.continuous_columns)) + if self.integer_continuous_columns: + df[self.integer_continuous_columns] = \ + df[self.integer_continuous_columns].astype(np.int32) + + for column in self.categorical_columns: + sampled_data = cp.random.randint(0, self.fits[column]["n_unique"], size=n, dtype=cp.int32) + sampled_data = cp.asnumpy(sampled_data.reshape(-1, 1)) + encoder = self.fits[column]["encoder"] + sampled_data = encoder.inverse_transform(sampled_data) + df[column] = sampled_data.reshape(-1).astype(self.fits[column]["dtype"]) + + else: + df = pd.DataFrame() + for column in self.column_order: + sampler = self.fits[column]["sampler"] + sampled_data = sampler(n) + sampled_data = sampled_data.reshape(-1, 1) + if "encoder" in self.fits[column]: + encoder = self.fits[column]["encoder"] + sampled_data = encoder.inverse_transform(sampled_data) + df[column] = sampled_data.reshape(-1).astype(self.fits[column]["dtype"]) + + df = df[self.column_order] + + if use_memmap: + memmap_outfile[start_idx:end_idx] = df.values + return None + return df + + def _space_complexity_factor(self): + return 2.5 + + def save(self, path): + with open(path, 'wb') as file_handler: + pickle.dump(self, file_handler, protocol=pickle.HIGHEST_PROTOCOL) + + @classmethod + def load(cls, path): + with open(path, 'rb') as file_handler: + model = pickle.load(file_handler) + return model diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/utils.py new file mode 100644 index 000000000..bccbae443 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/tabular/utils.py @@ -0,0 +1,137 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import gc +import multiprocessing +from functools import partial +from typing import Callable, List + +from tqdm import tqdm + +from syngen.generator.tabular.chunked_tabular_generator import ChunkedBaseTabularGenerator +from syngen.utils.io_utils import dump_dataframe +from syngen.utils.memory_manager import MemoryManager + + +def _generate_samples( + gen, + n_samples: int, + fname: str, + save_path: str, + post_gen_fn: Callable = None, + i: int = 0, +): + """ + MP sample generation fn + """ + fp = os.path.join(save_path, f"{fname}_{i}") + samples = gen.sample(n_samples) + if post_gen_fn is not None: + samples = post_gen_fn(samples) + dump_dataframe(samples, fp, format='parquet') + return fp + + +def pass_through(x): + return x + + +def tabular_chunk_sample_generation( + gen, + n_samples: int, + save_path: str, + fname: str, + post_gen_fn: Callable = pass_through, + num_workers: int = 1, + use_memmap=False, + verbose=True, +) -> List[str]: + """ + Chunk large sample generation into parts, + and dump csv files into save_path to avoid memory issues. + + Args: + gen: generator to sample new synthetic data from, + must implement `sample` + n_samples (int): number of samples to generate + save_path: directory to dump generated samples + fname (str): file name for saving csv's + post_gen_fn (Callable): will be called on generated samples + num_workers (int): number of workers to speed up generation using multiprocessing + Returns: + None + """ + + if isinstance(gen, ChunkedBaseTabularGenerator): + return gen.chunked_sampling(int(n_samples), + save_path=save_path, + fname=fname, + gpus=-1, + use_memmap=use_memmap, + verbose=verbose, + ) + + n_samples = int(n_samples) + # - check if mem available + gc.collect() + mem_avail = MemoryManager().get_available_virtual_memory() + emp_n = 1000 + est_samples = gen.sample(emp_n) + mem_usage = est_samples.memory_usage(index=True, deep=True).sum() + est_mem = (mem_usage / emp_n) * n_samples + + # - path + file_paths = [] + + # - gen samples + if n_samples <= 1e6 and mem_avail > est_mem: + file_paths.append( + _generate_samples( + gen=gen, + n_samples=n_samples, + fname=fname, + save_path=save_path, + post_gen_fn=post_gen_fn, + i=n_samples, + ) + ) + else: + r = (est_mem // mem_avail) + 10 + inc = int(min(n_samples // r, 5e6)) + num_iters = n_samples / inc + if num_iters - n_samples // inc > 0.0: + num_iters += 1 + num_iters = int(num_iters) + + generate_samples_p = partial( + _generate_samples, gen, inc, fname, save_path, post_gen_fn + ) + if num_workers > 1: + multiprocessing.set_start_method("spawn", force=True) + with multiprocessing.Pool(processes=num_workers) as pool: + tasks = pool.imap_unordered(generate_samples_p, range(0, num_iters)) + + if verbose: + tasks = tqdm(tasks, total=num_iters) + + file_paths = list(tasks) + else: + itr = range(0, n_samples, inc) + if verbose: + itr = tqdm(itr) + for i in itr: + file_paths.append(generate_samples_p(i)) + + return file_paths diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/utils.py new file mode 100644 index 000000000..68dadcc16 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/generator/utils.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import cupy as cp +from numba import cuda + + +WARP_SIZE = 32 # could be 32 or 64 + + +@cuda.jit +def repeat_kernel(repeat_ptr, cumsum_ptr, res, size): + idx = cuda.grid(1) + stride = cuda.gridsize(1) / WARP_SIZE + warp_id = idx / WARP_SIZE + tid_in_warp = idx % WARP_SIZE + + for i in range(warp_id, size, stride): + end = cumsum_ptr[i] + repeat = repeat_ptr[i] + start = end - repeat + + for j in range(start + tid_in_warp, end, WARP_SIZE): + res[j] = i + + +def cuda_repeat(repeats): + cumsum = repeats.cumsum(0) + total = cumsum[-1].item() + size = len(repeats) + block = 512 + warps_per_block = block // WARP_SIZE + grid = max((size + warps_per_block - 1) // warps_per_block, 2048) + res = cp.empty(total, dtype=repeats.dtype) + repeat_kernel[grid, block](repeats, cumsum, res, size) + cuda.synchronize() + return res diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/__init__.py new file mode 100644 index 000000000..7dda8469a --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/__init__.py @@ -0,0 +1,21 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from syngen.graph_aligner.base_graph_aligner import BaseGraphAligner +from syngen.graph_aligner.xgboost_aligner import XGBoostAligner + +aligner_classes = { + 'xgboost': XGBoostAligner, +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/base_graph_aligner.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/base_graph_aligner.py new file mode 100644 index 000000000..fef51ffcd --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/base_graph_aligner.py @@ -0,0 +1,56 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import abc + + +class BaseGraphAligner(abc.ABC): + """Base class for all graph alignment objects""" + + @classmethod + def get_aligners(cls, include_parents=True): + """Recursively find sublcasses of `BaseGraphAligner` + + Args: + include_parents (bool): whether to include parents to other classes. + (default: `True`) + """ + + aligners = dict() + for child in cls.__subclasses__(): + children = child.get_aligners(include_parents) + aligners.update(children) + + if include_parents or not children: + if abc.ABC not in child.__bases__: + aligners[child.__name__] = child + return aligners + + def fit(self, *args, **kwargs) -> None: + """function to fit aligner required to be implemented by aligners""" + + raise NotImplementedError() + + def align(self, *args, **kwargs): + """align function to align generated graph and generated features, + required to be implemented by aligners + """ + raise NotImplementedError() + + def save(self, path): + raise NotImplementedError() + + @classmethod + def load(cls, path): + raise NotImplementedError() diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/utils.py new file mode 100644 index 000000000..10f91574b --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/utils.py @@ -0,0 +1,187 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +from pathlib import Path, PosixPath +from typing import List, Union + +import cudf +import cupy +import pandas as pd +import torch +from tqdm import tqdm + +from syngen.utils.types import ColumnType +from syngen.utils.cugraph import import_cugraph + + +def get_graph(df: cudf.DataFrame, http://github.com/src="src", dst="dst"): + """Construct directed graph + + Args: + df (DataFrameType): dataframe containing edge info + src (str): source node column name + dst (str): destination node column name + + Returns: + `cugraph.DiGraph` + """ + cugraph = import_cugraph() + graph = cugraph.DiGraph() + graph.from_cudf_edgelist(df, source=src, destination=dst) + return graph + + +def merge_dfs(dfs, **kwargs): + """merge a list of dataframes on a particular column + + Args: + dfs (DataFrame): list of dataframes to merge on + kwargs (dict): key-word arguments to pass to DataFrame `merge` function + """ + if "on" not in kwargs: + kwargs["on"] = "vertex" + if "how" not in kwargs: + kwargs["how"] = "outer" + + df = dfs[0] + for i in range(1, len(dfs)): + df = df.merge(dfs[i], **kwargs) + return df + + +def get_features( + df, + G, + src: str = "src", + dst: str = "dst", + pagerank_kwargs: dict = {"tol": 1e-4}, +): + """Extract structural features from graph `G` + features extracted: katz_centrality, out degree, pagerank + + Args: + df (cudf.DataFrame): data containg edge list informatoin + G (cugraph.DiGraph): cuGraph graph descriptor containing connectivity information + from df. + src (str): source node column name. + dst (dst): destination node column name. + pagerank_kwargs (dict): page rank function arguments to pass. + """ + # - pagerank feat + cugraph = import_cugraph() + + pr_df = cugraph.pagerank(G, **pagerank_kwargs) + # - out-degree feat + degree_src_df = df.groupby(src).count() + degree_src_df = degree_src_df.reset_index().rename( + columns={src: "vertex", dst: "out_degree"} + ) + + # - in-degree feat + degree_dst_df = df.groupby(dst).count() + degree_dst_df = degree_dst_df.reset_index().rename( + columns={dst: "vertex", src: "in_degree"} + ) + + # - katz feat + katz_df = cugraph.katz_centrality(G, tol=1e-2, alpha=1e-3) + + return [pr_df, degree_src_df, degree_dst_df, katz_df] + + +def merge_graph_vertex_feat(old, new): + if old is None: + return new + merged_df = old.merge(new, on=['vertex'], how='outer') + merged_df = merged_df.fillna(0) + return merged_df + + +def chunk_pd_save( + df: pd.DataFrame, + save_path: Union[str, PosixPath], + chunk_size: Union[int, float], +): + """Chunks a large dataframe and casts to a cudf for faster save + + Args: + df (pdDataFrame): dataframe object to dump data + save_path (str): data path to dump chunks + chunk_size (int): size of the chunks + """ + + save_path = Path(save_path) + num_rows = len(df) + + if not save_path.exists(): + os.makedirs(save_path) + + if chunk_size > 0.0 <= 1.0: + chunk_size = int(num_rows * chunk_size) + else: + chunk_size = int(chunk_size) + + for i in tqdm(range(num_rows // chunk_size - 1)): + chunk_df = df.iloc[i * chunk_size : (i + 1) * chunk_size] + chunk_cudf = cudf.from_pandas(chunk_df) + chunk_cudf.to_parquet(save_path / f"{i}_chunk.parquet", index=False) + + +def z_norm(series, meta=None, compute=False): + """applies z-normalization (x - mu) / std""" + if meta: + mean = meta["mean"] + std = meta["std"] + else: + mean = series.mean() + std = series.std() + + out = (series - mean) / std + return out, {"mean": mean, "std": std} + + +def categorify(series, meta=None, compute=False): + """Converts categorical to ordinal""" + cat_codes = series.astype("category").cat.codes + return cat_codes, {} + + +def get_preproc_fn(name: str): + """Preprocessing map function""" + PREPROC_FN_MAP = {"z_norm": z_norm, "categorify": categorify} + return PREPROC_FN_MAP[name] + + +def get_preproc_dict(feature_types: dict): + """Apply preprocessing functions to each column type specified in `feature_types` """ + preproc_dict = {} + for feat, type_ in feature_types.items(): + if type_ == ColumnType.CONTINUOUS: + preproc_dict[feat] = {"type": type_, "preproc": "z_norm"} + elif type_ == ColumnType.CATEGORICAL: + preproc_dict[feat] = {"type": type_, "preproc": "categorify"} + return preproc_dict + + +def spread_ranks(ranks): + vals = cupy.unique(ranks) + rr = 0 + for v in vals: + m = ranks == v + num_v = cupy.sum(m) + idx_range = cupy.arange(0, cupy.sum(m)) + ranks[m] = ranks[m] + idx_range + rr + rr += num_v + return ranks diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/xgboost_aligner.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/xgboost_aligner.py new file mode 100644 index 000000000..1430c513f --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/graph_aligner/xgboost_aligner.py @@ -0,0 +1,573 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pickle +import logging +import os +import warnings +from collections import defaultdict +from pathlib import PosixPath +from typing import Dict, Union, Literal + +import cudf +import cupy +import numpy as np +import pandas as pd +import xgboost + +try: + from cuml.preprocessing import LabelEncoder + from pylibraft.random import rmat # rmat needs to be imported before cuml +except ImportError: + from sklearn.preprocessing import OrdinalEncoder as LabelEncoder + +from syngen.graph_aligner.base_graph_aligner import BaseGraphAligner +from syngen.graph_aligner.utils import ( + get_graph, + get_preproc_dict, + get_preproc_fn, + merge_dfs, + spread_ranks, merge_graph_vertex_feat, +) + +from syngen.graph_aligner.utils import get_features as default_features + + +from syngen.utils.types import ColumnType, DataFrameType, MetaData +from syngen.utils.utils import df_to_cudf, df_to_pandas + +# - suppress numba in debug mode +numba_logger = logging.getLogger("numba") +numba_logger.setLevel(logging.WARNING) + +warnings.filterwarnings('ignore') + + +class XGBoostAligner(BaseGraphAligner): + """Aligns two graphs via correlating structural graph features + and tabular features using a xgboost predictor. + + Args: + xgboost_params: `dict` + key-value parameters to pass to `xgboost.train`. To use + different parameters for each feature pass a + `dict` of `dict` corresponding to each feature, + with keys as the feature name and values as the xgboost_params. + num_boost_round: `dict` or int + number of boosting rounds for xgboost. The same `num_boost_round` + is used for all features unless a `dict` with keys as feature name + and values as `num_boost_round` is passed. + batch_size: int + the size of the chunk during the alignment process + topk: int + the number of candidates with the highest ranks to be chosen from during alignment + """ + + def __init__( + self, + xgboost_params: Union[Dict[str, dict], dict] = { + "learning_rate": 0.1, + "colsample_bytree": 0.3, + "max_depth": 5, + "n_estimators": 100, + "alpha": 10, + "tree_method": "gpu_hist", + }, + num_boost_round: Union[Dict[str, int], int] = 10, + batch_size: int = 100000, + topk: int = 4, + get_features=default_features, + verbose=False, + **kwargs, + ): + self.xgboost_params = xgboost_params + self.num_boost_round = num_boost_round + self.batch_size = batch_size + self.topk = topk + + self.col_maps_edge = None + self.col_maps_node = None + self.get_features = get_features + self.verbose = verbose + self.xgboost_params['verbosity'] = int(xgboost_params.get('verbosity', self.verbose)) + self.xgboost_params['silent'] = int(xgboost_params.get('silent', not self.verbose)) + + self.features_to_correlate_edge = None + self.features_to_correlate_node = None + self.col_maps_edge = None + self.col_maps_node = None + self.meta_dict_edge = None + self.meta_dict_node = None + + self.edge_trained_models = None + self.node_trained_models = None + + def _extract_structural_features(self, graphs): + structural_features = {} + + for graph_name, graph_info in graphs.items(): + is_hetero = graph_info[MetaData.SRC_NODE_TYPE] != graph_info[MetaData.DST_NODE_TYPE] + if is_hetero: + offset = graph_info['src_size'] + 10 + graph_info[MetaData.STRUCTURE_DATA][:, 1] = graph_info[MetaData.STRUCTURE_DATA][:, 1] + offset + + edge_list_df = cudf.DataFrame(graph_info[MetaData.STRUCTURE_DATA], columns=["src", "dst"]) + graph = get_graph(edge_list_df, http://github.com/src="src", dst="dst").to_undirected() + + graph_feat_dfs = self.get_features(edge_list_df, graph, http://github.com/src="src", dst="dst") + graph_feat_df = merge_dfs(graph_feat_dfs, on="vertex") + graph_feat_df = graph_feat_df.fillna(0) + + if is_hetero: + src_nodes = graph_feat_df['vertex'] <= graph_info['src_size'] + structural_features[graph_info[MetaData.SRC_NODE_TYPE]] = merge_graph_vertex_feat( + structural_features.get(graph_info[MetaData.SRC_NODE_TYPE]), + graph_feat_df.loc[src_nodes]) + + dst_nodes = graph_feat_df['vertex'] > graph_info['src_size'] + dst_graph_feat_df = graph_feat_df.loc[dst_nodes] + dst_graph_feat_df["vertex"] -= offset + structural_features[graph_info[MetaData.DST_NODE_TYPE]] = merge_graph_vertex_feat( + structural_features.get(graph_info[MetaData.DST_NODE_TYPE]), + dst_graph_feat_df) + graph_info[MetaData.STRUCTURE_DATA][:, 1] = graph_info[MetaData.STRUCTURE_DATA][:, 1] - offset + else: + structural_features[graph_info[MetaData.SRC_NODE_TYPE]] = merge_graph_vertex_feat( + structural_features.get(graph_info[MetaData.SRC_NODE_TYPE]), graph_feat_df) + for _, df in structural_features.items(): + df['vertex'] = df['vertex'].values.astype(int) + df.set_index('vertex', inplace=True) + return structural_features + + def fit( + self, + graphs, + node_features, + edge_features, + **kwargs, + ): + structural_features = self._extract_structural_features(graphs) + self._fit_node(node_features, structural_features) + self._fit_edge(edge_features, structural_features, graphs) + + def _fit_edge( + self, + edge_features, + structural_features, + graphs + ): + self.features_to_correlate_edge = {} + self.edge_trained_models = {} + self.col_maps_edge = {} + self.meta_dict_edge = {} + + for edge_name, edge_features_data in edge_features.items(): + self.features_to_correlate_edge[edge_name] = {} + cat_cols = edge_features_data[MetaData.CATEGORICAL_COLUMNS] + cont_columns = list(set(edge_features_data[MetaData.FEATURES_LIST]) - set(cat_cols)) + for c in cat_cols: + self.features_to_correlate_edge[edge_name][c] = MetaData.CATEGORICAL + for c in cont_columns: + self.features_to_correlate_edge[edge_name][c] = MetaData.CONTINUOUS + + self.meta_dict_edge[edge_name] = defaultdict(None) + preproc_dict = get_preproc_dict(self.features_to_correlate_edge[edge_name]) + + for feat, v in preproc_dict.items(): + preproc_fn = get_preproc_fn(v["preproc"]) + edge_features_data[MetaData.FEATURES_DATA][feat], meta = \ + preproc_fn(edge_features_data[MetaData.FEATURES_DATA][feat]) + self.meta_dict_edge[feat] = meta + + graph_info = graphs[edge_name] + + edge_list = graph_info[MetaData.STRUCTURE_DATA] + src_ids = edge_list[:, 0] + dst_ids = edge_list[:, 1] + + src_struct_feat = structural_features[graph_info[MetaData.SRC_NODE_TYPE]].loc[src_ids].values + dst_struct_feat = structural_features[graph_info[MetaData.DST_NODE_TYPE]].loc[dst_ids].values + + X_train = np.concatenate([src_struct_feat, dst_struct_feat], axis=1).astype(float) + + self.edge_trained_models[edge_name] = {} + self.col_maps_edge[edge_name] = {} + + edge_features_df = cudf.DataFrame.from_pandas(edge_features_data[MetaData.FEATURES_DATA]) + + for col_name, col_type in self.features_to_correlate_edge[edge_name].items(): + if col_name in self.xgboost_params: + xgboost_params = dict(self.xgboost_params[col_name]) + else: + xgboost_params = dict(self.xgboost_params) + y_train = edge_features_df[col_name] + + if "objective" not in xgboost_params: + if col_type == ColumnType.CONTINUOUS: + xgboost_params["objective"] = "reg:squarederror" + elif col_type == ColumnType.CATEGORICAL: + xgboost_params["objective"] = "multi:softmax" + vals = edge_features_df[col_name] + encoder = LabelEncoder() + encoder.fit(vals) + self.col_maps_edge[edge_name][col_name] = encoder + num_classes = len(encoder.classes_) + xgboost_params["num_class"] = num_classes + y_train = encoder.transform(y_train) + y_train = y_train.values + dtrain = xgboost.DMatrix(X_train, y_train) + # - train the model + trained_model = xgboost.train( + xgboost_params, + dtrain, + num_boost_round=self.num_boost_round, + evals=[(dtrain, "train")], + verbose_eval=self.verbose, + ) + self.edge_trained_models[edge_name][col_name] = trained_model + + def _fit_node( + self, + node_features, + structural_features + ): + self.features_to_correlate_node = {} + self.node_trained_models = {} + self.col_maps_node = {} + self.meta_dict_node = {} + + # fit nodes + for node_name, node_features_data in node_features.items(): + self.features_to_correlate_node[node_name] = {} + cat_cols = node_features_data[MetaData.CATEGORICAL_COLUMNS] + cont_columns = list(set(node_features_data[MetaData.FEATURES_LIST]) - set(cat_cols)) + + for c in cat_cols: + self.features_to_correlate_node[node_name][c] = MetaData.CATEGORICAL + for c in cont_columns: + self.features_to_correlate_node[node_name][c] = MetaData.CONTINUOUS + + self.meta_dict_node[node_name] = defaultdict(None) + + preproc_dict = get_preproc_dict(self.features_to_correlate_node[node_name]) + + for feat, v in preproc_dict.items(): + preproc_fn = get_preproc_fn(v["preproc"]) + node_features_data[MetaData.FEATURES_DATA][feat], meta = \ + preproc_fn(node_features_data[MetaData.FEATURES_DATA][feat]) + self.meta_dict_node[feat] = meta + + nodes = structural_features[node_name].index.values.astype(int) + node_struct_feat = structural_features[node_name].loc[nodes].values + X_train = node_struct_feat.astype(float) + + self.node_trained_models[node_name] = {} + self.col_maps_node[node_name] = {} + + node_features_df = cudf.DataFrame.from_pandas(node_features_data[MetaData.FEATURES_DATA]) + + for col_name, col_type in self.features_to_correlate_node[node_name].items(): + if col_name in self.xgboost_params: + xgboost_params = dict(self.xgboost_params[col_name]) + else: + xgboost_params = dict(self.xgboost_params) + + y_train = node_features_df[col_name].loc[nodes] + + if "objective" not in xgboost_params: + if col_type == ColumnType.CONTINUOUS: + xgboost_params["objective"] = "reg:squarederror" + elif col_type == ColumnType.CATEGORICAL: + xgboost_params["objective"] = "multi:softmax" + vals = node_features_df[col_name].loc[nodes] + encoder = LabelEncoder() + encoder.fit(vals) + self.col_maps_node[node_name][col_name] = encoder + num_classes = len(encoder.classes_) + xgboost_params["num_class"] = num_classes + y_train = encoder.transform(y_train) + y_train = y_train.values + + dtrain = xgboost.DMatrix(X_train, y_train) + trained_model = xgboost.train( + xgboost_params, + dtrain, + num_boost_round=self.num_boost_round, + evals=[(dtrain, "train")], + verbose_eval=self.verbose, + ) + self.node_trained_models[node_name][col_name] = trained_model + + def align( + self, + graphs, + node_features, + edge_features, + ) -> pd.DataFrame: + + structural_features = self._extract_structural_features(graphs) + for k, v in structural_features.items(): + structural_features[k] = df_to_pandas(v) + + res = { + MetaData.NODES: {}, + MetaData.EDGES: {}, + } + if self.features_to_correlate_node: + res[MetaData.NODES] = self._align( + structural_features, + node_features, + None, + self.features_to_correlate_node, + self.col_maps_node, + self.node_trained_models, + MetaData.NODES, + ) + + if self.features_to_correlate_edge: + res[MetaData.EDGES] = self._align( + structural_features, + edge_features, + graphs, + self.features_to_correlate_edge, + self.col_maps_edge, + self.edge_trained_models, + MetaData.EDGES, + ) + + return res + + def _align( + self, + structural_features, + tab_features, + graphs, + features_to_correlate_part, + col_maps, + trained_models: Dict[str, xgboost.Booster], + part: Literal[MetaData.NODES, MetaData.EDGES], + ) -> Dict[str, pd.DataFrame]: + result_dict = {} + for part_name, features_to_correlate in features_to_correlate_part.items(): + preproc_dict = get_preproc_dict(features_to_correlate) + + if part == MetaData.NODES: + split_df = structural_features[part_name] + elif part == MetaData.EDGES: + split_df = graphs[part_name][MetaData.STRUCTURE_DATA] + else: + raise ValueError(f"Only `{MetaData.NODES}` and `{MetaData.EDGES}` parts expected, got ({part})") + + topk = min(len(split_df), self.topk) + + batch_size = self.batch_size + if len(split_df) // batch_size == 0: + batch_size = len(split_df) + chunks = np.array_split(split_df, len(split_df) // batch_size) + + all_preds = [] + + for chunk in chunks: + if part == MetaData.NODES: + node_feat = chunk.values + X_test = node_feat.astype(float) + dtest = xgboost.DMatrix(X_test) + elif part == MetaData.EDGES: + src_ids = chunk[:, 0] + dst_ids = chunk[:, 1] + src_struct_feat = structural_features[graphs[part_name][MetaData.SRC_NODE_TYPE]].loc[src_ids].values + dst_struct_feat = structural_features[graphs[part_name][MetaData.DST_NODE_TYPE]].loc[dst_ids].values + X_test = np.concatenate([src_struct_feat, dst_struct_feat], axis=1).astype(float) + dtest = xgboost.DMatrix(X_test) + + col_preds = [] + for col_name, col_type in features_to_correlate.items(): + preds = trained_models[part_name][col_name].predict(dtest) + col_preds.append(preds.reshape(-1, 1)) + col_preds = np.concatenate(col_preds, axis=1) + all_preds.append(col_preds) + + all_preds = np.concatenate(all_preds, axis=0) + all_preds = cupy.asarray(all_preds) + + target_cols = list(features_to_correlate.keys()) + y_generated = [] + + for col_name, col_type in features_to_correlate.items(): + preproc_fn = None + if preproc_dict: + try: + preproc_fn = get_preproc_fn( + preproc_dict[col_name]["preproc"] + ) + except: + pass + y = tab_features[part_name][col_name] + if preproc_fn is not None: + y, _ = preproc_fn(y) + if col_type == ColumnType.CATEGORICAL: + y = col_maps[part_name][col_name].inverse_transform(y) + y_generated.append(cudf.Series(y)) + + y_generated = cudf.concat(y_generated, axis=1).values + ranks = cupy.zeros((len(split_df), 1)) + if len(target_cols) == 1: + y_generated = y_generated.reshape(-1) + target_col = target_cols[0] + col_type = features_to_correlate[target_col] + + if col_type == ColumnType.CATEGORICAL: + all_preds = col_maps[part_name][target_col].inverse_transform( + cudf.Series(all_preds) + ) + all_preds = all_preds.values + unique_preds = cupy.unique(all_preds) + unique_preds = cupy.asnumpy(unique_preds) + unique_generated = cupy.unique(y_generated) + present_unique = [ + up for up in unique_preds if up in unique_generated + ] + idxs = cupy.arange(0, len(y_generated)) + pred_assigned = cupy.zeros(len(all_preds), dtype="bool") + gen_assigned = cupy.zeros(len(y_generated), dtype="bool") + unassigned_idxs_pred = [] + + for up in present_unique: + sel_idxs = idxs[y_generated == up] + cupy.random.shuffle(sel_idxs) + ups_mask = (all_preds == up).squeeze() + num_ups = cupy.sum(ups_mask) + + if len(sel_idxs) > num_ups: + r_idxs = sel_idxs[:num_ups] + ranks[ups_mask] = r_idxs.reshape(-1, 1) + pred_assigned[ups_mask] = True + gen_assigned[sel_idxs[:num_ups]] = True + else: + r_idxs = cupy.where(ups_mask)[0] + ra_idxs = r_idxs[: len(sel_idxs)] + ranks[ra_idxs] = sel_idxs.reshape(-1, 1) + ups_mask[ra_idxs] = False + unassigned_idxs = ra_idxs[len(sel_idxs):] + unassigned_idxs_pred.append(unassigned_idxs) + pred_assigned[ra_idxs] = True + gen_assigned[sel_idxs] = True + ranks[~pred_assigned] = idxs[~gen_assigned][: cupy.sum(~pred_assigned)].reshape(-1, 1) + + elif col_type == ColumnType.CONTINUOUS: + y_generated = cupy.ravel(y_generated) + y_idxsort = cupy.argsort(y_generated) + y_generated_sorted = y_generated[y_idxsort] + ranking = cupy.searchsorted(y_generated_sorted, all_preds) + ranks = y_idxsort[ranking] + ranks = spread_ranks(ranks) + + elif len(target_cols) > 1: + y_generated = y_generated / ( + cupy.linalg.norm(y_generated, ord=2, axis=1).reshape(-1, 1) + ) + chunks = cupy.array_split(all_preds, len(all_preds) // batch_size) + for idx, chunk in enumerate(chunks): + idxs = cupy.ones((len(y_generated),), dtype=bool) + chunk = chunk / cupy.linalg.norm(chunk, ord=2, axis=1).reshape( + -1, 1 + ) + sim = cupy.einsum("ij,kj->ik", chunk, y_generated) + chunk_ranks = cupy.argsort(sim, axis=1)[:, -topk:] + rand_sel = cupy.random.randint(0, topk, len(chunk_ranks)) + chunk_ranks = chunk_ranks[ + cupy.arange(len(chunk_ranks)), rand_sel + ] + cupy.put(idxs, chunk_ranks, False) + y_generated = y_generated[idxs] + ranks[ + idx * batch_size: idx * batch_size + len(chunk) + ] = chunk_ranks.reshape(-1, 1) + + ranks[ranks >= len(tab_features[part_name])] = len(tab_features[part_name]) - 1 + ranks = cupy.asnumpy(ranks) + ranks = ranks.squeeze() + + features = tab_features[part_name].iloc[ranks].reset_index(drop=True) + result_dict[part_name] = features + + return result_dict + + def save(self, save_dir: Union[PosixPath, str]): + if not os.path.exists(save_dir): + os.makedirs(save_dir) + + if self.edge_trained_models: + for edge_name, models in self.edge_trained_models.items(): + for col_name, model in models.items(): + model.save_model( + os.path.join(save_dir, f"{edge_name}___{col_name}___xgb_aligner_edge.json") + ) + + if self.node_trained_models: + for node_name, models in self.node_trained_models.items(): + for col_name, model in models.items(): + model.save_model( + os.path.join(save_dir, f"{node_name}___{col_name}___xgb_aligner_node.json") + ) + + meta_data = { + "xgboost_params": self.xgboost_params, + "num_boost_round": self.num_boost_round, + "batch_size": self.batch_size, + "topk": self.topk, + "get_features": self.get_features, + "verbose": self.verbose, + "fitted_data": { + "features_to_correlate_edge": self.features_to_correlate_edge, + "features_to_correlate_node": self.features_to_correlate_node, + "col_maps_edge": self.col_maps_edge, + "col_maps_node": self.col_maps_node, + "meta_dict_edge": self.meta_dict_edge, + "meta_dict_node": self.meta_dict_node, + } + } + with open(os.path.join(save_dir, "xgb_aligner_meta.pkl"), "wb") as file_handler: + pickle.dump(meta_data, file_handler, protocol=pickle.HIGHEST_PROTOCOL) + + @classmethod + def load(cls, dir_path: Union[PosixPath, str]): + + with open(os.path.join(dir_path, "xgb_aligner_meta.pkl"), "rb") as file_handler: + meta_data = pickle.load(file_handler) + + fitted_data = meta_data.pop('fitted_data') + + instance = cls(**meta_data) + for k, v in fitted_data.items(): + setattr(instance, k, v) + + files = os.listdir(dir_path) + edge_files = [f for f in files if "xgb_aligner_edge" in f] + + instance.edge_trained_models = defaultdict(dict) + for ef in edge_files: + xgb_model = xgboost.Booster() + xgb_model.load_model(os.path.join(dir_path, ef)) + edge_name, col_name = ef.split("___")[:2] # - same format as `save` + instance.edge_trained_models[edge_name][col_name] = xgb_model + + node_files = [f for f in files if "xgb_aligner_node" in f] + instance.node_trained_models = defaultdict(dict) + for nf in node_files: + xgb_model = xgboost.Booster() + xgb_model.load_model(os.path.join(dir_path, nf)) + node_name, col_name = ef.split("___")[:2] # - same format as `save` + instance.node_trained_models[node_name][col_name] = xgb_model + return instance diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/__init__.py new file mode 100644 index 000000000..b0dbda317 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/base_preprocessing.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/base_preprocessing.py new file mode 100644 index 000000000..8b13ec561 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/base_preprocessing.py @@ -0,0 +1,84 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import os +from abc import ABC, abstractmethod +from typing import Optional + +from syngen.utils.types import MetaData +from syngen.configuration import SynGenDatasetFeatureSpec + +logger = logging.getLogger(__name__) +log = logger + + +class BasePreprocessing(ABC): + """Base class for all preprocessing transforms. + + Args: + source_path: path to the raw dataset + destination_path: path to store the dataset in SynGen format + download: tries automatically download the dataset if True + """ + + def __init__( + self, + source_path: str, + destination_path: Optional[str] = None, + download: bool = False, + **kwargs, + ): + self.source_path = source_path + self.destination_path = destination_path or os.path.join(source_path, 'syngen_preprocessed') + + if download: + self.download() + assert self._check_files() + + def _prepare_feature_list(self, tabular_data, cat_columns, cont_columns): + feature_list = [ + { + MetaData.NAME: feat_name, + MetaData.DTYPE: str(tabular_data[feat_name].dtype), + MetaData.FEATURE_TYPE: MetaData.CONTINUOUS, + } + for feat_name in cont_columns + ] + feature_list.extend([ + { + MetaData.NAME: feat_name, + MetaData.DTYPE: str(tabular_data[feat_name].dtype), + MetaData.FEATURE_TYPE: MetaData.CATEGORICAL, + } + for feat_name in cat_columns + ]) + return feature_list + + + @abstractmethod + def transform(self, gpu=False, use_cache=False) -> SynGenDatasetFeatureSpec: + raise NotImplementedError() + + @abstractmethod + def download(self): + raise NotImplementedError() + + @abstractmethod + def _check_files(self) -> bool: + raise NotImplementedError() + + @classmethod + def add_cli_args(cls, parser): + return parser diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/__init__.py new file mode 100644 index 000000000..21f084455 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/__init__.py @@ -0,0 +1,29 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .cora import CORAPreprocessing +from .epinions import EpinionsPreprocessing +from .ogbn_mag import OGBN_MAG_Preprocessing +from .ogbn_mag240m import MAG240mPreprocessing +from .ieee import IEEEPreprocessing +from .tabformer import TabFormerPreprocessing + +DATASETS = { + 'cora': CORAPreprocessing, + 'epinions': EpinionsPreprocessing, + 'ogbn_mag': OGBN_MAG_Preprocessing, + 'ogbn_mag240m': MAG240mPreprocessing, + 'ieee': IEEEPreprocessing, + 'tabformer': TabFormerPreprocessing, +} diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/cora.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/cora.py new file mode 100644 index 000000000..46802fb27 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/cora.py @@ -0,0 +1,163 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import os +import logging +import shutil +import subprocess +from typing import List, Union, Optional + +import numpy as np +import pandas as pd + +from syngen.configuration import SynGenDatasetFeatureSpec +from syngen.preprocessing.base_preprocessing import BasePreprocessing +from syngen.utils.types import MetaData + +logger = logging.getLogger(__name__) +log = logger + + +class CORAPreprocessing(BasePreprocessing): + def __init__( + self, + source_path: str, + destination_path: Optional[str] = None, + download: bool = False, + **kwargs, + ): + """ + preprocessing for https://linqs-data.soe.ucsc.edu/public/lbc/cora.tgz + """ + super().__init__(source_path, destination_path, download, **kwargs) + + def transform(self, gpu=False, use_cache=False): + + assert not gpu, "CORA preprocessing does not support cudf preprocessing" + + if use_cache and os.path.exists(self.destination_path): + return SynGenDatasetFeatureSpec.instantiate_from_preprocessed(self.destination_path) + tabular_operator = pd + operator = np + + examples = {} + + with open(os.path.join(self.source_path, 'cora.content'), "r") as cora_content: + for line in cora_content: + entries = line.rstrip("\n").split("\t") + # entries contains [ID, Word1, Word2, ..., Label]; "Words" are 0/1 values. + words = list(map(int, entries[1:-1])) + example_id = int(entries[0]) + label = entries[-1] + features = { + "id": example_id, + "label": label, + } + for i, w in enumerate(words): + features[f"w_{i}"] = w + examples[example_id] = features + tabular_data = tabular_operator.DataFrame.from_dict( + examples, orient="index" + ).reset_index(drop=True) + + node_features = [ + { + MetaData.NAME: f"w_{i}", + MetaData.DTYPE: 'int64', + MetaData.FEATURE_TYPE: MetaData.CATEGORICAL, + } + for i in range(len(words)) + ] + node_features.extend([ + { + MetaData.NAME: name, + MetaData.DTYPE: 'int64', + MetaData.FEATURE_TYPE: MetaData.CATEGORICAL, + } + for name in ["label"] + ]) + + for c in tabular_data.columns: + tabular_data[c] = tabular_data[c].astype("category").cat.codes.astype(int) + tabular_data = tabular_data.set_index('id') + + structural_data = tabular_operator.read_csv(os.path.join(self.source_path, "cora.cites")) + structural_data.columns = ["src", "dst"] + for c in ["src", "dst"]: + structural_data[c] = structural_data[c].astype(int) + + paper_ids = operator.unique(operator.concatenate([ + structural_data["src"].values, + structural_data["dst"].values, + ])) + + mapping = operator.empty(int(paper_ids.max()) + 1, dtype=int) + mapping[paper_ids] = operator.arange(len(paper_ids)) + + for c in ["src", "dst"]: + structural_data[c] = mapping[structural_data[c]] + + graph_metadata = { + MetaData.NODES: [ + { + MetaData.NAME: "paper", + MetaData.COUNT: len(tabular_data), + MetaData.FEATURES: node_features, + MetaData.FEATURES_PATH: "paper.parquet", + }, + ], + MetaData.EDGES: [{ + MetaData.NAME: "cite", + MetaData.COUNT: len(structural_data), + MetaData.SRC_NODE_TYPE: "paper", + MetaData.DST_NODE_TYPE: "paper", + MetaData.DIRECTED: False, + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + MetaData.STRUCTURE_PATH: "cite_edge_list.parquet", + }] + } + shutil.rmtree(self.destination_path, ignore_errors=True) + os.makedirs(self.destination_path) + + tabular_data.to_parquet(os.path.join(self.destination_path, "paper.parquet")) + structural_data.to_parquet(os.path.join(self.destination_path, "cite_edge_list.parquet")) + + with open(os.path.join(self.destination_path, 'graph_metadata.json'), 'w') as f: + json.dump(graph_metadata, f, indent=4) + + graph_metadata[MetaData.PATH] = self.destination_path + return SynGenDatasetFeatureSpec(graph_metadata) + + def download(self): + log.info("downloading CORA dataset...") + cmds = [ + fr"mkdir -p {self.source_path}", + fr"wget 'https://linqs-data.soe.ucsc.edu/public/lbc/cora.tgz' -P {self.source_path}", + fr"tar -xf {self.source_path}/cora.tgz -C {self.source_path}", + fr"sed -i 's/\t/,/g' {self.source_path}/cora/cora.cites", + fr"sed -i '1s/^/src,dst\n/' {self.source_path}/cora/cora.cites", + fr"mv {self.source_path}/cora/* {self.source_path}/.", + fr"rm -r {self.source_path}/cora", + ] + for cmd in cmds: + try: + subprocess.check_output(cmd, shell=True) + except subprocess.CalledProcessError as e: + raise Exception(e.output) + + def _check_files(self): + files = ['cora.cites', 'cora.content'] + return all(os.path.exists(os.path.join(self.source_path, file)) for file in files) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/epinions.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/epinions.py new file mode 100644 index 000000000..acdfda33b --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/epinions.py @@ -0,0 +1,176 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging +import os +import shutil +import tarfile +from typing import Optional +from urllib.request import urlopen + +import cudf +import cupy as cp +import numpy as np +import pandas as pd + +from syngen.configuration import SynGenDatasetFeatureSpec +from syngen.preprocessing.base_preprocessing import BasePreprocessing +from syngen.utils.types import MetaData + +logger = logging.getLogger(__name__) +log = logger + + +class EpinionsPreprocessing(BasePreprocessing): + ITEM_SPACE_ARCHIVE_URL = ( + "http://konect.cc/files/download.tsv.epinions-rating.tar.bz2" + ) + + SOCIAL_SPACE_ARCHIVE_URL = ( + "http://konect.cc/files/download.tsv.epinions.tar.bz2" + ) + + def __init__( + self, + source_path: str, + destination_path: Optional[str] = None, + download: bool = False, + **kwargs, + ): + """ + preprocessing for http://www.trustlet.org/wiki/Extended_Epinions_dataset + + Args: + + """ + self.ratings_file = os.path.join(source_path, 'epinions-rating', 'out.epinions-rating') + self.trust_file = os.path.join(source_path, 'epinions', 'out.epinions') + super().__init__(source_path, destination_path, download, **kwargs) + + def transform(self, gpu=False, use_cache=False): + + if use_cache and os.path.exists(self.destination_path): + return SynGenDatasetFeatureSpec.instantiate_from_preprocessed(self.destination_path) + + operator = cp if gpu else np + tabular_operator = cudf if gpu else pd + + item_space_data = tabular_operator.read_csv( + self.ratings_file, + sep=" ", + names=["userId", "itemId", "rating", "timestamp"], + skiprows=1, + ) + social_space_data = tabular_operator.read_csv( + self.trust_file, + sep=" ", + names=["userId", "friendId", "trust", "timestamp"], + skiprows=1, + ) + social_space_data = social_space_data[social_space_data["trust"] == 1] + + min_item_id = int(item_space_data['itemId'].min()) + + item_space_data['itemId'] = item_space_data['itemId'] - min_item_id + + min_user_id = min( + int(item_space_data['userId'].min()), + int(social_space_data['userId'].min()), + int(social_space_data['friendId'].min()) + ) + + item_space_data['userId'] = item_space_data['userId'] - min_user_id + social_space_data['userId'] = social_space_data['userId'] - min_user_id + social_space_data['friendId'] = social_space_data['friendId'] - min_user_id + + graph_metadata = { + MetaData.NODES: [ + { + MetaData.NAME: "user", + MetaData.COUNT: int(item_space_data['userId'].max()), + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + }, + { + MetaData.NAME: "item", + MetaData.COUNT: int(item_space_data['itemId'].max()), + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + } + ], + MetaData.EDGES: [ + { + MetaData.NAME: "user-item", + MetaData.COUNT: len(item_space_data), + MetaData.SRC_NODE_TYPE: "user", + MetaData.DST_NODE_TYPE: "item", + MetaData.DIRECTED: False, + MetaData.FEATURES: [ + { + MetaData.NAME: "rating", + MetaData.DTYPE: str(item_space_data["rating"].dtype), + MetaData.FEATURE_TYPE: MetaData.CATEGORICAL, + } + ], + MetaData.FEATURES_PATH: "user-item.parquet", + MetaData.STRUCTURE_PATH: "user-item_edge_list.parquet", + }, + { + MetaData.NAME: "user-user", + MetaData.COUNT: len(social_space_data), + MetaData.SRC_NODE_TYPE: "user", + MetaData.DST_NODE_TYPE: "item", + MetaData.DIRECTED: False, + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + MetaData.STRUCTURE_PATH: "user-user_edge_list.parquet", + } + ] + } + shutil.rmtree(self.destination_path, ignore_errors=True) + os.makedirs(self.destination_path) + + item_space_data[['rating']] \ + .to_parquet(os.path.join(self.destination_path, "user-item.parquet")) + + item_space_data[['userId', 'itemId']] \ + .rename(columns={'userId': MetaData.SRC, 'itemId': MetaData.DST}) \ + .to_parquet(os.path.join(self.destination_path, "user-item_edge_list.parquet")) + + social_space_data[['userId', 'friendId']] \ + .rename(columns={'userId': MetaData.SRC, 'friendId': MetaData.DST}) \ + .to_parquet(os.path.join(self.destination_path, "user-user_edge_list.parquet")) + + with open(os.path.join(self.destination_path, 'graph_metadata.json'), 'w') as f: + json.dump(graph_metadata, f, indent=4) + + graph_metadata[MetaData.PATH] = self.destination_path + return SynGenDatasetFeatureSpec(graph_metadata) + + def download(self): + if not os.path.exists(self.source_path): + os.makedirs(self.source_path) + + if not os.path.exists(self.ratings_file): + with tarfile.open(fileobj=urlopen(self.ITEM_SPACE_ARCHIVE_URL), mode="r|bz2") as tar: + tar.extractall(self.source_path) + + if not os.path.exists(self.trust_file): + with tarfile.open(fileobj=urlopen(self.SOCIAL_SPACE_ARCHIVE_URL), mode="r|bz2") as tar: + tar.extractall(self.source_path) + + def _check_files(self): + files = [self.ratings_file, self.trust_file] + return all(os.path.exists(file) for file in files) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ieee.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ieee.py new file mode 100644 index 000000000..c65362437 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ieee.py @@ -0,0 +1,128 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import json +import logging +import shutil +from typing import Optional + +import cudf +import cupy as cp +import numpy as np +import pandas as pd + +from syngen.configuration import SynGenDatasetFeatureSpec +from syngen.preprocessing.base_preprocessing import BasePreprocessing +from syngen.utils.types import MetaData + +logger = logging.getLogger(__name__) +log = logger + + +class IEEEPreprocessing(BasePreprocessing): + """ + preprocessing for https://www.kaggle.com/competitions/ieee-fraud-detection + """ + + def __init__( + self, + source_path: str, + destination_path: Optional[str] = None, + download: bool = False, + **kwargs, + ): + super().__init__(source_path, destination_path, download, **kwargs) + + def transform(self, gpu=False, use_cache=False): + + if use_cache and os.path.exists(self.destination_path): + return SynGenDatasetFeatureSpec.instantiate_from_preprocessed(self.destination_path) + + operator = cp if gpu else np + tabular_operator = cudf if gpu else pd + + data = tabular_operator.read_csv(os.path.join(self.source_path, 'data.csv')) + data = data.fillna(0) + + cont_columns = [ + 'TransactionDT', 'TransactionAmt', 'C1', 'C2', 'C3', 'C4', + 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'C11', 'C12', 'C14', 'V279', + 'V280', 'V284', 'V285', 'V286', 'V287', 'V290', 'V291', 'V292', 'V293', + 'V294', 'V295', 'V297', 'V298', 'V299', 'V302', 'V303', 'V304', 'V305', + 'V306', 'V307', 'V308', 'V309', 'V310', 'V311', 'V312', 'V316', 'V317', + 'V318', 'V319', 'V320', 'V321', + ] + + cat_columns = ["isFraud"] + + for col in ('user_id', 'product_id', *cat_columns): + data[col] = data[col].astype("category").cat.codes + data[col] = data[col].astype(int) + + structural_data = data[['user_id', 'product_id']] + + tabular_data = data[[*cat_columns, *cont_columns]] + + edge_features = self._prepare_feature_list(tabular_data, cat_columns, cont_columns) + + graph_metadata = { + MetaData.NODES: [ + { + MetaData.NAME: "user", + MetaData.COUNT: int(structural_data['user_id'].max()), + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + }, + { + MetaData.NAME: "product", + MetaData.COUNT: int(structural_data['product_id'].max()), + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + } + ], + MetaData.EDGES: [ + { + MetaData.NAME: "user-product", + MetaData.COUNT: len(structural_data), + MetaData.SRC_NODE_TYPE: "user", + MetaData.DST_NODE_TYPE: "product", + MetaData.DIRECTED: False, + MetaData.FEATURES: edge_features, + MetaData.FEATURES_PATH: "user-product.parquet", + MetaData.STRUCTURE_PATH: "user-product_edge_list.parquet", + } + ] + } + + shutil.rmtree(self.destination_path, ignore_errors=True) + os.makedirs(self.destination_path) + + tabular_data.to_parquet(os.path.join(self.destination_path, "user-product.parquet")) + structural_data.to_parquet(os.path.join(self.destination_path, "user-product_edge_list.parquet")) + + with open(os.path.join(self.destination_path, 'graph_metadata.json'), 'w') as f: + json.dump(graph_metadata, f, indent=4) + + graph_metadata[MetaData.PATH] = self.destination_path + return SynGenDatasetFeatureSpec(graph_metadata) + + def download(self): + raise NotImplementedError( + "IEEE dataset does not support automatic downloading. Please run /workspace/scripts/get_datasets.sh" + ) + + def _check_files(self) -> bool: + files = ['data.csv'] + return all(os.path.exists(os.path.join(self.source_path, file)) for file in files) \ No newline at end of file diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ogbn_mag.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ogbn_mag.py new file mode 100644 index 000000000..98b4410a7 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ogbn_mag.py @@ -0,0 +1,222 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import os +import shutil +from typing import Optional + +import cudf +import cupy as cp +import numpy as np +import pandas as pd +from ogb.nodeproppred import NodePropPredDataset + +from syngen.configuration import SynGenDatasetFeatureSpec +from syngen.preprocessing.base_preprocessing import BasePreprocessing +from syngen.utils.io_utils import dump_dataframe +from syngen.utils.types import MetaData + + +class OGBN_MAG_Preprocessing(BasePreprocessing): + """ + The OGBN_MAG_Preprocessing class includes the transformation + operation for a subset of the Microsoft Academic Graph (MAG). + It's a heterogeneous network that contains four types of entities—papers + (736,389 nodes), authors (1,134,649 nodes), institutions (8,740 nodes), + and fields of study (59,965 nodes)—as well as four types of directed relations + connecting two types of entities—an author is “affiliated with” an institution, + an author “writes” a paper, a paper “cites” a paper, and a paper “has a topic + of” a field of study. For more information, please check + https://ogb.stanford.edu/docs/nodeprop/ + + """ + + def __init__( + self, + source_path: str, + destination_path: Optional[str] = None, + download: bool = False, + **kwargs, + ): + super().__init__(source_path, destination_path, download, **kwargs) + + def download(self): + NodePropPredDataset(name="ogbn-mag", root=self.source_path) + + def _check_files(self) -> bool: + return True + + def transform(self, gpu=False, use_cache=False): + + tabular_operator = cudf if gpu else pd + operator = cp if gpu else np + + if use_cache and os.path.exists(self.destination_path): + return SynGenDatasetFeatureSpec.instantiate_from_preprocessed(self.destination_path) + + shutil.rmtree(self.destination_path, ignore_errors=True) + os.makedirs(self.destination_path) + + dataset = NodePropPredDataset(name="ogbn-mag", root=self.source_path)[0] + data = dataset[0] + labels = dataset[1]["paper"] + + graph_metadata = { + MetaData.NODES: [], + MetaData.EDGES: [], + } + + connections = {} + + for e, edges in data["edge_index_dict"].items(): + + structural_data = pd.DataFrame(edges.T, columns=[MetaData.SRC, MetaData.DST]) + + connections[e[1]] = tabular_operator.DataFrame({ + "src_id": edges[0, :], + "dst_id": edges[1, :], + }) + + edata = data["edge_reltype"][e] + + edge_type = { + MetaData.NAME: e[1], + MetaData.COUNT: len(structural_data), + MetaData.SRC_NODE_TYPE: e[0], + MetaData.DST_NODE_TYPE: e[2], + MetaData.DIRECTED: False, + MetaData.FEATURES: [{ + MetaData.NAME: 'feat', + MetaData.DTYPE: str(edata.dtype), + MetaData.FEATURE_TYPE: MetaData.CATEGORICAL, + }], + MetaData.FEATURES_PATH: f"{e[1]}_features.parquet", + MetaData.STRUCTURE_PATH: f"{e[1]}_list.parquet", + } + + dump_dataframe(tabular_operator.DataFrame(edata, columns=['feat']), + os.path.join(self.destination_path, edge_type[MetaData.FEATURES_PATH])) + dump_dataframe(structural_data, + os.path.join(self.destination_path, edge_type[MetaData.STRUCTURE_PATH])) + graph_metadata[MetaData.EDGES].append(edge_type) + + # paper node type + continuous_column_names = ["feat_" + str(i) for i in range(data["node_feat_dict"]["paper"].shape[1])] + paper_features_dataframe = tabular_operator.DataFrame( + data["node_feat_dict"]["paper"], + columns=continuous_column_names, + ).astype("float32") + + paper_features_dataframe["year"] = tabular_operator.DataFrame(data["node_year"]["paper"]).astype("int32") + paper_features_dataframe["venue"] = tabular_operator.DataFrame(labels).astype("int32") + + paper_node_type = { + MetaData.NAME: "paper", + MetaData.COUNT: data["num_nodes_dict"]['paper'], + MetaData.FEATURES: [ + { + MetaData.NAME: name, + MetaData.DTYPE: str(dtype), + MetaData.FEATURE_TYPE: + MetaData.CATEGORICAL if str(dtype).startswith('int') else MetaData.CONTINUOUS, + } for name, dtype in paper_features_dataframe.dtypes.items() + ], + MetaData.FEATURES_PATH: "paper.parquet", + } + dump_dataframe(paper_features_dataframe, + os.path.join(self.destination_path, paper_node_type[MetaData.FEATURES_PATH])) + graph_metadata[MetaData.NODES].append(paper_node_type) + + # author node type + paper_features_dataframe["paper_id"] = operator.arange(paper_features_dataframe.shape[0]) + + author_feat = connections["writes"].merge( + paper_features_dataframe, + left_on="dst_id", + right_on="paper_id", + how="left" + ).groupby("src_id", sort=True).mean() + author_features_dataframe = author_feat[continuous_column_names] + + author_node_type = { + MetaData.NAME: "author", + MetaData.COUNT: data["num_nodes_dict"]['author'], + MetaData.FEATURES: [ + { + MetaData.NAME: name, + MetaData.DTYPE: str(dtype), + MetaData.FEATURE_TYPE: MetaData.CONTINUOUS, + } for name, dtype in author_features_dataframe.dtypes.items() + ], + MetaData.FEATURES_PATH: "author.parquet", + } + dump_dataframe(author_features_dataframe, + os.path.join(self.destination_path, author_node_type[MetaData.FEATURES_PATH])) + graph_metadata[MetaData.NODES].append(author_node_type) + + # institution node type + author_features_dataframe["author_id"] = operator.arange(author_features_dataframe.shape[0]) + institution_feat = connections["affiliated_with"].merge( + author_features_dataframe, + left_on="src_id", + right_on="author_id" + ).groupby("dst_id", sort=True).mean() + institution_dataframe = institution_feat[continuous_column_names] + + institution_node_type = { + MetaData.NAME: "institution", + MetaData.COUNT: data["num_nodes_dict"]['institution'], + MetaData.FEATURES: [ + { + MetaData.NAME: name, + MetaData.DTYPE: str(dtype), + MetaData.FEATURE_TYPE: MetaData.CONTINUOUS, + } for name, dtype in institution_dataframe.dtypes.items() + ], + MetaData.FEATURES_PATH: "institution.parquet", + } + dump_dataframe(institution_dataframe, + os.path.join(self.destination_path, institution_node_type[MetaData.FEATURES_PATH])) + graph_metadata[MetaData.NODES].append(institution_node_type) + + # field_of_study node type + field_of_study_feat = connections["has_topic"].merge( + paper_features_dataframe, + left_on="src_id", + right_on="paper_id" + ).groupby("dst_id", sort=True).mean() + field_of_study_dataframe = field_of_study_feat[continuous_column_names] + + field_of_study_node_type = { + MetaData.NAME: "field_of_study", + MetaData.COUNT: data["num_nodes_dict"]['field_of_study'], + MetaData.FEATURES: [ + { + MetaData.NAME: name, + MetaData.DTYPE: str(dtype), + MetaData.FEATURE_TYPE: MetaData.CONTINUOUS, + } for name, dtype in field_of_study_dataframe.dtypes.items() + ], + MetaData.FEATURES_PATH: "field_of_study.parquet", + } + dump_dataframe(field_of_study_dataframe, + os.path.join(self.destination_path, field_of_study_node_type[MetaData.FEATURES_PATH])) + graph_metadata[MetaData.NODES].append(field_of_study_node_type) + + with open(os.path.join(self.destination_path, 'graph_metadata.json'), 'w') as f: + json.dump(graph_metadata, f, indent=4) + + graph_metadata[MetaData.PATH] = self.destination_path + return SynGenDatasetFeatureSpec(graph_metadata) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ogbn_mag240m.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ogbn_mag240m.py new file mode 100644 index 000000000..3465fb989 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/ogbn_mag240m.py @@ -0,0 +1,162 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import os +import shutil +from typing import Optional + +import numpy as np +import pandas as pd + +from ogb.lsc import MAG240MDataset + +from syngen.preprocessing.base_preprocessing import BasePreprocessing +from syngen.configuration import SynGenDatasetFeatureSpec +from syngen.utils.io_utils import dump_dataframe +from syngen.utils.types import MetaData + + +class MAG240mPreprocessing(BasePreprocessing): + + def __init__( + self, + source_path: str, + destination_path: Optional[str] = None, + download: bool = False, + skip_node_features=False, + **kwargs, + ): + super().__init__(source_path, destination_path, download, **kwargs) + self.include_node_features = not skip_node_features + + def download(self): + MAG240MDataset(root=self.source_path) + + def _check_files(self) -> bool: + return True + + def transform(self, gpu=False, use_cache=False): + + if gpu: + raise ValueError("MAG240m support does not support gpu preprocessing at the moment") + + if use_cache and os.path.exists(self.destination_path): + return SynGenDatasetFeatureSpec.instantiate_from_preprocessed(self.destination_path) + + shutil.rmtree(self.destination_path, ignore_errors=True) + os.makedirs(self.destination_path) + + dataset = MAG240MDataset(root=self.source_path) + + graph_metadata = { + MetaData.NODES: [], + MetaData.EDGES: [], + } + + # paper node type + + features = [] + features_path = None + if self.include_node_features: + features_path = 'paper_tabular_features' + os.makedirs(os.path.join(self.destination_path, features_path)) + column_names = ["feat_" + str(i) for i in range(0, dataset.num_paper_features)] + feat_memmap = dataset.paper_feat + + features = [ + { + MetaData.NAME: name, + MetaData.DTYPE: str(feat_memmap.dtype), + MetaData.FEATURE_TYPE: MetaData.CONTINUOUS, + MetaData.FEATURE_FILE: 'paper_feats.npy' + } for name in column_names + ] + np.save(os.path.join(self.destination_path, features_path, 'paper_feats.npy'), feat_memmap) + + features.append({ + MetaData.NAME: 'year', + MetaData.DTYPE: "int32", + MetaData.FEATURE_TYPE: MetaData.CATEGORICAL, + MetaData.FEATURE_FILE: 'year_label.npy' + }) + features.append({ + MetaData.NAME: 'label', + MetaData.DTYPE: "int32", + MetaData.FEATURE_TYPE: MetaData.CATEGORICAL, + MetaData.FEATURE_FILE: 'year_label.npy' + }) + year_label_df = pd.DataFrame() + year_label_df['year'] = dataset.all_paper_year + year_label_df['label'] = np.nan_to_num(dataset.all_paper_label, nan=-2) + np.save(os.path.join(self.destination_path, features_path, 'year_label.npy'), year_label_df.values) + del year_label_df + + paper_node_type = { + MetaData.NAME: "paper", + MetaData.COUNT: dataset.num_papers, + MetaData.FEATURES: features, + MetaData.FEATURES_PATH: features_path, + } + graph_metadata[MetaData.NODES].append(paper_node_type) + + # author node type + author_node_type = { + MetaData.NAME: "author", + MetaData.COUNT: dataset.num_authors, + MetaData.FEATURES_PATH: None, + } + graph_metadata[MetaData.NODES].append(author_node_type) + + # institution node type + institution_node_type = { + MetaData.NAME: "institution", + MetaData.COUNT: dataset.num_institutions, + MetaData.FEATURES_PATH: None, + } + graph_metadata[MetaData.NODES].append(institution_node_type) + + for (src_node_type, dst_node_type), edge_name in dataset.__rels__.items(): + edges = dataset.edge_index(src_node_type, dst_node_type) + structural_data = pd.DataFrame(edges.T, columns=[MetaData.SRC, MetaData.DST]) + + edge_type = { + MetaData.NAME: edge_name, + MetaData.COUNT: len(structural_data), + MetaData.SRC_NODE_TYPE: src_node_type, + MetaData.DST_NODE_TYPE: dst_node_type, + MetaData.DIRECTED: False, + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + MetaData.STRUCTURE_PATH: f"{edge_name}_list.parquet", + } + dump_dataframe(structural_data, + os.path.join(self.destination_path, edge_type[MetaData.STRUCTURE_PATH])) + graph_metadata[MetaData.EDGES].append(edge_type) + + with open(os.path.join(self.destination_path, 'graph_metadata.json'), 'w') as f: + json.dump(graph_metadata, f, indent=4) + + graph_metadata[MetaData.PATH] = self.destination_path + return SynGenDatasetFeatureSpec(graph_metadata) + + @classmethod + def add_cli_args(cls, parser): + parser.add_argument( + "-snf", + "--skip-node-features", + action='http://github.com/store_true', + help='Prepares only the structural part of the MAG240m dataset' + ) + return parser diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/tabformer.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/tabformer.py new file mode 100644 index 000000000..7243a5808 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/preprocessing/datasets/tabformer.py @@ -0,0 +1,146 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math +import os +import json +import logging +import shutil +from typing import Optional + +import cudf +import cupy as cp +import numpy as np +import pandas as pd + +from syngen.utils.types import DataFrameType +from syngen.configuration import SynGenDatasetFeatureSpec +from syngen.preprocessing.base_preprocessing import BasePreprocessing +from syngen.utils.types import MetaData + + +class TabFormerPreprocessing(BasePreprocessing): + """ + preprocessing for https://github.com/IBM/TabFormer + + """ + + def __init__( + self, + source_path: str, + destination_path: Optional[str] = None, + download: bool = False, + **kwargs, + ): + super().__init__(source_path, destination_path, download, **kwargs) + + @staticmethod + def nanNone(X: DataFrameType) -> DataFrameType: + return X.where(X.notnull(), "None") + + @staticmethod + def amountEncoder(X: DataFrameType) -> DataFrameType: + return ( + X.str.slice(start=1) + .astype(float) + .clip(lower=1.0) + .map(lambda x: math.log(x)) + ) + + def transform(self, gpu=False, use_cache=False) -> SynGenDatasetFeatureSpec: + + if use_cache and os.path.exists(self.destination_path): + return SynGenDatasetFeatureSpec.instantiate_from_preprocessed(self.destination_path) + + operator = cp if gpu else np + tabular_operator = cudf if gpu else pd + + data = tabular_operator.read_csv(os.path.join(self.source_path, 'card_transaction.v2.csv')) + data.columns = [ + i.lower().replace(" ", "_") for i in data.columns.tolist() + ] + data = data.rename( + columns={"is_fraud?": "is_fraud", "errors?": "errors", "merchant_name": "merchant_id"} + ) + + data['card_id'] = data['user'] + data['card'] + data.drop(columns=['user', 'card'], inplace=True) + + data["errors"] = data["errors"].fillna(0) + data["use_chip"] = self.nanNone(data["use_chip"]) + data["amount"] = self.amountEncoder(data["amount"]) + + cont_columns = ["amount"] + + cat_columns = ["use_chip", "errors", "is_fraud"] + + for col in ("card_id", "merchant_id", *cat_columns): + data[col] = data[col].astype("category").cat.codes + data[col] = data[col].astype(int) + + structural_data = data[['card_id', 'merchant_id']] + tabular_data = data[[*cat_columns, *cont_columns]] + + edge_features = self._prepare_feature_list(tabular_data, cat_columns, cont_columns) + + graph_metadata = { + MetaData.NODES: [ + { + MetaData.NAME: "card", + MetaData.COUNT: int(structural_data['card_id'].max()), + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + }, + { + MetaData.NAME: "merchant", + MetaData.COUNT: int(structural_data['merchant_id'].max()), + MetaData.FEATURES: [], + MetaData.FEATURES_PATH: None, + } + ], + MetaData.EDGES: [ + { + MetaData.NAME: "transaction", + MetaData.COUNT: len(structural_data), + MetaData.SRC_NODE_TYPE: "card", + MetaData.DST_NODE_TYPE: "merchant", + MetaData.DIRECTED: False, + MetaData.FEATURES: edge_features, + MetaData.FEATURES_PATH: "transaction.parquet", + MetaData.STRUCTURE_PATH: "transaction_edge_list.parquet", + } + ] + } + + shutil.rmtree(self.destination_path, ignore_errors=True) + os.makedirs(self.destination_path) + + tabular_data.to_parquet(os.path.join(self.destination_path, "transaction.parquet")) + structural_data.to_parquet(os.path.join(self.destination_path, "transaction_edge_list.parquet")) + + with open(os.path.join(self.destination_path, 'graph_metadata.json'), 'w') as f: + json.dump(graph_metadata, f, indent=4) + + graph_metadata[MetaData.PATH] = self.destination_path + return SynGenDatasetFeatureSpec(graph_metadata) + + def download(self): + raise NotImplementedError( + "TabFormer dataset does not support automatic downloading. Please run /workspace/scripts/get_datasets.sh" + ) + + def _check_files(self) -> bool: + files = ['card_transaction.v2.csv'] + return all(os.path.exists(os.path.join(self.source_path, file)) for file in files) + diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/__init__.py new file mode 100644 index 000000000..a4eca9190 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/__init__.py @@ -0,0 +1,17 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .base_synthesizer import BaseSynthesizer +from .configuration_graph_synthesizer import ConfigurationGraphSynthesizer diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/base_synthesizer.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/base_synthesizer.py new file mode 100644 index 000000000..e3d0150f9 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/base_synthesizer.py @@ -0,0 +1,66 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import abc + + +class BaseSynthesizer(abc.ABC): + """Base class for all ``Synthesizers``""" + + @classmethod + def get_synthesizers(cls, include_parents=True): + """Recursively find sublcasses of `BaseSynthesizer` + + Args: + include_parents (bool): whether to include parents to other classes. (default: `True`) + """ + + synthesizers = dict() + for child in cls.__subclasses__(): + children = child.get_synthesizers(include_parents) + synthesizers.update(children) + + if include_parents or not children: + if abc.ABC not in child.__bases__: + synthesizers[child.__name__] = child + return synthesizers + + def fit(self, *args, **kwargs): + """fits synthesizer on a specified dataset""" + raise NotImplementedError() + + def generate(self, *args, **kwargs): + """generate graph using configured synthesizer""" + raise NotImplementedError() + + def save(self, path: str): + """save this synthesizer to disk + Args: + path (str): The path to save the synthesizer to + """ + raise NotImplementedError() + + @classmethod + def load(cls, path: str): + """load up a saved synthesizer object from disk. + + Args: + path (str): The path to load the synthesizer from + """ + raise NotImplementedError() + + @staticmethod + def add_args(parser): + """optional function to add arguments to parser for the CLI interface""" + return parser diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/configuration_graph_synthesizer.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/configuration_graph_synthesizer.py new file mode 100644 index 000000000..cc41e3f85 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/synthesizer/configuration_graph_synthesizer.py @@ -0,0 +1,711 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import gc +import logging +import json +import os +import shutil +import warnings +from typing import Optional, Literal + +import pandas as pd + +from syngen.configuration import SynGenDatasetFeatureSpec, SynGenConfiguration +from syngen.generator.tabular import tabular_generators_classes +from syngen.graph_aligner import aligner_classes +from syngen.generator.graph import get_structural_generator_class +from syngen.generator.tabular.utils import tabular_chunk_sample_generation +from syngen.utils.io_utils import ( + dump_generated_graph, + load_graph, + load_dataframe, + merge_dataframe_files, dump_dataframe, +) +from syngen.utils.types import DataFrameType, MetaData, DataSourceInputType +from syngen.utils.utils import CustomTimer, dynamic_import, get_object_path, to_ndarray, df_to_pandas, ensure_path + +logger = logging.getLogger(__name__) +log = logger + +warnings.filterwarnings('ignore') + + +class ConfigurationGraphSynthesizer(object): + """A configuration graph synthesizer. Supports generating graph datasets based on the provided configuration. This synthesizer requires a dataset to be fit on + prior to generating graphs of similar properties. + + Args: + configuration (SynGenConfiguration): configuration to be used during generation + timer_path (srt): path to the file where the generation process timings will be saved + num_workers (int): number of workers to speed up generation. + save_path (str): path to the directory where the results will be saved + gpu (bool): flag to use GPU graph generator (default: True ), if set to False CPU will be used. + verbose (bool): print intermediate results (default: False) + """ + def __init__( + self, + configuration: SynGenConfiguration, + timer_path: Optional[str] = None, + num_workers: int = 1, + save_path: str = './', + gpu: bool = True, + verbose: bool = False, + **kwargs, + ): + self.configuration = configuration + self.num_workers = num_workers + self.verbose = verbose + self.timer = CustomTimer(timer_path, verbose=self.verbose) + self.gpu = gpu + self.save_path = save_path + + if not os.path.exists(self.save_path): + os.makedirs(self.save_path) + + self.structure_generators = None + self.tabular_generators = None + self.aligners = None + + def _fit_tabular_generators(self, tab_gen_configs, feature_info_list, + part: Literal[MetaData.NODES, MetaData.EDGES], + features_to_return=()): + tabular_generators = [] + feature_info_dict = {feature[MetaData.NAME]: feature for feature in feature_info_list} + feature_data_cache = {} + for tab_gen_cfg in tab_gen_configs: + gen_info = {'feature_file': tab_gen_cfg.get('feature_file')} + tab_gen_class = tabular_generators_classes[tab_gen_cfg[MetaData.TYPE]] + tab_gen_cfg[MetaData.PARAMS]['gpu'] = tab_gen_cfg[MetaData.PARAMS].get('gpu', self.gpu) + tab_gen_cfg[MetaData.PARAMS]['verbose'] = tab_gen_cfg[MetaData.PARAMS].get('verbose', self.verbose) + perform_fit = True + enforce_fit = tab_gen_cfg.get('perform_fit', False) + generator_dump_path = tab_gen_cfg.get(MetaData.DUMP_PATH, None) + + if generator_dump_path and os.path.exists(generator_dump_path) and not enforce_fit: + tab_gen = tab_gen_class.load(generator_dump_path) + perform_fit = False + else: + tab_gen = tab_gen_class(**tab_gen_cfg[MetaData.PARAMS]) + + if tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.TYPE] == DataSourceInputType.RANDOM: + if perform_fit: + tab_gen.fit(columns=tab_gen_cfg[MetaData.FEATURES_LIST]) + if generator_dump_path and perform_fit: + tab_gen.save(generator_dump_path) + tabular_generators.append((tab_gen, gen_info)) + continue + + categorical_features = [] + data_source_feature_info_list = None + if not perform_fit: + pass + elif tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.TYPE] == DataSourceInputType.DATASET: + data_source_path = tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.PATH] + elif tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.TYPE] == DataSourceInputType.CONFIGURATION: + cfg = SynGenDatasetFeatureSpec.instantiate_from_preprocessed( + tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.PATH]) + data_source_info = cfg.get_info(part, tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.NAME]) + data_source_feature_info_list = data_source_info[MetaData.FEATURES] + data_source_path = os.path.join(tab_gen_cfg[MetaData.DATA_SOURCE][MetaData.PATH], + data_source_info[MetaData.FEATURES_PATH]) + else: + raise ValueError("unsupported data_source type") + + for feature_name in tab_gen_cfg[MetaData.FEATURES_LIST]: + if feature_info_dict[feature_name][MetaData.FEATURE_TYPE] == MetaData.CATEGORICAL: + categorical_features.append(feature_name) + + if not perform_fit and len(features_to_return) == 0: + pass + elif data_source_path in feature_data_cache: + data = feature_data_cache[data_source_path] + else: + # FORCE_CPU_MEM_TRANSFER + data = load_dataframe(data_source_path, feature_info=data_source_feature_info_list) + feature_data_cache[data_source_path] = data + + if perform_fit: + tab_gen.fit(data, + categorical_columns=categorical_features, + columns=tab_gen_cfg[MetaData.FEATURES_LIST], + verbose=self.verbose) + + if generator_dump_path and perform_fit: + tab_gen.save(ensure_path(generator_dump_path)) + + tabular_generators.append((tab_gen, gen_info)) + + if features_to_return: + return_dataframe = pd.DataFrame() + for _, cache_data in feature_data_cache.items(): + columns_intersect = list(set(features_to_return) & set(cache_data.columns)) + return_dataframe[columns_intersect] = cache_data[columns_intersect] + del feature_data_cache + + return_categorical_features = [] + for feature_name in features_to_return: + if feature_info_dict[feature_name][MetaData.FEATURE_TYPE] == MetaData.CATEGORICAL: + return_categorical_features.append(feature_name) + return tabular_generators, (return_dataframe, return_categorical_features) + + del feature_data_cache + return tabular_generators + + def _fit_structural_generator(self, edge_type, return_graph=False): + structure_gen_cfg = edge_type[MetaData.STRUCTURE_GENERATOR] + + is_bipartite = edge_type[MetaData.SRC_NODE_TYPE] != edge_type[MetaData.DST_NODE_TYPE] + + is_directed = edge_type[MetaData.DIRECTED] + + data_source_cfg = structure_gen_cfg[MetaData.DATA_SOURCE] + is_random = data_source_cfg[MetaData.TYPE] == DataSourceInputType.RANDOM + + generator_class = get_structural_generator_class( + structure_gen_cfg[MetaData.TYPE], + is_bipartite=is_bipartite, + is_random=is_random, + ) + + gen_info = dict(is_bipartite=is_bipartite, + is_directed=is_directed, + num_edges=edge_type[MetaData.COUNT], + noise=structure_gen_cfg[MetaData.PARAMS].get('noise', 0.5)) + + structure_gen_cfg[MetaData.PARAMS]['gpu'] = structure_gen_cfg[MetaData.PARAMS].get('gpu', self.gpu) + structure_gen_cfg[MetaData.PARAMS]['verbose'] = structure_gen_cfg[MetaData.PARAMS].get('verbose', self.verbose) + perform_fit = True + enforce_fit = structure_gen_cfg.get('perform_fit', False) + + generator_dump_path = structure_gen_cfg.get(MetaData.DUMP_PATH, None) + + if generator_dump_path and os.path.exists(generator_dump_path) and not enforce_fit: + generator = generator_class.load(generator_dump_path) + generator.gpu = structure_gen_cfg[MetaData.PARAMS]['gpu'] + generator.verbose = structure_gen_cfg[MetaData.PARAMS]['verbose'] + perform_fit = False + else: + generator = generator_class( + **structure_gen_cfg[MetaData.PARAMS] + ) + + if not perform_fit and not return_graph: + pass + elif data_source_cfg[MetaData.TYPE] == DataSourceInputType.RANDOM: + graph = None + elif data_source_cfg[MetaData.TYPE] == DataSourceInputType.CONFIGURATION: + cfg = SynGenDatasetFeatureSpec.instantiate_from_preprocessed(data_source_cfg[MetaData.PATH]) + data_source_edge_info = cfg.get_edge_info(data_source_cfg[MetaData.NAME]) + graph_src_set = cfg.get_node_info(data_source_edge_info[MetaData.SRC_NODE_TYPE])[MetaData.COUNT] + graph_path = os.path.join(data_source_cfg[MetaData.PATH], data_source_edge_info[MetaData.STRUCTURE_PATH]) + graph = load_graph(graph_path) + else: + raise ValueError("unsupported data_source type") + + if is_bipartite: + gen_info['is_directed'] = False + gen_info['num_nodes_src_set'] = self.configuration.get_node_info( + edge_type[MetaData.SRC_NODE_TYPE])[MetaData.COUNT] + gen_info['num_nodes_dst_set'] = self.configuration.get_node_info( + edge_type[MetaData.DST_NODE_TYPE])[MetaData.COUNT] + + if perform_fit: + generator.fit(graph, src_set=None, dst_set=None, + is_directed=False, transform_graph=False) + else: + gen_info['num_nodes'] = self.configuration.get_node_info(edge_type[MetaData.SRC_NODE_TYPE])[MetaData.COUNT] + gen_info['has_self_loop'] = structure_gen_cfg[MetaData.PARAMS].get('has_self_loop', False) + if perform_fit: + generator.fit(graph, is_directed=is_directed) + + if generator_dump_path and perform_fit: + generator.save(generator_dump_path) + + if return_graph: + return (generator, gen_info), graph, graph_src_set + + return generator, gen_info + + def _fit_aligners(self, aligner_cfgs, graphs_to_process, features_to_align): + + aligners = [] + for aligner_cfg in aligner_cfgs: + aligner_class = aligner_classes[aligner_cfg[MetaData.TYPE]] + + aligner_graphs = {graph_name: graphs_to_process[graph_name] for graph_name in aligner_cfg[MetaData.GRAPHS]} + aligner_node_features = {feature_name: features_to_align[MetaData.NODES][feature_name] + for feature_name in aligner_cfg[MetaData.NODES]} + aligner_edge_features = {feature_name: features_to_align[MetaData.EDGES][feature_name] + for feature_name in aligner_cfg[MetaData.EDGES]} + aligner = aligner_class(**aligner_cfg[MetaData.PARAMS]) + aligner.fit(aligner_graphs, aligner_node_features, aligner_edge_features) + + aligners.append(( + aligner, + { + graph_name: { + MetaData.SRC_NODE_TYPE: graph_info[MetaData.SRC_NODE_TYPE], + MetaData.DST_NODE_TYPE: graph_info[MetaData.DST_NODE_TYPE] + } + for graph_name, graph_info in aligner_graphs.items() + } + )) + + del features_to_align + del graphs_to_process + return aligners + + def fit( + self, + ): + """Fit the synthesizer on graph. + """ + + self.structure_generators = {} + self.tabular_generators = {MetaData.NODES: {}, MetaData.EDGES: {}} + self.aligners = [] + + graphs_to_process = {} + features_to_align = {MetaData.NODES: {}, MetaData.EDGES: {}} + + if MetaData.ALIGNERS in self.configuration: + for aligner_cfg in self.configuration[MetaData.ALIGNERS]: + for graph_name in aligner_cfg[MetaData.GRAPHS]: + graphs_to_process[graph_name] = None + + for part in [MetaData.NODES, MetaData.EDGES]: + if aligner_cfg[part]: + for part_name, feature_names in aligner_cfg[part].items(): + if part_name not in features_to_align[part]: + features_to_align[part][part_name] = { + MetaData.FEATURES_LIST: set(), + } + features_to_align[part][part_name][MetaData.FEATURES_LIST] |= set(feature_names) + + self.timer.start_counter('fit') + self.timer.start_counter('fit_nodes') + for node_type in self.configuration[MetaData.NODES]: + node_name = node_type[MetaData.NAME] + + if MetaData.TABULAR_GENERATORS in node_type: + self.timer.start_counter(f'fit_node_{node_name}') + + if node_name in features_to_align[MetaData.NODES]: + self.tabular_generators[MetaData.NODES][node_name], (features_data, cat_cols) = \ + self._fit_tabular_generators( + node_type[MetaData.TABULAR_GENERATORS], node_type[MetaData.FEATURES], MetaData.NODES, + features_to_return=list(features_to_align[MetaData.NODES][node_name][MetaData.FEATURES_LIST]) + ) + features_to_align[MetaData.NODES][node_name][MetaData.FEATURES_DATA] = features_data + features_to_align[MetaData.NODES][node_name][MetaData.CATEGORICAL_COLUMNS] = cat_cols + else: + self.tabular_generators[MetaData.NODES][node_name] = self._fit_tabular_generators( + node_type[MetaData.TABULAR_GENERATORS], node_type[MetaData.FEATURES], MetaData.NODES + ) + self.timer.end_counter(f'fit_node_{node_name}', + f'NODE {node_name} FIT TOOK') + self.timer.end_counter('fit_nodes', 'FIT NODES TOOK') + + self.timer.start_counter('fit_edges') + for edge_type in self.configuration[MetaData.EDGES]: + edge_name = edge_type[MetaData.NAME] + + if MetaData.STRUCTURE_GENERATOR in edge_type: + self.timer.start_counter(f'fit_edges_struct_{edge_name}') + if edge_name in graphs_to_process: + graphs_to_process[edge_name] = { + MetaData.SRC_NODE_TYPE: edge_type[MetaData.SRC_NODE_TYPE], + MetaData.DST_NODE_TYPE: edge_type[MetaData.DST_NODE_TYPE], + } + self.structure_generators[edge_name], \ + graphs_to_process[edge_name][MetaData.STRUCTURE_DATA], \ + graphs_to_process[edge_name]['src_size'] = self._fit_structural_generator(edge_type, return_graph=True) + else: + self.structure_generators[edge_name] = self._fit_structural_generator(edge_type) + + self.timer.end_counter(f'fit_edges_struct_{edge_name}', + f'EDGE {edge_name} STRUCTURAL FIT TOOK') + + if MetaData.TABULAR_GENERATORS in edge_type: + self.timer.start_counter(f'fit_edges_tabular_{edge_name}') + if edge_name in features_to_align[MetaData.EDGES]: + self.tabular_generators[MetaData.EDGES][edge_name], (features_data, cat_cols) = \ + self._fit_tabular_generators( + edge_type[MetaData.TABULAR_GENERATORS], edge_type[MetaData.FEATURES], MetaData.EDGES, + features_to_return=list(features_to_align[MetaData.EDGES][edge_name][MetaData.FEATURES_LIST]) + ) + features_to_align[MetaData.EDGES][edge_name][MetaData.FEATURES_DATA] = features_data + features_to_align[MetaData.EDGES][edge_name][MetaData.CATEGORICAL_COLUMNS] = cat_cols + else: + self.tabular_generators[MetaData.EDGES][edge_name] = self._fit_tabular_generators( + edge_type[MetaData.TABULAR_GENERATORS], edge_type[MetaData.FEATURES], MetaData.EDGES + ) + self.timer.end_counter(f'fit_edges_tabular_{edge_name}', + f'EDGE {edge_name} TABULAR FIT TOOK') + + if MetaData.ALIGNERS in self.configuration: + self.aligners = self._fit_aligners(self.configuration[MetaData.ALIGNERS], + graphs_to_process, + features_to_align) + + self.timer.end_counter('fit_edges', 'FIT EDGES TOOK') + self.timer.end_counter('fit', 'FIT TOOK') + + def _generate_tabular_data(self, tabular_generators, num_samples, features_path, name): + + merge_data = features_path.endswith('.csv') or features_path.endswith('.parquet') + + if self.aligners: + assert merge_data + + generated_dfs = [] + + for tab_gen_id, (tab_gen, gen_info) in enumerate(tabular_generators): + + use_memmap = False + if merge_data: + save_path = os.path.join(self.save_path, 'temp_tab_gen_dir') + fname = f"{name}_{tab_gen_id}" if len(tabular_generators) > 1 else name + else: + save_path = os.path.join(self.save_path, features_path) + fname = 'chunk' + + os.makedirs(save_path, exist_ok=True) + + if gen_info['feature_file'] and gen_info['feature_file'].endswith('.npy') and tab_gen.supports_memmap: + use_memmap = True + fname = gen_info['feature_file'] + + feature_files = tabular_chunk_sample_generation( + tab_gen, + n_samples=num_samples, + save_path=save_path, + fname=fname, + num_workers=self.num_workers, + use_memmap=use_memmap, + verbose=self.verbose + ) + + if merge_data: + generated_df = merge_dataframe_files(feature_files, format='parquet') + generated_dfs.append(generated_df) + shutil.rmtree(save_path) + + if merge_data: + generated_dfs = pd.concat(generated_dfs, axis=1) + dump_dataframe(generated_dfs, os.path.join(self.save_path, features_path), format=None) + gc.collect() + + def generate( + self, + return_data=False, + **kwargs, + ): + """ Generates graph + + Args: + return_data(bool): if true load the generated data into the output configuration + + """ + node_type_to_node_counts = {node_type[MetaData.NAME]: node_type[MetaData.COUNT] + for node_type in self.configuration[MetaData.NODES]} + edge_type_to_edge_info = {edge_type[MetaData.NAME]: edge_type + for edge_type in self.configuration[MetaData.EDGES]} + + output_config = self.configuration.copy() + + edge_type_name_to_idx = {edge_info[MetaData.NAME]: idx + for idx, edge_info in enumerate(output_config[MetaData.EDGES])} + node_type_name_to_idx = {node_info[MetaData.NAME]: idx + for idx, node_info in enumerate(output_config[MetaData.NODES])} + + self.timer.start_counter("gen_s") + for edge_type_name, (structure_generator, gen_info) in self.structure_generators.items(): + self.timer.start_counter(f'gen_edges_struct_{edge_type_name}') + edge_info = edge_type_to_edge_info[edge_type_name] + + generated_graph_path = ensure_path(os.path.join(self.save_path, edge_info[MetaData.STRUCTURE_PATH])) + + merge_data = generated_graph_path.endswith('.csv') or \ + generated_graph_path.endswith('.parquet') + + use_memmap = generated_graph_path.endswith('.npy') + + if not merge_data and not use_memmap: + os.makedirs(generated_graph_path, exist_ok=True) + + if gen_info['is_bipartite']: + num_nodes_src_set = node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]] \ + if node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]] > -1 \ + else gen_info['num_nodes_src_set'] + num_nodes_dst_set = node_type_to_node_counts[edge_info[MetaData.DST_NODE_TYPE]] \ + if node_type_to_node_counts[edge_info[MetaData.DST_NODE_TYPE]] > -1 \ + else gen_info['num_nodes_dst_set'] + graph, src_nodes, dst_nodes = structure_generator.generate( + num_edges_dst_src=gen_info['num_edges'], + num_edges_src_dst=gen_info['num_edges'], + num_nodes_src_set=num_nodes_src_set, + num_nodes_dst_set=num_nodes_dst_set, + is_directed=gen_info['is_directed'], + noise=gen_info.get('noise', 0.5), + return_node_ids=True, + apply_edge_mirroring=False, + transform_graph=False, + save_path=None if merge_data else generated_graph_path, + ) + + node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]] = max( + node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]], + src_nodes.max() + 1 + ) + node_type_to_node_counts[edge_info[MetaData.DST_NODE_TYPE]] = max( + node_type_to_node_counts[edge_info[MetaData.DST_NODE_TYPE]], + dst_nodes.max() + 1 + ) + else: + num_nodes = node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]] \ + if node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]] > -1 \ + else gen_info['num_nodes'] + + graph, node_ids = structure_generator.generate( + num_nodes=num_nodes, + num_edges=gen_info['num_edges'], + is_directed=gen_info['is_directed'], + has_self_loop=gen_info.get('has_self_loop', False), + noise=gen_info.get('noise', 0.5), + return_node_ids=True, + save_path=None if merge_data else generated_graph_path + ) + node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]] = max( + node_type_to_node_counts[edge_info[MetaData.SRC_NODE_TYPE]], + node_ids.max() + 1 + ) + + if merge_data or not self.gpu: + dump_generated_graph(generated_graph_path, graph) + output_config[MetaData.EDGES][edge_type_name_to_idx[edge_type_name]][MetaData.COUNT] = \ + len(graph) if merge_data or use_memmap else int(graph) + + del graph + gc.collect() + self.timer.end_counter(f'gen_edges_struct_{edge_type_name}', + f'EDGE {edge_type_name} STRUCT GEN TOOK') + self.timer.end_counter("gen_s", "GEN STRUCT TOOK") + + for node_type_name, counts in node_type_to_node_counts.items(): + output_config[MetaData.NODES][node_type_name_to_idx[node_type_name]][MetaData.COUNT] = int(counts) + + self.timer.start_counter("gen_t_nodes") + for node_type_name, tabular_generators in self.tabular_generators[MetaData.NODES].items(): + num_nodes = node_type_to_node_counts[node_type_name] + features_path = output_config[MetaData.NODES][node_type_name_to_idx[node_type_name]][MetaData.FEATURES_PATH] + self._generate_tabular_data(tabular_generators, num_nodes, features_path, node_type_name) + self.timer.end_counter("gen_t_nodes", "GEN TABULAR NODE FEATURES TOOK") + + self.timer.start_counter("gen_t_edges") + for edge_type_name, tabular_generators in self.tabular_generators[MetaData.EDGES].items(): + num_edges = output_config[MetaData.EDGES][edge_type_name_to_idx[edge_type_name]][MetaData.COUNT] + features_path = output_config[MetaData.EDGES][edge_type_name_to_idx[edge_type_name]][MetaData.FEATURES_PATH] + self._generate_tabular_data(tabular_generators, num_edges, features_path, edge_type_name) + self.timer.end_counter("gen_t_edges", "GEN TABULAR EDGE FEATURES TOOK") + + self.timer.start_counter("gen_alignment") + + if self.aligners: + for aligner, graphs_info in self.aligners: + + graphs_data = {} + for graph_name, graph_info in graphs_info.items(): + graphs_data[graph_name] = graph_info.copy() + if graph_info[MetaData.SRC_NODE_TYPE] != graph_info[MetaData.DST_NODE_TYPE]: + graphs_data[graph_name]['src_size'] = \ + output_config[MetaData.NODES][node_type_name_to_idx[graph_info[MetaData.SRC_NODE_TYPE]]][ + MetaData.COUNT] + graphs_data[graph_name][MetaData.STRUCTURE_DATA] = load_graph(os.path.join( + self.save_path, + output_config[MetaData.EDGES][edge_type_name_to_idx[graph_name]][MetaData.STRUCTURE_PATH] + )) + + node_features_data = { + node_name: load_dataframe(os.path.join( + self.save_path, + output_config[MetaData.NODES][node_type_name_to_idx[node_name]][MetaData.FEATURES_PATH]), + feature_info=output_config[MetaData.NODES][node_type_name_to_idx[node_name]][MetaData.FEATURES] + ) + for node_name in aligner.features_to_correlate_node + } + + edge_features_data = { + edge_name: load_dataframe(os.path.join( + self.save_path, + output_config[MetaData.EDGES][edge_type_name_to_idx[edge_name]][MetaData.FEATURES_PATH]), + feature_info=output_config[MetaData.EDGES][edge_type_name_to_idx[edge_name]][MetaData.FEATURES] + ) + for edge_name in aligner.features_to_correlate_edge + } + + aligned_data = aligner.align( + graphs_data, + node_features_data, + edge_features_data, + ) + + for node_name, tab_data in aligned_data[MetaData.NODES].items(): + dump_dataframe(tab_data, os.path.join( + self.save_path, + output_config[MetaData.NODES][node_type_name_to_idx[node_name]][MetaData.FEATURES_PATH] + ), format=None + ) + for edge_name, tab_data in aligned_data[MetaData.EDGES].items(): + dump_dataframe(tab_data, os.path.join( + self.save_path, + output_config[MetaData.EDGES][edge_type_name_to_idx[edge_name]][MetaData.FEATURES_PATH] + ), format=None + ) + self.timer.end_counter("gen_alignment", "GEN ALIGNMENT TAKE") + + with open(os.path.join(self.save_path, 'graph_metadata.json'), 'w') as f: + json.dump(output_config, f, indent=4) + + output_config[MetaData.PATH] = self.save_path + + if return_data: + for node_info in output_config[MetaData.NODES]: + if node_info[MetaData.FEATURES_PATH]: + node_info[MetaData.FEATURES_DATA] = load_dataframe(os.path.join( + self.save_path, node_info[MetaData.FEATURES_PATH] + )) + + for edge_info in output_config[MetaData.EDGES]: + if edge_info[MetaData.FEATURES_PATH]: + edge_info[MetaData.FEATURES_DATA] = load_dataframe(os.path.join( + self.save_path, edge_info[MetaData.FEATURES_PATH] + )) + if edge_info[MetaData.STRUCTURE_PATH]: + edge_info[MetaData.STRUCTURE_DATA] = load_graph(os.path.join( + self.save_path, edge_info[MetaData.STRUCTURE_PATH], + )) + return output_config + return output_config + + def save(self, path): + """ saves the synthesizer to disk + + Args: + path (str): The path to save the synthesizer to + """ + + meta_data = { + "configuration": self.configuration.copy(), + "timer_path": self.timer.path, + "num_workers": self.num_workers, + "save_path": self.save_path, + "gpu": self.gpu, + "verbose": self.verbose, + } + if not os.path.exists(path): + os.makedirs(path) + + if self.structure_generators: + meta_data['struct_gens'] = {} + for edge_name, (struct_gen, gen_info) in self.structure_generators.items(): + struct_gen.save(os.path.join(path, f'struct_gen_{edge_name}')) + meta_data['struct_gens'][edge_name] = { + 'gen_info': gen_info, + 'object_path': get_object_path(struct_gen) + } + + if self.tabular_generators: + meta_data['tab_gens'] = {} + for part, part_gens in self.tabular_generators.items(): + meta_data['tab_gens'][part] = {} + for part_name, tab_gens in part_gens.items(): + meta_data['tab_gens'][part][part_name] = [] + for idx, (tab_gen, gen_info) in enumerate(tab_gens): + tab_gen.save(os.path.join(path, f'tab_gen_{part}_{part_name}_{idx}')) + meta_data['tab_gens'][part][part_name].append({ + 'gen_info': gen_info, + 'object_path': get_object_path(tab_gen) + }) + + if self.aligners: + meta_data['aligners'] = [] + for idx, (aligner, graphs_info) in enumerate(self.aligners): + aligner.save(os.path.join(path, f'aligner_{idx}')) + meta_data['aligners'].append( + { + 'object_path': get_object_path(aligner), + 'graphs_info': graphs_info, + } + ) + + with open(os.path.join(path, "synthesizer_metadata.json"), "w") as fp: + json.dump(meta_data, fp, indent=4) + + @classmethod + def load(cls, path): + """ load up a saved synthesizer object from disk. + + Args: + path (str): The path to load the synthesizer from + """ + + with open(os.path.join(path, "synthesizer_metadata.json"), 'r') as f: + meta_data = json.load(f) + struct_gens = meta_data.pop('struct_gens', {}) + tab_gens = meta_data.pop('tab_gens', {}) + aligners = meta_data.pop('aligners', {}) + + instance = cls(**meta_data) + + if struct_gens: + instance.structure_generators = { + edge_name: ( + dynamic_import(data['object_path']).load( + os.path.join(path, f'struct_gen_{edge_name}') + ), + data['gen_info'], + ) + for edge_name, data in struct_gens.items() + } + + if tab_gens: + instance.tabular_generators = { + part: { + part_name: [ + ( + dynamic_import(data['object_path']).load( + os.path.join(path, f'tab_gen_{part}_{part_name}_{idx}') + ), + data['gen_info'], + ) + for idx, data in enumerate(part_gens) + ] + for part_name, part_gens in part_data.items() + } + for part, part_data in tab_gens.items() + } + + if aligners: + instance.aligners = [ + ( + dynamic_import(data['object_path']).load( + os.path.join(path, f'aligner_{idx}') + ), + data['graphs_info'], + ) + for idx, data in enumerate(aligners) + ] + return instance diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/__init__.py new file mode 100644 index 000000000..845f5ef69 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/__init__.py @@ -0,0 +1,17 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .utils import * +from .io_utils import * diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/cugraph.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/cugraph.py new file mode 100644 index 000000000..3d737de7b --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/cugraph.py @@ -0,0 +1,18 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +def import_cugraph(): + """ Lazy import of cugraph. """ + import cugraph + return cugraph diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/io_utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/io_utils.py new file mode 100644 index 000000000..a4f93dd57 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/io_utils.py @@ -0,0 +1,195 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import os +from collections import defaultdict + +from pathlib import Path, PosixPath +from typing import Optional, Union, List + +import numpy as np +import pandas as pd +from tqdm import tqdm + +from syngen.utils.utils import infer_operator +from syngen.utils.types import NDArray +from syngen.utils.types import MetaData + +logger = logging.getLogger(__name__) +log = logger + + +def dump_dataframe(data: pd.DataFrame, save_path: Union[PosixPath, str], format: Optional[str] = 'parquet') -> None: + + if save_path.endswith('.csv'): + format = 'csv' + if save_path.endswith('.parquet'): + format = 'parquet' + + log.info(f"writing to file {save_path} {format}") + + if format == 'parquet': + data.to_parquet(save_path, compression=None, index=False) + elif format == 'csv': + data.to_csv(save_path, index=False) + else: + raise ValueError(f'unsupported file_format: {format}, expected `csv` or `parquet`') + + +def dump_generated_graph(path: Union[PosixPath, str], graph: NDArray, format: str = 'npy') -> None: + operator = infer_operator(graph) + + if path.endswith('.npy'): + format = 'npy' + if path.endswith('.csv'): + format = 'csv' + if path.endswith('.parquet'): + format = 'parquet' + + if format is None: + raise ValueError() + + if format == 'npy': + operator.save(path, graph) + elif format == 'csv': + operator.savetxt(path, graph, fmt='%i', delimiter='\t') + elif format == 'parquet': + dump_dataframe(pd.DataFrame(graph, columns=['src', 'dst'], copy=False), path) + else: + raise ValueError(f'unsupported file_format: {format}, expected `npy`, `parquet` or `csv`') + + +def merge_dataframe_files(file_paths: List[Union[PosixPath, str]], format='csv') -> pd.DataFrame: + if format == 'parquet': + dfs = [pd.read_parquet(fn) for fn in file_paths] + elif format == 'csv': + dfs = [pd.read_csv(fn) for fn in file_paths] + else: + raise ValueError(f'unsupported file_format: {format}, expected `csv` or `parquet`') + return pd.concat(dfs, axis=0, ignore_index=True) + + +def load_dataframe(path: Union[PosixPath, str], format: Optional[str] = None, feature_info: Optional = None) -> pd.DataFrame: + + if path.endswith('.parquet'): + format = 'parquet' + elif path.endswith('.csv'): + format = 'csv' + elif path.endswith('.npy'): + format = 'npy' + elif os.path.isdir(path): + format = 'dir' + + if format is None: + raise ValueError() + + if format == 'parquet': + return pd.read_parquet(path) + if format == 'csv': + return pd.read_csv(path) + + assert feature_info is not None, '`npy` and `dir` require specified feature_info' + + if format == 'npy': + return pd.DataFrame(np.load(path, mmap_mode='r'), columns=[f[MetaData.NAME] for f in feature_info], copy=False) + if format == 'dir': + file_names_to_features = defaultdict(list) + for fi in feature_info: + file_names_to_features[fi[MetaData.FEATURE_FILE]].append(fi) + return pd.concat( + [load_dataframe(os.path.join(path, fn), feature_info=file_names_to_features[fn]) + for fn in os.listdir(path)], axis=1, copy=False) + + +def load_graph(path: Union[str, PosixPath], format: Optional[str] = None) -> np.ndarray: + + if path.endswith('.parquet'): + format = 'parquet' + elif path.endswith('.csv'): + format = 'csv' + elif path.endswith('.npy'): + format = 'npy' + + if format is None: + raise ValueError() + + if format == 'parquet': + return pd.read_parquet(path).values + if format == 'csv': + return pd.read_csv(path).values + if format == 'npy': + return np.load(path, mmap_mode='c') + + +def write_csv_file_listener(save_path: Union[str, PosixPath], save_name: str, queue): + KILL_SIG = "kill" + save_path = Path(save_path) / f"{save_name}.csv" + first_file = True + while True: + # - keep listening until `kill` signal + m = queue.get() + if m == KILL_SIG: + break + elif type(m) == pd.DataFrame: + if first_file: + m.to_csv(save_path, index=False, header=True) + first_file = False + else: + m.to_csv(save_path, mode="append", index=False, header=False) + else: + raise Exception(f"{m} is not supported") + + +def merge_csv_files( + file_paths: List[Union[str, PosixPath]], + save_path: Union[str, PosixPath], + save_name: str = "samples", + header: bool = True, + remove_original_files: bool = True, +) -> None: + + """ + Merges CSV files into a single large CSV file + + Args: + file_paths (str): a list of paths to individual csv files + save_path (str): a path to directory to save merged csv file + save_name (str): file name of merged csv file + Returns: + None + """ + + save_path = Path(save_path) + record_header = False + + if header: + record_header = True + + with open(save_path / f"{save_name}", "w") as out_file: + for i, fp in enumerate(tqdm(file_paths)): + with open(fp, "r") as csv: + for i, l in enumerate(csv): + if i == 0 and record_header: + out_file.write(l + "\n") + record_header = False + continue + elif i == 0: + continue + else: + out_file.write(l + "\n") + + if remove_original_files: + for f in file_paths: + os.remove(f) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/memory_manager.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/memory_manager.py new file mode 100644 index 000000000..40f7576e3 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/memory_manager.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pynvml +import psutil + + +class MemoryManager(object): + + def __init__(self, gpus=None): + pynvml.nvmlInit() + + def __new__(cls): + if not hasattr(cls, 'instance'): + cls.instance = super(MemoryManager, cls).__new__(cls) + return cls.instance + + def get_available_gpus(self): + return pynvml.nvmlDeviceGetCount() + + def get_memory_info_on_gpu(self, gpu_id): + h = pynvml.nvmlDeviceGetHandleByIndex(gpu_id) + return pynvml.nvmlDeviceGetMemoryInfo(h) + + def get_min_available_across_gpus_memory(self, gpus): + total = None + used = 0 + for g_id in range(gpus): + info = self.get_memory_info_on_gpu(g_id) + if total is None: + total = info.total + else: + assert total == info.total + used = max(used, info.used) + return total - used + + def get_available_virtual_memory(self): + return psutil.virtual_memory().available diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/__init__.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/__init__.py new file mode 100644 index 000000000..0aa3edebe --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/__init__.py @@ -0,0 +1,20 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# flake8: noqa +from .array_type import NDArray +from .column_type import ColumnType +from .dataframe_type import DataFrameType +from .metadata import MetaData +from .data_source_input_type import DataSourceInputType diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/array_type.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/array_type.py new file mode 100644 index 000000000..b0c4ec8a3 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/array_type.py @@ -0,0 +1,20 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import TypeVar + +import cupy as cp +import numpy as np + +NDArray = TypeVar('NDArray', np.ndarray, cp.ndarray) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/column_type.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/column_type.py new file mode 100644 index 000000000..672f6849a --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/column_type.py @@ -0,0 +1,22 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .str_enum import StrEnum + + +class ColumnType(StrEnum): + CONTINUOUS = "continuous" + CATEGORICAL = "categorical" + MIXED = "mixed" + DISCRETE = "discrete" diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/data_source_input_type.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/data_source_input_type.py new file mode 100644 index 000000000..ac057f7e6 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/data_source_input_type.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from enum import Enum + + +class DataSourceInputType(Enum): + DATASET = "dataset", "ds" + EDGE_LIST = "edge_list", 'el' + RANDOM = "random", 'rnd' + CONFIGURATION = "configuration", 'cfg' + DATA = "data", 'data' + + def __new__(cls, *values): + obj = object.__new__(cls) + obj._value_ = values[0] + for other_value in values[1:]: + cls._value2member_map_[other_value] = obj + obj._all_values = values + return obj + + def __eq__(self, other): + return super().__eq__(self._value2member_map_[other]) diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/dataframe_type.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/dataframe_type.py new file mode 100644 index 000000000..beab1e5f2 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/dataframe_type.py @@ -0,0 +1,23 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Union + +import cudf +import pandas + +DataFrameType = Union[ + cudf.DataFrame, + pandas.DataFrame, +] diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/metadata.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/metadata.py new file mode 100644 index 000000000..3bca94eef --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/metadata.py @@ -0,0 +1,77 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +from .str_enum import StrEnum + + +class MetaData(StrEnum): + PATH = "path" + EDGES = "edges" + NODES = "nodes" + ALIGNERS = "[gen]aligners" + + GRAPHS = "graphs" + + NAME = "name" + COUNT = "count" + + NODE_DATA = "node_data" + EDGE_DATA = "edge_data" + TYPE = "type" + DTYPE = "dtype" + SRC = "src" + SRC_NAME = "src_name" + SRC_NODE_TYPE = "src_node_type" + + DST = "dst" + DST_NAME = "dst_name" + DST_NODE_TYPE = "dst_node_type" + + NODE_NAME = "node_name" + NODE_COLUMNS = "node_columns" + EDGE_NAME = "edge_name" + LABELS = "labels" + FEATURES = "features" + FEATURES_PATH = "features_path" + FEATURES_DATA = "features_data" + FEATURE_TYPE = "feature_type" + FEATURE_FILE = "feature_file" + FILENAME_PREFIX = "filename_prefix" + STRUCTURE_PATH = "structure_path" + STRUCTURE_DATA = "structure_data" + + NODE_FEAT = "node_feat" + EDGE_FEAT = "edge_feat" + TRAIN_MASK = "train_mask" + VAL_MASK = "val_mask" + TEST_MASK = "test_mask" + + CONTINUOUS = "continuous" + CATEGORICAL = "categorical" + + CONTINUOUS_COLUMNS = "continuous_columns" + CATEGORICAL_COLUMNS = "categorical_columns" + UNDIRECTED = "undirected" + DIRECTED = "directed" + + # generation related keys + STRUCTURE_GENERATOR = "[gen]structure_generator" + TABULAR_GENERATORS = "[gen]tabular_generators" + DATA_SOURCE = "data_source" + FEATURES_LIST = "features_list" + PARAMS = "params" + DUMP_PATH = "dump_path" + diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/str_enum.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/str_enum.py new file mode 100644 index 000000000..b0de6fff7 --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/types/str_enum.py @@ -0,0 +1,33 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import enum + + +class StrEnum(str, enum.Enum): + def __new__(cls, *args): + for arg in args: + if not isinstance(arg, (str, enum.auto)): + raise TypeError( + "Values of StrEnums must be strings: {} is a {}".format( + repr(arg), type(arg) + ) + ) + return super().__new__(cls, *args) + + def __str__(self): + return self.value + + def _generate_next_value_(name, *_): + return name diff --git a/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/utils.py b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/utils.py new file mode 100644 index 000000000..be72cb74c --- /dev/null +++ b/Tools/DGLPyTorch/SyntheticGraphGeneration/syngen/utils/utils.py @@ -0,0 +1,190 @@ +# Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import time +import logging +import importlib +from pathlib import PosixPath +from typing import Optional, Union + +import cudf +import cupy +import dask.dataframe as dd +import dask_cudf +import cupy as cp +import numpy as np +import pandas as pd +import os + +from syngen.utils.types import DataFrameType, NDArray + +logger = logging.getLogger(__name__) +log = logger + + +class CustomTimer: + """Wraps `time` module and adds tagging for multiple timers + + Example: + timer = CustomTimer() + timer.start_counter("tag") + # - do a series of operation + # ... + # - end of operations + timer.end_counter("tag", "tag timer has ended") + + Args: + path (Optional[str]) + + """ + + def __init__(self, path: Optional[Union[PosixPath, str]] = str, verbose: bool = False): + self.path = path + self.verbose = verbose + self.timers = {} + self.f = None + if self.path: + self.f = open(self.path, "w") + + def start_counter(self, key: str): + self.timers[key] = time.perf_counter() + + def end_counter(self, key: str, msg: str): + end = time.perf_counter() + start = self.timers.get(key, None) + + if start is None: + return + message_string = f"{msg}: {end - start:.2f}\n" + if self.f: + self.f.write(message_string) + if self.verbose: + print(message_string, end='') + + def maybe_close(self): + if self.f: + self.f.close() + + +def current_ms_time(): + return round(time.time() * 1000) + + +def to_ndarray(df: DataFrameType) -> NDArray: + """ Returns potentially distributed data frame to its in-memory equivalent array. """ + if isinstance(df, (cudf.DataFrame, pd.DataFrame)): + return df.values + elif isinstance(df, (dask_cudf.DataFrame, dd.DataFrame)): + return df.compute().values + else: + raise NotImplementedError(f'Conversion of type {type(df)} is not supported') + + +def df_to_pandas(df): + """ Converts `DataFrameType` to `pandas.DataFrame` + + Args: + df (DataFrameType): the DataFrame to be converted + """ + if isinstance(df, cudf.DataFrame): + pddf = df.to_pandas() + elif isinstance(df, dask_cudf.DataFrame): + pddf = pd.DataFrame( + cupy.asnumpy(df.values.compute()), columns=df.columns + ) + elif isinstance(df, pd.DataFrame): + pddf = df + else: + raise ValueError(f"DataFrame type {type(df)} not supported") + return pddf + + +def df_to_cudf(df: DataFrameType): + """ Converts `DataFrameType` to `cudf.DataFrame` + + Args: + df (DataFrameType): the DataFrame to be converted + """ + if isinstance(df, cudf.DataFrame): + pass + elif isinstance(df, dask_cudf.DataFrame): + df = cudf.DataFrame( + cupy.asnumpy(df.values.compute()), columns=df.columns + ) + elif isinstance(df, pd.DataFrame): + df = cudf.from_pandas(df) + else: + raise ValueError(f"DataFrameType type {type(df)} not supported") + return df + + +def df_to_dask_cudf(df: DataFrameType, + chunksize: Optional[int] = None): + """ Converts `DataFrameType` to `dask_cudf.DataFrame` + + Args: + df (DataFrameType): the DataFrame to be converted + chunksize (int): dask chunk size. (default: min(1e6, len(df) // num_devices)) + """ + if chunksize is None: + chunksize = min( + int(1e6), len(df) // cupy.cuda.runtime.getDeviceCount() + ) + if isinstance(df, cudf.DataFrame): + df = dask_cudf.from_cudf(df, chunksize=chunksize) + elif isinstance(df, dask_cudf.DataFrame): + pass + elif isinstance(df, pd.DataFrame): + df = cudf.from_pandas(df) + df = dask_cudf.from_cudf(df, chunksize=chunksize) + else: + raise ValueError(f"DataFrameType type {type(df)} not supported") + return df + + +def dynamic_import(object_path): + """Import an object from its full path.""" + if isinstance(object_path, str): + parent, obj_name = object_path.rsplit(".", 1) + try: + parent = importlib.import_module(parent) + except ImportError: + raise ImportError(f"Could not import {object_path}") + + return getattr(parent, obj_name) + + return object_path + + +def get_object_path(obj): + return obj.__class__.__module__ + '.' + obj.__class__.__name__ + + +def ensure_path(path: Union[str, PosixPath]): + if not os.path.exists(os.path.dirname(path)): + os.makedirs(os.path.dirname(path)) + return path + +def infer_operator(ndarray: NDArray): + """ Returns array backend module (numpy or cupy). """ + if isinstance(ndarray, np.ndarray): + return np + elif isinstance(ndarray, cp.ndarray): + return cp + else: + logger.warning( + 'Detected array of type %s, while one of (%s) was expected. Defaulting to using numpy', + type(ndarray), 'numpy.ndarray, cupy.ndarray', + ) + return np diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/.dockerignore b/Tools/PyTorch/TimeSeriesPredictionPlatform/.dockerignore index de69b6856..937a02b3c 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/.dockerignore +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/.dockerignore @@ -6,3 +6,7 @@ .gitignore Dockerfile .dockerignore +/outputs/ +/datasets/ +/multirun/ +/notebooks/ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/.gitignore b/Tools/PyTorch/TimeSeriesPredictionPlatform/.gitignore index 41d0e9e04..597ee33b6 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/.gitignore +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/.gitignore @@ -3,3 +3,5 @@ __pycache__ /outputs/ *.zip /datasets/*/ +/datasets/ +/notebooks/ \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/Dockerfile b/Tools/PyTorch/TimeSeriesPredictionPlatform/Dockerfile index 9144a4d71..2603220b5 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/Dockerfile +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/Dockerfile @@ -1,5 +1,19 @@ +# Copyright 2021-2024 NVIDIA CORPORATION + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + #SPDX-License-Identifier: Apache-2.0 -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.04-py3 +ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:22.12-py3 FROM ${FROM_IMAGE_NAME} @@ -30,26 +44,31 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* -# Install perf_client required library RUN apt-get update && \ apt-get install -y libb64-dev libb64-0d curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -# Set workdir and python path WORKDIR /workspace ENV PYTHONPATH /workspace +RUN rm /usr/lib/libxgboost.so + ADD requirements.txt /workspace/requirements.txt ADD triton/requirements.txt /workspace/triton/requirements.txt RUN pip install -r /workspace/requirements.txt RUN pip install -r /workspace/triton/requirements.txt RUN pip install nvidia-pyindex RUN pip install git+https://github.com/NVIDIA/dllogger#egg=dllogger -RUN pip install --no-cache-dir -r requirements.txt -f https://data.dgl.ai/wheels/repo.html +RUN pip install --no-cache-dir -r requirements.txt +RUN pip install dgl==1.0.1 -f https://data.dgl.ai/wheels/cu117/repo.html -# Add model files to workspace -ADD . /workspace +ADD ./hydra_plugins /workspace/hydra_plugins +RUN pip install /workspace/hydra_plugins/hydra_optuna_sweeper/ +RUN pip install /workspace/hydra_plugins/hydra_joblib_launcher/ +RUN pip install /workspace/hydra_plugins/hydra_multiprocessing_launcher/ +RUN pip install /workspace/hydra_plugins/hydra_torchrun_launcher/ +RUN cp /workspace/hydra_plugins/optuna_sweeper.py /usr/local/lib/python3.8/dist-packages/hydra/plugins/sweeper.py -RUN pip install -e distributed_launcher +ADD . /workspace RUN rm -rf examples docker-examples tutorials diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/LICENSE b/Tools/PyTorch/TimeSeriesPredictionPlatform/LICENSE index 0a8c444de..c1a81fee0 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/LICENSE +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2021-2022 NVIDIA Corporation + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/NOTICE b/Tools/PyTorch/TimeSeriesPredictionPlatform/NOTICE index 5b55d6904..39c73b0f1 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/NOTICE +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/NOTICE @@ -190,7 +190,7 @@ This repository contains code from https://github.com/rwightman/pytorch-image-mo same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2021-2022 NVIDIA Corporation + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/README.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/README.md index 555abfd4c..aae2800be 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/README.md +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/README.md @@ -2,17 +2,57 @@ Time-series prediction is a common problem in multiple domains for various applications, including retail, industry, smart cities, and financial services. Research in the time-series field is growing exponentially, with hundreds of deep learning time-series forecasting paper submissions to ICML, ECML, ITISE, and multiple journals every year. However, there is currently no common framework to compare the accuracy and performance of all the models from the industry or academia. +## Table Of Contents +- [Solution overview](#solution-overview) + * [Time-Series Prediction Platform architecture](#time-series-prediction-platform-architecture) + * [Default configuration](#default-configuration) + * [Feature support matrix](#feature-support-matrix) + * [Features](#features) + * [Mixed precision training](#mixed-precision-training) + * [Enabling mixed precision](#enabling-mixed-precision) + * [Models](#models) + * [Datasets](#datasets) +- [Setup](#setup) + * [Requirements](#requirements) +- [Quick Start Guide](#quick-start-guide) + * [Getting Started](#getting-started) + * [Adding a new dataset](#adding-a-new-dataset) + * [New dataset example](#new-dataset-example) + * [Adding a new model](#adding-a-new-model) + * [New model example](#new-model-example) +- [Advanced](#advanced) + * [Memory mapping large datasets](#memory-mapping-large-datasets) + * [Running multi-GPU experiments](#running-multi-gpu-experiments) + * [Parallel training](#parallel-training) + * [Running experiments with Exponential Moving Averaging](#running-experiments-with-exponential-moving-averaging) + * [Running experiments with Curriculum Learning](#running-experiments-with-curriculum-learning) + * [Hyperparameter Search](#hyperparameter-search) + * [Custom launchers](#custom-launchers) + * [XGBoost Training](#xgboost-training) + * [Postprocessing of predictions](#postprocessing-of-predictions) + * [Interprete your model](#interprete-your-model) + * [Ensembling](#ensembling) + * [Conversion, Deployment, and Inference](#conversion-deployment-and-inference) + * [Online Inference](#online-inference) + * [Parameters](#parameters) +- [Release notes](#release-notes) + * [Changelog](#changelog) + * [Known issues](#known-issues) +- [Reference](#reference) + * [Cite](#cite) + ## Solution Overview Time-Series Prediction Platform (TSPP) enables users to mix and match datasets and models. In this case, the user has complete control over the following settings and can compare side-by-side results obtained from various solutions. These include: -- Evaluation metrics -- Evaluation datasets -- Prediction horizons -- Prediction sliding window sizes Model choice +- Evaluation metrics +- Evaluation datasets +- Prediction horizons +- Prediction sliding window sizes +- Model choice - Model hyperparameters ### Time-Series Prediction Platform architecture -The platform has the following architecture. +The platform has the following architecture. ![Time-series Prediction Platform architecture @@ -29,23 +69,14 @@ The platform is designed to support multiple data types for input features, incl
-### Default configuration -The TSPP utilizes the default configurations provided by each model for each accompanying dataset. More information on individual model configurations can be found within the respective model repositories. By default, Temporal Fusion Transformer (TFT) is included within the TSPP. - -### Models - - Temporal Fusion Transformers - - XGBoost - - AutoARIMA - - LSTM - ### Feature support matrix -This tool supports the following features: +This tool supports the following features: -| Feature | Time-Series Prediction Platform +| Feature | Time-Series Prediction Platform |-----------------------|-------------------------- -|[Automatic mixed precision (AMP)](https://pytorch.org/docs/stable/amp.html)| Yes -|[Multi-GPU training with (PyTorch DDP)](https://pytorch.org/tutorials/intermediate/ddp_tutorial.html) | Yes -|[TorchScript, ONNX, and TRT conversion and NVIDIA Triton Deployment] | Yes +|[Automatic mixed precision (AMP)](https://pytorch.org/docs/stable/amp.html)| Yes +|[Multi-GPU training with (PyTorch DDP)](https://pytorch.org/tutorials/intermediate/ddp_tutorial.html) | Yes +|[TorchScript, ONNX, and TRT conversion and NVIDIA Triton Deployment](https://github.com/triton-inference-server/server) | Yes #### Features @@ -53,15 +84,13 @@ This tool supports the following features: Multi-GPU training with [PyTorch Distributed Data Parallel](https://pytorch.org/tutorials/intermediate/ddp_tutorial.html) is a mode of computation for PyTorch models that allows operations to be executed across multiple GPUs in parallel to accelerate computation. -**TorchScript, ONNX, and TRT conversion and NVIDIA Triton Deployment** refer to the conversion of a model to the aforementioned formats and the ability to deploy the resulting converted models to an NVIDIA Triton inference server. More detail about this process and native inference can be found in the Advanced tab under the Conversion, Deployment, and Inference subsection. - - +**TorchScript, ONNX, and TRT conversion and NVIDIA Triton Deployment** refer to the conversion of a model to the aforementioned formats and the ability to deploy the resulting converted models to an NVIDIA Triton inference server. More detail about this process and native inference can be found in the Advanced tab under the [Conversion, Deployment, and Inference](#conversion-deployment-and-inference) subsection. ### Mixed precision training Mixed precision is the combined use of different numerical precisions in a computational method. [Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant computational speedup by performing operations in half-precision format while storing minimal information in single-precision to retain as much information as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in NVIDIA Volta, and following with both the NVIDIA Turing and NVIDIA Ampere Architectures, significant training speedups are experienced by switching to mixed precision -- up to 3x overall speedup on the most arithmetically intense model architectures. Using mixed precision training requires two steps: -1. Porting the model to use the FP16 data type where appropriate. +1. Porting the model to use the FP16 data type where appropriate. 2. Adding loss scaling to preserve small gradient values. The ability to train deep learning networks with lower precision was introduced in the NVIDIA Pascal architecture and first supported in [CUDA 8](https://devblogs.nvidia.com/parallelforall/tag/fp16/) in the NVIDIA Deep Learning SDK. @@ -74,10 +103,34 @@ For information about: #### Enabling mixed precision Mixed precision can be enabled by specifying `trainer.config.amp=True` in the launch call. For some cases, when the batch size is small, the overhead of scheduling kernels for mixed precision can be larger than the performance gain from using lower precision, effectively succeeding with lower throughput. + +### Default configuration +The TSPP utilizes the default configurations provided by each model for each accompanying dataset. More information on individual model configurations can be found within the respective model repositories. By default, Temporal Fusion Transformer (TFT) is included within the TSPP. + +### Models + - [Temporal Fusion Transformers](https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/Forecasting/TFT/modeling.py) ( [conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/tft.yaml) ) + - [XGBoost](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tspp_xgboost.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/xgboost.yaml)) + - [AutoARIMA](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/stat_models.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/auto_arima.yaml)) + - [LSTM](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/lstm.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/lstm.yaml)) + - [N-BEATS](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nbeats.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nbeats.yaml)) + - [N-HITS](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nhits.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nhits.yaml)) + - [DeepAR](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/deepar.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/deepar.yaml)) + - [MTGNN](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/mtgnn.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/mtgnn.yaml)) + - [DCRNN](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/models/dcrnn.py) ([conf](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dcrnn.yaml)) + +### Datasets + - [Electricity](https://archive.ics.uci.edu/dataset/321/electricityloaddiagrams20112014) + - [Traffic](https://archive.ics.uci.edu/dataset/204/pems+sf) + - [M5](https://github.com/Mcompetitions/M5-methods) + - [PEMS-BAY](https://pems.dot.ca.gov/?dnode=Clearinghouse) + +**Note**: We don't provide scripts to download `M5` and `PEMS-BAY` datasets, each user is responsible for downloading them from corresponding websites. + +**Note**: Each user is responsible for checking the content of datasets and the applicable licenses and determining if suitable for the intended use. + ## Setup The following section lists the requirements you need to meet to run the Time-Series Prediction Platform. - ### Requirements This repository contains a Dockerfile that extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: @@ -89,21 +142,20 @@ This repository contains a Dockerfile that extends the PyTorch NGC container and For more information about how to get started with NGC containers, refer to the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: - [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) - [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) - -For those unable to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). + For those unable to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). ## Quick start guide ### Getting Started -1. Create a dataset directory. The directory can be arbitrary, and it is recommended not to include it in the TimeSeriesPredictionPlatform directory. This arbitrary directory will be mounted to the TSPP container later. In the following steps, this directory will be referred to as /your/datasets/. +1. Create a dataset directory. The directory can be arbitrary, and it is recommended not to include it in the TimeSeriesPredictionPlatform directory. This arbitrary directory will be mounted to the TSPP container later. In the following steps, this directory will be referred to as `/your/datasets/`. 2. Enter the Deep Learning Examples TSPP repository: ``` cd DeeplearningExamples/Tools/TimeSeriesPredictionPlatform ``` -3. Copy the relevant temporal fusion transformer code to the TSPP: +3. Copy the relevant temporal fusion transformer [code](https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/Forecasting/TFT/modeling.py) to the TSPP: ``` mkdir -p models/tft_pyt/ && cp ../../PyTorch/Forecasting/TFT/modeling.py models/tft_pyt/ ``` @@ -112,17 +164,18 @@ mkdir -p models/tft_pyt/ && cp ../../PyTorch/Forecasting/TFT/modeling.py models/ docker build -t tspp . ``` -5. Next, we will start our container and mount the dataset directory, which means that /workspace/datasets/ points to /your/datasets/. Any changes made to this folder in the docker container are reflected in the original directory and vice versa. If we want to mount additional folders, we can add ‘-v /path/on/local/:/path/in/container/’ to the run command. This will be useful if we want to save the outputs from training or inference once we close the container. To start the docker container: +5. Next, we will start our container and mount the dataset directory, which means that `/workspace/datasets/` points to `/your/datasets/`. Any changes made to this folder in the docker container are reflected in the original directory and vice versa. If we want to mount additional folders, we can add `-v /path/on/local/:/path/in/container/` to the run command. This will be useful if we want to save the outputs from training or inference once we close the container. To start the docker container: ``` docker run -it --gpus all --ipc=host --network=host -v /your/datasets/:/workspace/datasets/ tspp bash ``` -6. After running the previous command, you will be placed inside the docker container in the /workspace directory. Inside the container, download either the `electricity` or `traffic` dataset: +6. After running the previous command, you will be placed inside the docker container in the /workspace directory. Inside the container preprocess `electricity`, `traffic`, `M5` or `pems_bay` dataset. Some of the datasets might need manual download of the data, see [datasets](#datasets): + ``` -python data/script_download_data.py --dataset {dataset_name} --output_dir /workspace/datasets/ +python data/script_preprocess_data.py --dataset {dataset_name} --output_dir /workspace/datasets/ ``` The raw electricity dataset is the 15-minute electricity consumption of 370 customers from the UCI Electricity Load Diagrams. We aggregate to an hourly forecast and use the previous week to predict the following day. -The raw traffic dataset is the 10-minute occupancy rate of San Francisco freeways from 440 sensors downloaded from the UCI PEMS-SF Data Set. We again aggregate to an hourly forecast and use the previous week to predict the following day. +The raw traffic dataset is the 10-minute occupancy rate of San Francisco freeways from 440 sensors downloaded from the UCI PEMS-SF Data Set. We again aggregate to an hourly forecast and use the previous week to predict the following day. 7. Preprocess the dataset: ``` @@ -147,36 +200,36 @@ cd DeeplearningExamples/Tools/TimeSeriesPredictionPlatform 2. Do a preliminary data transposition. TSPP `launch_preproc.py` script is designed to work with CSV input. Each row should contain only a single datapoint. CSV should contain at least three columns: one for time feature, one for labels, and one for dataset ID (we assume a single file will contain data for multiple correlated time series). For reference, see `data/script_download_data.py` script. -3. Include the target dataset in the directory where you want to keep your datasets. The directory can be arbitrary, and it is recommended not to include it in the TimeSeriesPredictionPlatform directory. This arbitrary directory will be mounted to the TSPP container later +3. Include the target dataset in the directory where you want to keep your datasets. The directory can be arbitrary, and it is recommended not to include it in the TimeSeriesPredictionPlatform directory. This arbitrary directory will be mounted to the TSPP container later 4. Create a configuration file for your dataset, found in TimeSeriesPredictionPlatform/conf/dataset, that includes the following values: - * source_path: The path to the CSV that contains your dataset + * source_path: The path to the CSV that contains your dataset - * dest_path: The path to where preprocessing should write your preprocessed dataset + * dest_path: The path to where preprocessing should write your preprocessed dataset - * time_ids: The name of the column within your source CSV that is the feature to split your training, validation, and test datasets on. + * time_ids: The name of the column within your source CSV that is the feature to split your training, validation, and test datasets on. - * train_range, valid_range, test_range: The ranges that mark the edges of the train, validation, and test subsets. Remember that subsets can overlap since predicting the first ‘unseen element’ requires the input of the seen elements before it. As an alternative, a valid_boundary can be specified, which marks the end of training. Then from the valid boundary, the next horizon length number of entries are for validation, and finally, following the end of the validation set, the next horizon length number of entries are for testing. + * train_range, valid_range, test_range: The ranges that mark the edges of the train, validation, and test subsets. Remember that subsets can overlap, since predicting the first ‘unseen element’ requires the input of the seen elements before it. As an alternative, a `valid_boundary` can be specified, which marks the end of training. Then from the `valid boundary`, the next `horizon length` number of entries are for validation, and finally, from the end of the validation set, the next horizon length number of entries are for testing. - * dataset_stride: The stride the dataloader uses to walk the sliding window through the dataset. Default: 1 - - * scale_per_id: Whether to scale continuous features during preprocessing using scalers fitted on just samples from the same ID (True), or all samples (False, Default) - - * encoder_length: The length of data known up until the ‘present’ + * stride: The stride the dataloader uses to walk the sliding window through the dataset. Default: 1 + + * scale_per_id: Whether to scale continuous features during preprocessing using scalers fitted on just samples from the same ID (True), or all samples (False, Default) + + * encoder_length: The length of data known up until the ‘present’ - * example_length: The length of all data, including data known into the future. The prediction horizon is the difference between example_length and encoder_length. + * example_length: The length of all data, including data known into the future. The prediction horizon is the difference between example_length and encoder_length. - * features: A list of the features that the model takes as input. Each feature should be represented by an object containing descriptive attributes. All features should have at least a feature_type (ID, TIME, TARGET, WEIGHT, SAMPLE_WEIGHT, KNOWN, OBSERVED, or STATIC) and feature_embed_type (CONTINUOUS or CATEGORICAL). Continuous features may have a scaler attribute that represents the type of scaler used in preprocessing. Categorical columns should have a cardinality attribute that represents the number of unique values the feature takes plus one (this is due to mapping NaNs to 0 in all cases). Examples can be found in the files in /TimeSeriesPredictionPlatform/conf/dataset/. Required features are one TIME feature, at least one ID feature, one TARGET feature, and at least one KNOWN, OBSERVED, or STATIC feature. + * features: A list of the features that the model takes as input. Each feature should be represented by an object containing descriptive attributes. All features should have at least a feature_type (ID, TIME, TARGET, WEIGHT, SAMPLE_WEIGHT, KNOWN, OBSERVED, or STATIC) and feature_embed_type (CONTINUOUS or CATEGORICAL). Continuous features may have a scaler attribute that represents the type of scaler used in preprocessing. Categorical columns should have a cardinality attribute that represents the number of unique values the feature takes plus one (this is due to mapping NaNs to 0 in all cases). Examples can be found in the files in /TimeSeriesPredictionPlatform/conf/dataset/. Required features are one TIME feature, at least one ID feature, one TARGET feature, and at least one KNOWN, OBSERVED, or STATIC feature. - * train_samples: The number of samples that should be taken at train time to use as train input to your model for a single epoch + * train_samples: The number of samples that should be taken at train time to use as train input to your model for a single epoch - * valid_samples: The number of samples that should be taken at train time to use as validation input to your model for a single epoch + * valid_samples: The number of samples that should be taken at train time to use as validation input to your model for a single epoch - * binarized: Whether or not preprocessing should accelerate data loading by outputting the preprocessed dataset in a binarized format + * binarized: Whether preprocessing should accelerate data loading by outputting the preprocessed dataset in a binarized format - * time_series_count: The number of unique time-series contained in the dataset. + * time_series_count: The number of unique time-series contained in the dataset. 5. After a specification has been written, it is ready to be preprocessed with: @@ -197,17 +250,115 @@ docker run -it --gpus all -v /your/datasets/:/workspace/datasets/ --ipc=host tsp python launch_training.py dataset={YOUR_DATASET} model=tft trainer/criterion=quantile ``` +#### New dataset example +
+ see example + In this section, we will demonstrate how to add a new dataset. Let's assume we want to add a few sine waves dataset to demonstrate the model's ability to fit a deterministic timeseries, in TSPP we should follow these steps: + + 1. Create dataset and save in datasets directory + ```python + # script_generate_sine.py + import os + import numpy as np + import pandas as pd + + + if __name__ == '__main__': + dest_path = '/workspace/datasets/sines/' + os.makedirs(dest_path, exist_ok=True) + # generate series with general form y = k * sin(x) + ks = [1, 10, 125] + xs = np.linspace(0, 4*np.pi, num=200) + df = pd.concat([pd.DataFrame({'y': k * np.sin(xs), 'x': xs, 'point_idx': np.arange(len(xs)), 'ts_id': i}) for i, k in enumerate(ks)]) + + df.to_csv(os.path.join(dest_path, 'sines.csv')) + ``` + ```bash + python script_generate_sine.py + ``` + + 2. Create dataset description for data in `conf/dataset/.yaml` + For our example we want to predict the next value based on series id, previous value and corresponding x values. + `example_length` is going to be 2, since we want to predict the next value from previous and `encoder_length` is 1 to indicate that 1 of 2 values in the example are used as a lookback window. + + For evaluation and testing, we will leave last two values. Easiest way to achieve this is to set `valid_boundary` (to learn more on how to use ranges instead of boundary, refer to [electricity.yaml](https://github.com/NVIDIA/DeepLearningExamples/blob/master/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity.yaml)). + + Also, since we know that series have widely different scales, we want to scale them separately, hence `scale_per_id` + + ```yaml + # conf/dataset/sines.yaml + _target_: data.datasets.create_datasets + config: + graph: False + source_path: /workspace/datasets/sines/sines.csv + dest_path: /workspace/datasets/sines/ + valid_boundary: 198 + scale_per_id: True + encoder_length: 1 + input_length: 1 + example_length: 2 + stride: 1 + MultiID: False + features: + - name: 'ts_id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + - name: 'point_idx' + feature_type: 'TIME' + feature_embed_type: 'CONTINUOUS' + - name: 'y' + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'x' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'ts_id' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + train_samples: -1 + valid_samples: -1 + binarized: True + time_series_count: 3 + ``` + + **NOTE**: How the same column can be used to describe several different features. The only one you probably wouldn't want to appear more than once is TARGET column ;) + + 3. Congratulations! You created your own dataset, now you can proceed to preprocess it and train your models with it. + ```bash + python launch_preproc.py dataset=sines + python launch_training.py dataset=sines model=tft trainer.config.num_epochs=1 + ``` + +
### Adding a new model -Models added to the prediction platform are subject to a few key constraints. Namely, the models should be constructed using vanilla PyTorch. Models should handle the forecasting task (anomaly detection and classification are planned); models should expect that the data is fed in a sliding window and that tensors will be aggregated by Temporal/Data Type. An example of this can be found in data/dataset.py. \ -The default format of the data batch is a dictionary with tensors representing different kinds of covariates. A complete list of the tensors can be found in a batch: +Models added to the prediction platform are subject to a few key constraints. Namely, the models should be constructed using PyTorch. Models should handle the forecasting task (anomaly detection and classification are planned); models should expect that the data is fed in a sliding window and that tensors will be aggregated by Temporal/Data Type. An example of this can be found in data/dataset.py. \ +The default format of the data batch is a dictionary with tensors representing different kinds of covariates. A complete list of the tensor names and types that can be found in a batch: ``` -FEAT_NAMES = ["s_cat", "s_cont", "k_cat", "k_cont", "o_cat", "o_cont", "target", "weight", "sample_weight", "id"] +FEAT_NAME_MAP = { + "s_cat": (InputTypes.STATIC, DataTypes.CATEGORICAL), + "s_cont": (InputTypes.STATIC, DataTypes.CONTINUOUS), + "k_cat": (InputTypes.KNOWN, DataTypes.CATEGORICAL), + "k_cont": (InputTypes.KNOWN, DataTypes.CONTINUOUS), + "o_cat": (InputTypes.OBSERVED, DataTypes.CATEGORICAL), + "o_cont": (InputTypes.OBSERVED, DataTypes.CONTINUOUS), + "target": (InputTypes.TARGET, DataTypes.CONTINUOUS), + "weight": (InputTypes.WEIGHT, DataTypes.CONTINUOUS), + "sample_weight": (InputTypes.SAMPLE_WEIGHT, DataTypes.CONTINUOUS), + "id": (InputTypes.ID, DataTypes.CATEGORICAL), + "timestamp": (InputTypes.TIME, DataTypes.CATEGORICAL) # During preprocessing we cast all time data to int +} ``` -To integrate a model into the TSPP: +To integrate a model into the TSPP: 1. Enter the Deep Learning Examples repository: @@ -215,20 +366,22 @@ To integrate a model into the TSPP: cd DeeplearningExamples ``` -2. Copy the model files into the Deep Learning Examples DeeplearningExamples/Tools/PyTorch/TimeSeriesPredictionPlatform/models/ directory: +2. Copy the model files into the Deep Learning Examples DeepLearningExamples/Tools/PyTorch/TimeSeriesPredictionPlatform/models/ directory: ``` cp -r /PATH/TO/YOUR/MODEL Tools/PyTorch/TimeSeriesPredictionPlatform/models ``` -3. Write a configuration file for the model in `DeeplearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model`. +3. Write a configuration file for the model in `DeepLearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model`. + +This configuration file should reflect the default configuration for your model. Within this file, the _target_ of the model component should be set to point to your model class and global override to define the trainer type used for your model. Currently, we support `ctltrainer` - used for DL models, `stat` and `xgb` trainers used for stat and xgb models respectively. If you need a custom trainer, you can check `conf/trainer/trainer.yaml` or feel free to open an issue with suggestions. For example, on how to define a trainer for your model, see `conf/model/tft.yaml`. -This configuration file should reflect the default configuration for your model. Within this file, the _target_ of the model component should be set to point to your model class. If your model needs additional configuration values based on the dataset, you should create a configuration file in `DeeplearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model_dataset/{modelname_datasetname.yaml}` named according to the model and dataset names. Examples can be found in the `DeeplearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model/tft.yaml` and `DeeplearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model_dataset/tft_traffic.yaml` files. +If your model needs additional configuration values based on the dataset, you should create a configuration file in `DeepLearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model_dataset/{modelname_datasetname.yaml}` named according to the model and dataset names. Examples can be found in the `DeepLearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model/tft.yaml` and `DeepLearningExamples/Tools/TimeSeriesPredictionPlatform/conf/model_dataset/tft_traffic.yaml` files. 4. Build and launch container: ``` -cd DeeplearningExamples/Tools/ -docker build -t tspp TimeSeriesPredictionPlatform +cd DeepLearningExamples/Tools/TimeSeriesPredictionPlatform +docker build -t tspp . docker run -it --rm --ipc=host --network=host --gpus all -v /your/datasets/:/workspace/datasets/ tspp bash ``` @@ -239,42 +392,97 @@ python launch_training.py model={model_name} Some additional values may be needed in this call. For example, if your model requires the Gaussian NLL criterion, you will need to append trainer/criterion=GLL to your call. +#### New model example + +
+ see example + Let's assume that you want to test linear model performance for your research and you want to consume all static categorical and known continuous data you have available: + 1. Write your model that consumes `config` argument: + + ```python + # models/linear.py + import torch + import torch.nn as nn + + class LinearModel(nn.Module): + def __init__(self, config): + super().__init__() + self.encoder_length = config.encoder_length + self.example_length = config.example_length + self.forecest_len = self.example_length - self.encoder_length + self.num_targets = config.temporal_target_size + self.input_size = (len(config.static_categorical_inp_lens) + + config.temporal_known_continuous_inp_size) * self.encoder_length + self.model = nn.Linear(self.input_size, + self.num_targets * self.forecest_len, + bias=config.use_bias) + + def forward(self, batch): + batch_size = batch['target'].shape[0] + inp = torch.cat((batch['s_cat'][:, :self.encoder_length].view(batch_size, -1), + batch['k_cont'][:, :self.encoder_length].view(batch_size, -1)), + dim=1) + pred = self.model(inp) + return pred.reshape(batch_size, self.forecest_len, self.num_targets) + ``` + + 2. Write `conf/model/` entry for your model: + ```yaml + # conf/model/linear.yaml + _target_: models.linear.LinearModel + config: + use_bias: True + + defaults: + - _self_ + - /trainer@_global_/trainer: ctltrainer + ``` + **NOTE**: `static_continuous_inp_size`, `temporal_known_continuous_inp_size`, etc. are 'magic' values that are injected into config during parsing time, to know more see `conf/train_derived_fields.yaml`. This file connects different parts of config and creates aggregate fields that, for example, keep track of number and cardinality of categorical variables in model config. + + 3. Congratulations! You are ready to train your model. + ```bash + python launch_training.py model=linear dataset=electricity + ``` + +
## Advanced The following sections provide more details about changing the dataset, altering the data preprocessing, and comparing the training results. -### Running multi-GPU experiments +### Memory mapping large datasets +Since March 2024 release, we have an option designed for large datasets. Instead of loading dataset into RAM, you can use option `+dataset.config.memory_mapped=True` with `launch_training.py` to memory map dataset from the drive. Note, however, that in order to saturate GPUs, you will have to increase the number of dataloader workers `trainer.config.num_workers` to compensate for longer example loading time. Loading time depends heavily on drives and file system your machine uses. +### Running multi-GPU experiments Launching on multi-GPU requires no changes to model code and can be executed as follows within a TSPP container: ``` -python launch_training.py -m hydra/launcher=torchrun hydra.launcher.nproc_per_node={num_gpus} {override parameters} +python launch_training.py -m hydra/launcher=torchrun hydra.launcher.nproc_per_node={num_gpus} {override parameters} ``` -Statistical models (like AutoARIMA) are not run on GPU, so they are unsuitable for multi-GPU acceleration. In addition, XGBoost has a separate way of doing multi-GPU acceleration. +Statistical models (like AutoARIMA) do not run on GPU, so they are unsuitable for multi-GPU acceleration. In addition, XGBoost has a separate way of doing multi-GPU acceleration (see `dask_xgboost`). ### Parallel training While doing seed sweeps or hp searches on a machine with more than one GPU, we can parallelize the workload by using the `joblib` hydra plugin. To use the plugin, one has to specify `hydra/launcher=joblib` together with the number of parallel jobs `hydra.launcher.n_jobs=8`. For example: ```bash python launch_training.py \ - -m \ - seed='range(1,17)' \ - model=tft \ - dataset=electricity \ - trainer/criterion=quantile \ - trainer.config.num_epochs=3 \ - hydra/launcher=joblib \ - hydra.launcher.n_jobs=8 \ - hydra.sweeper.max_batch_size=8 + -m \ + seed='range(1,17)' \ + model=tft \ + dataset=electricity \ + trainer/criterion=quantile \ + trainer.config.num_epochs=3 \ + hydra/launcher=joblib \ + hydra.launcher.n_jobs=8 \ + hydra.sweeper.max_batch_size=8 ``` *Warning*: Sweeper sends jobs to a launcher in batches. In order to avoid race conditions, specify sweeper batch size to exactly match the number of parallel jobs. For the default sweeper it would be: `hydra.sweeper.max_batch_size=8`, and for optuna sweeper: `hydra.sweeper.n_jobs=8`. ### Running experiments with Exponential Moving Averaging -Exponential moving averaging is a technique in which, while training, the model weights are integrated into a weighted moving average, and the weighted moving average is used in lieu of the directly trained model weights at test time. Our experiments have found this technique improves the convergence properties of most models and datasets we work with. The full paper of EMA can be found here (https://arxiv.org/pdf/1803.05407.pdf) +Exponential moving averaging is a technique in which, while training, the model weights are integrated into a weighted moving average, and the weighted moving average is used in lieu of the directly trained model weights at test time. Our experiments have found this technique improves the convergence properties of most models and datasets we work with. The full paper of EMA can be found [here](https://arxiv.org/pdf/1803.05407.pdf). To activate EMA in the TSPP, specify `trainer.config.ema=True` in the command line call at runtime. The decay parameter in the moving average can be modified using the `+trainer.config.ema_decay={decay}`. @@ -288,48 +496,139 @@ Hyperparameter searches can be used to find close-to-optimal hyperparameter conf ```bash python launch_training.py -m hydra/sweeper=optuna hydra.sweeper.n_trials={N} {parameter_ranges} ``` + +For example: let's tune model size and learning rate for `tft` model on `electricity` dataset. +```bash +export RESULTS=/ws/test_sweep +mkdir -p ${RESULTS} + +python launch_training.py -m \ + 'model.config.n_head=choice(1,2,4)' \ + 'model.config.hidden_size=choice(128,256)' \ + 'trainer.optimizer.lr=tag(log, interval(1e-5, 1e-2))' \ + model=tft \ + dataset=electricity \ + trainer.config.batch_size=1024 \ + evaluator.config.batch_size=1024 \ + hydra/sweeper=optuna \ + +optuna_objectives=[MAE,RMSE] \ + hydra.sweeper.direction=[minimize,minimize] \ + hydra.sweeper.n_trials=128 \ + hydra/launcher=joblib \ + hydra.launcher.n_jobs=8 \ + hydra.sweeper.storage="sqlite:///${RESULTS}/hp_search_multiobjective.db" +``` + For more info how to properly set up {parameter_ranges} visit [hydra docs](https://hydra.cc/docs/plugins/optuna_sweeper/#search-space-configuration) +### Custom launchers + +TSPP now have custom sweeper and launchers in order to boost performance during hp searches with optuna. To utilize more of your resources during long sweeps, you can select `multiprocessing` as your launcher and set your `hydra.sweeper.experiment_sequence` to `hydra_utils.TSPPOptunaExperimentSequence` in the existing sweeps: +```bash +python launch_training.py -m \ + hydra/sweeper=optuna \ + hydra/launcher=multiprocessing \ + hydra.launcher.n_jobs= \ + hydra.sweeper.n_trials={N} \ + hydra.sweeper.experiment_sequence=hydra_utils.TSPPOptunaExperimentSequence \ + {parameter_ranges} +``` + +This might boost performance, especially if you are using early stopping and sweep over model sizes or any other parameter that changes model training time. +For more information and motivation behind the changes, see this [hydra issue](https://github.com/facebookresearch/hydra/issues/2435) and related [PR](https://github.com/facebookresearch/hydra/pull/2461) + ### XGBoost Training -XGBoost and RAPIDS packages are now automatically present in the base NGC PyTorch containers. The TSPP is able to leverage this and allow users to perform training, inference, and deployment on XGBoost and Dask XGBoost using the same commands as Neural Network models. To train: +XGBoost and RAPIDS packages are now automatically present in the base NGC PyTorch containers. The TSPP is able to leverage this and allow users to perform training, inference, and deployment on XGBoost and Dask XGBoost using the same commands as neural network models. To train: ```bash python launch_training.py model={xgboost, dask_xgboost} dataset={dataset} ``` Note: All stages of XGBoost are run on GPU. CPU training is currently not supported. -This launches training using CSV files from the output of preprocessing. Validation data is automatically used for early stopping if applicable. -The TSPP trains a separate XGBoost model for each step in the horizon. If some arbitrary row in the dataframe is at time `t`, then for the ith model, we train it to predict timestep `t+i`. As a part of this, we give the model access to all the features at time step t and bring up the static and known features at timestep `t+i`. Each ID is handled separately, so for any given training/prediction sample, there is only data from 1 ID. -XGBoost itself cannot create new features or process features in the same way as neural networks. To this end, we have created a framework where one can specify lag_features and moving_average_features. Lag_features allow the XGBoost model to have access to the values of the given feature in the past, while moving_average_features allow the model to have access to the moving average of the given feature to some number of previous time steps. For an example of how to specify these features, take a look at conf/model_dataset/xgboost_electricity.yaml. To specify a lag_feature, one needs to select a feature, a min value, and a max value. The TSPP then automatically adds the values of that feature at timestep `t-min_value` to `t-max_value`. Instead of specifying min and max, one can also specify value, which is a list of values for finer control. Note the values must be greater than 0 and must be natural numbers. -To specify a moveing_average_feature, one needs to select a feature and a window_size. This window_size indicates that a new feature will be added that is the average of the values of the feature from `t-window_size` to `t`. -For model parameters, the standard XGBoost parameters can be passed using `model.config.{parameter}`, some may require `+model.config.{parameter}` if the parameter is not set inside the conf/ directory. In addition, one can specify the number of boosting rounds using `model.config.n_rounds`. +This launches training using CSV files from the output of preprocessing. Validation data is automatically used for early stopping if applicable. +The TSPP trains a separate XGBoost model for each step in the horizon. If some arbitrary row in the dataframe is at time `t`, then for the `i`th model, we train it to predict timestep `t+i`. As a part of this, we give the model access to all the features at time step `t` and bring up the static and known features at timestep `t+i`. Each ID is handled separately, so for any given training/prediction sample, there is only data from 1 ID. +XGBoost itself cannot create new features or process features in the same way as neural networks. To this end, we have created a framework where one can specify `lag_features` and `moving_average_features`. `lag_features` allow the XGBoost model to have access to the values of the given feature in the past, while `moving_average_features` allow the model to have access to the moving average of the given feature to some number of previous time steps. For an example of how to specify these features, take a look at `conf/model_dataset/xgboost_electricity.yaml`. To specify a `lag_feature`, one needs to select a feature, a min value, and a max value. The TSPP then automatically adds the values of that feature at timestep `t-min_value` to `t-max_value`. Instead of specifying min and max, one can also specify value, which is a list of values for finer control. Note the values must be greater than 0 and must be natural numbers. +To specify a `moveing_average_feature`, one needs to select a feature and a `window_size`. This `window_size` indicates that a new feature will be added that is the average of the values of the feature from `t-window_size` to `t`. +For model parameters, the standard XGBoost parameters can be passed using `model.config.{parameter}`, some may require `+model.config.{parameter}` if the parameter is not set inside the conf/ directory. In addition, one can specify the number of boosting rounds using `model.config.n_rounds`. There are a few additional parameters that are used exclusively for DaskXGBoost for initialization of the LocalCUDACluster: `model.config.cluster.world_size`, which sets the number of GPUs to use, `model.config.cluster.device_pool_frac`, which sets the amount of memory to allocate on the GPUs, `model.config.cluster.protocol` which sets the protocol to use on the cluster, and `model.config.cluster.npartitions` which sets the number of partitions to use for converting to Dask-cuDF. -Finally, `trainer.callbacks.early_stopping.patience` can be used to set the early stopping patience of the XGBoost rounds, and `trainer.config.log_interval` can be used to set the frequency of the logging for XGBoost. +Finally, `trainer.callbacks.early_stopping.patience` can be used to set the early stopping patience of the XGBoost rounds, and `trainer.config.log_interval` can be used to set the frequency of the logging for XGBoost. + +### Postprocessing of predictions +Some datasets require additional post-processing to make predictions more accurate, e.g. during sales prediction you are more than sure to sale at least 0 of a given product. That's why TSPP evaluator module now support postprocessing. To use it, you need to set `evaluator/postprocessor` to one of the predefined postprocessors, or create your own in `conf/evaluator/postprocessor/` + +```bash +python launch_training.py model=tft dataset=electricity trainer.config.num_epochs=1 evaluator/postprocessor=clip_to_zero +``` + +### Interprete your model +For selected models (ones that inherit from `InterpretableModelBase`) TSPP allows users to visualize activations/attention masks/etc. In order to visualize the model, you have to add `TensorBoardBackend` and/or `WandBBackend` to your `conf/logger.yaml`, since those backends support figure logging. Next, you need to specify which examples you want to visualize adding `+evaluator.config.visualisation_indices` to your config. For example to visualise tft attention on samples 1, 1025, 1026 and 2048 use: +```bash +TFT_SCRIPTING=1 python launch_training.py \ + dataset=${DATASET} \ + model=tft \ + trainer/criterion=quantile \ + trainer.config.batch_size=1024 \ + +evaluator.config.visualisation_indices='[1, 1025, 1026, 2048]' +``` +Note: Interpretability for TFT model requires environmental variable `TFT_SCRIPTING` to be set. + +### Ensembling +Currently, we only support ensembling of DL models with the same type. This can be used to ensemble same models with different hyperparameters, most commonly random generator `seed`. For example, this script trains 8 models with different seeds and then uses them to produce one prediction: +```bash +RESULTS=/ws/tft_ensemble_checkpoints +mkdir -p ${RESULTS} + +python launch_training.py \ + -m \ + seed="range(1,9)" \ + model=tft \ + dataset=electricity \ + overrides=tft/electricity/best_0 \ + trainer.config.log_interval=-1 \ + +trainer.config.force_rerun=True \ + evaluator.config.metrics=[MAE,RMSE,SMAPE,TDI] \ + hydra.sweep.dir=${RESULTS} \ + hydra/launcher=joblib \ + hydra.launcher.n_jobs=8 \ + hydra.sweeper.max_batch_size=8 + +rm ${RESULTS}/*/last_checkpoint.zip + +MODEL_LIST="[" +for I in $( seq 0 7 ) +do + MODEL_LIST+="{dir: ${RESULTS}/$I, checkpoint: best_checkpoint.zip, weight:1.0}," +done +MODEL_LIST=${MODEL_LIST::-1} +MODEL_LIST+="]" +TFT_SCRIPTING=1 python launch_ensembling.py model.config.model_list="${MODEL_LIST}" +``` +Note: we export `TFT_SCRIPTING` to use native `torch.nn.LayerNorm` instead of `apex.FusedLayerNorm`. Using `apex` implementation might lead to errors during ensembling and it will be removed in the next release as this API is deprecated. + ### Conversion, Deployment, and Inference -Inference takes place after a model has been trained and one wants to run data through. Since this only entails using a forward function, the model can be optimized and converted to many different formats that can perform the forward pass more efficiently. In addition, one can set up a [NVIDIA Triton inference server](https://github.com/triton-inference-server/server), which allows for a continuous stream of data to be presented to and passed through the model. The server provides an inference service via an HTTP or gRPC endpoint at ports 8000 and 8001, respectively, on the “bridge” docker network. - +Inference takes place after a model has been trained and one wants to run data through. Since this only entails using a forward function, the model can be optimized and converted to many different formats that can perform the forward pass more efficiently. In addition, one can set up a [NVIDIA Triton inference server](https://github.com/triton-inference-server/server), which allows for a continuous stream of data to be presented to and passed through the model. The server provides an inference service via an HTTP or gRPC endpoint at ports 8000 and 8001, respectively, on the “bridge” docker network. The TSPP supports a few versions of inference, including native inference and NVIDIA Triton deployment. Both use the test_forward function specified in the model config (defaults to forward()) as the forward function. -To launch native inference, one must have a checkpoint directory from a TSPP training call that includes a .hydra directory and a best_checkpoint.zip from training a Neural Net, a populated checkpoints directory from training an XGBoost, or an arima.pkl file from training an ARIMA model. Then run +To launch native inference, one must have a checkpoint directory from a TSPP training call that includes a .hydra directory and a best_checkpoint.zip from training a Neural Net, a populated checkpoints directory from training an XGBoost, or an arima.pkl file from training an ARIMA model. Then run ``` python launch_inference.py checkpoint=/path/to/checkpoint/directory ``` -Note: Do not confuse the checkpoint directory with the TimeSeriesPredictionPlatform/outputs/ directory. The directory to use in the inference call is typically two levels lower (for example, /path/to/TimeSeriesPredictionPlatform/outputs/2021-08-23/03-03-11/). +Note: Do not confuse the checkpoint directory with the TimeSeriesPredictionPlatform/outputs/ directory. The directory to use in the inference call is typically two levels lower (for example, `/path/to/TimeSeriesPredictionPlatform/outputs/2021-08-23/03-03-11/`). The device argument refers to the device that one would like the model to be built on and run on. Note that multi-GPU inference launches are not supported. By default, the evaluator uses the configs specified in the .hydra/config.yaml file from the checkpoint directory. One can override these by including them in the launch. For example, if one wanted to adjust the metrics to use MAE and RMSE only. ``` python launch_inference.py checkpoint=/path/to/checkpoint/directory “+inference.config.evaluator.config.metrics=[‘MAE’, ‘RMSE’]” ``` -Note: Be sure to include the + when overriding any of the evaluator configs. +Note: Be sure to include the `+` when necessary, this special character will add new fields to the current config. However if value already exists, this will result in error from hydra. -Prior to the next section, make sure that the TSPP container is run with the following arguments from the TSPP directory. We recommend an outputs_dir is created that can be used to mount the outputs directory and the multirun folder from multi-GPU runs. +Prior to the next section, make sure that the TSPP container is run with the following arguments from the TSPP directory. We recommend an outputs_dir is created that can be used to mount the outputs directory and the multirun folder from multi-GPU runs. ``` docker run -it --rm --gpus all --ipc=host --network=host -v /your/datasets/:/workspace/datasets/ -v /your/outputs_dir/:/your/outputs_dir/ -v $(pwd):$(pwd) -v /your/outputs_dir/outputs/:/workspace/outputs/ -v /your/outputs_dir/multirun/:/workspace/multirun/ -v /var/run/docker.sock:/var/run/docker.sock tspp ``` Note that `/your/outputs_dir/{outputs/multirun}` is equivalent to the python script `os.path.join(/your/outputs_dir/, outputs)`. -In the previous command, note that six different directories are mounted. The datasets are mounted to the usual location, but we have two different mount locations for outputs. Mounting the outputs to /workspace/outputs/ allows usual training calls to be saved in your output directory. Similarly, mounting the multirun to /workspace/multirun/ allows multi-GPU to be saved. The second output mount is mounted to the same path as the output directory is in the host. This is essential due to the way we deploy to NVIDIA Triton. The directory of the output in the docker must match the directory of the output on the host machine. Additionally, the mount for /var/run/docker.sock allows the tspp docker container to launch another container. In our case, this is the NVIDIA Triton server. In subsequent calls to launch_triton_configure.py, the /path/to/checkpoint/directory/ must be of the form /your/outputs_dir/{checkpoint_dir} instead of /workspace/{checkpoint_dir} and should be absolute paths. +In the previous command, note that six different directories are mounted. The datasets are mounted to the usual location, but we have two different mount locations for outputs. Mounting the outputs to /workspace/outputs/ allows usual training calls to be saved in your output directory. Similarly, mounting the multirun to /workspace/multirun/ allows multi-GPU to be saved. The second output mount is mounted to the same path as the output directory is in the host. This is essential due to the way we deploy to NVIDIA Triton. The directory of the output in the docker must match the directory of the output on the host machine. Additionally, the mount for /var/run/docker.sock allows the tspp docker container to launch another container. In our case, this is the NVIDIA Triton server. In subsequent calls to launch_triton_configure.py, the /path/to/checkpoint/directory/ must be of the form /your/outputs_dir/{checkpoint_dir} instead of /workspace/{checkpoint_dir} and should be absolute paths. Remember that multi-GPU runs are stored in `multirun` instead of `outputs`. To use deployment, the simplest way is to use the directories `multirun` and `outputs` directly inside the TSPP. This can be achieved by launching the docker as follows. @@ -338,31 +637,31 @@ docker run -it --rm --gpus all --ipc=host --network=host -v /your/datasets/:/wor ``` -Finally, note that to run the deployment script, you must be in the same directory path in the container as the TSPP is stored on your machine. This means that being in /workspace in the container may not work for running the deployment. If outside the container your TimeSeriesPredictionPlatform is at /home/user/TimeSeriesPredictionPlatform, you must be at the same path in your docker container (/home/user/TimeSeriesPredictionPlatform). This is the purpose of the `-v $(pwd):$(pwd)` in the run script. +Finally, note that to run the deployment script, you must be in the same directory path in the container as the TSPP is stored on your machine. This means that being in /workspace in the container may not work for running the deployment. If outside the container your TimeSeriesPredictionPlatform is at /home/user/TimeSeriesPredictionPlatform, you must be at the same path in your docker container (/home/user/TimeSeriesPredictionPlatform). This is the purpose of the `-v $(pwd):$(pwd)` in the run script. To launch conversion and deployment, one must again have a checkpoint directory from a TSPP training call that includes a .hydra directory and a best_checkpoint.zip from a Neural Net training or a populated checkpoints directory from an XGBoost training. Stats model, such as Arima, are not supported for deployment. In addition, the model that will be converted must already support conversion to the required format. In the current version of the TSPP, we first export the model to either TorchScript-Script or TorchScript-Trace and subsequently convert it to TorchScript, Onnx, or TRT using the model-navigator package. We also support export to Onnx and conversion to both Onnx and TRT. For XGBoost models, we format the checkpoints and deploy using the FIL backend; there are no extra steps necessary. To run export and conversion (for XGBoost, the deployment/export and deployment/convert fields can be ignored, and no other deployment options are functional): ``` python launch_triton_configure.py deployment/export={ts-trace, ts-script, onnx} deployment/convert={torchscript, onnx, trt} checkpoint=/path/to/checkpoint/directory ``` -The format mapping is listed below -TorchScript-Script: ts-script -TorchScript-Trace: ts-trace -TorchScript: torchscript -Onnx: onnx -TRT: trt +The format mapping is listed below: + +- TorchScript-Script: ts-script +- TorchScript-Trace: ts-trace +- TorchScript: torchscript +- Onnx: onnx +- TRT: trt -Note that some conversions do not support the apex FusedLayerNorm library. To get around this, we set the operating system environment variable ‘TFT_SCRIPTING” to True when loading the model for deployment. This changes the apex LayerNorm to vanilla torch LayerNorm. In addition, one can select the batch size and precision of the conversion, using +inference.config.evaluator.config.batch_size and inference.config.precision=Choice[ fp32, fp16 ] respectively. +Note that the conversions do not support the apex fused LayerNorm library. In order to get around this, we set the os environ variable ‘TFT_SCRIPTING” to True when loading the model for deployment. This changes the apex LayerNorm to vanilla torch LayerNorm. In addition, one can select the batch size and precision of the conversion, using +inference.config.evaluator.config.batch_size and inference.config.precision=Choice[ fp32, fp16 ] respectively. Once export and conversion have been done, the results are stored in /path/to/checkpoint/directory/deployment. Subsequently, the converted model’s NVIDIA Triton config is generated in the /path/to/checkpoint/directory/deployment/navigator_workspace/model-store/ directory. An additional option in running conversion is selecting whether to run the basics of conversion and NVIDIA Triton config creation or to run the full pipeline of conversion, NVIDIA Triton config creation, profiling, analysis, and helm chart creation. Setting config.inference.optimize=True during launch switches to the full pipeline. Another part of optimization is setting the backend accelerator for NVIDIA Triton config generation. Setting config.inference.accelerator=Choice[none, trt] changes the accelerator specified. Note that this defaults to ‘none’ and ‘trt’ is only compatible with the Onnx conversion. If one wants to launch the NVIDIA Triton inference server using a specific GPU, the CUDA index can be specified with the config option config.inference.gpu, which defaults to 0. -More information on the conversion is located here: -https://github.com/triton-inference-server/model_navigator/blob/v0.2.7/docs/conversion.md +More information on the conversion is located [here](https://github.com/triton-inference-server/model_navigator/blob/v0.2.7/docs/conversion.md) -More information on the NVIDIA Triton config creation is located here: https://github.com/triton-inference-server/model_navigator/blob/v0.2.7/docs/triton_model_configurator.md +More information on the NVIDIA Triton config creation is located [here](https://github.com/triton-inference-server/model_navigator/blob/v0.2.7/docs/triton_model_configurator.md) -More information on the full pipeline is located here: -https://github.com/triton-inference-server/model_navigator/blob/v0.2.7/docs/run.md +More information on the full pipeline is located [here]( +https://github.com/triton-inference-server/model_navigator/blob/v0.2.7/docs/run.md) After running `launch_triton_configure.py`, the directories are set up for quick Triton deployment. To start the server: @@ -375,24 +674,24 @@ Once the script finishes running, the Triton server will run in the background w python launch_inference.py inference=triton checkpoint=/path/to/checkpoint/directory ``` Similar to the native inference, one can again override the evaluator configs. The NVIDIA Triton model name is set as the second directory to the model. For example, in the case of our TFT model, whose path is models.tft_pyt.TemporalFusionTransformer, the name of the NVIDIA Triton model is tft_pyt. In the case of XGBoost, there is a different model name for each model in the horizon length, specified as `xgb_{i}`. -There is a config option +inference.config.model_name, which can be set to the NVIDIA Triton model name. This does not set the name of the model but instead selects which of the possible models in the model-store directory will be used for inference. This is useful after a call using the optimize option, which can generate multiple different models in the model-store. +There is a config option +inference.config.model_name, which can be set to the NVIDIA Triton model name. This does not set the name of the model but instead selects which of the possible models in the model-store directory will be used for inference. This is useful after a call using the optimize option, which can generate multiple different models in the model-store. -For both the native and triton launch_inference, one can specify what dataset and target_scalers to use (if any) as long as the data shapes do not conflict with the already trained model. To specify a dataset directory use +inference.config.dataset_dir=/path/to/dataset. The dataset directory must contain a tspp_preprocess.bin file as well as either train.bin/valid.bin/test.bin or train.csv/valid.csv/test.csv, depending on the configuration option dataset.config.binarized (this option cannot be changed during deployment or inference). Once the path has been set, deployment and inference both use the test dataset. +For both the native and triton launch_inference, one can specify what dataset and target_scalers to use (if any) as long as the data shapes do not conflict with the already trained model. To specify a dataset directory use +inference.config.dataset_dir=/path/to/dataset. The dataset directory must contain a tspp_preprocess.bin file as well as either train.bin/valid.bin/test.bin or train.csv/valid.csv/test.csv, depending on the configuration option dataset.config.binarized (this option cannot be changed during deployment or inference). Once the path has been set, deployment and inference both use the test dataset. #### Online Inference The TSPP also supports an online inference solution for both XGBoost models and Neural models. Given raw data (not preprocessed by TSPP), both native and NVIDIA Triton inference can preprocess and pass the data through the models. When running, specify `+inference.config.dataset_path=/path/to/raw/data/csv` and if applicable `+inference.config.preproc_state_path=/path/to/tspp_preprocess.bin` (if the preprocess state is saved elsewhere). Note this is not yet supported on ARIMA models. As a final note, make sure to close the NVIDIA Triton Inference Server docker container when finished using `docker stop trt_server_cont`. -Our TFT model supports export to TorchScript-Trace and conversion to all formats. +Our TFT model supports export to TorchScript-Trace and conversion to all formats. -If you encounter an error such as +If you encounter an error such as ``` RuntimeError: Model tft_pyt:1 is not ready ``` -Or +Or ``` ERROR root Exception in callback .wrapped_callback at 0x7f9437b469d0>: AttributeError("'InferenceServerException' object has no attribute 'get_response'") ``` @@ -408,17 +707,23 @@ Config structure reflects the internal design of the tool. Most components have ``` With a few exceptions where components are strictly dependent (for example, optimizer can be used only during training, so its configuration is stored in `/workspace/conf/trainer/optimizer/{optimizer_name}.yaml`) -If a parameter does not exist in the config, you must prepend `+` to its reference in the command line call. For example, `+trainer.config.force_rerun=...` adds force_rerun to trainer.config, but trainer.config.force_rerun=... errors. +If a parameter does not exist in the config, you must prepend `+` to its reference in the command line call. For example, `+trainer.config.force_rerun=...` adds force_rerun to trainer.config, but `trainer.config.force_rerun=...` errors. ## Release Notes -We’re constantly refining and improving our performance on AI and HPC workloads with frequent updates to our software stack. For our latest performance data, refer to these pages for [AI](https://developer.nvidia.com/deep-learning-performance-training-inference) and [HPC](https://developer.nvidia.com/hpc-application-performance) benchmarks. - - ### Changelog -November 2021 -- Initial release + +March 2024 +- Added memory mapped datasets +- Added ensembling module +- Added wandb logging +- Added postprocessor +- Added timestamps to predictions +- Added visialization and interpretability +- Added custom hydra plugins +- Added support for models from the [paper](#reference) +- Added support for dataset from the [paper](#reference) July 2022 - Reworked config structure @@ -434,10 +739,26 @@ July 2022 - Added example scripts - Criterions and optimizers no longer require dummy wrappers +November 2021 +- Initial release + ### Known issues If you encounter errors stating `srcIndex < value`, verify that your categorical cardinalities are the correct size, this indicates that the value of a categorical you are trying to embed is too large for its respective embedding table. +## Reference +### Cite +Cite the following paper if you find this code useful or use it in your own work: +``` +@misc{bączek2024tspp, + title={TSPP: A Unified Benchmarking Tool for Time-series Forecasting}, + author={Jan Bączek and Dmytro Zhylko and Gilberto Titericz and Sajad Darabi and Jean-Francois Puget and Izzy Putterman and Dawid Majchrowski and Anmol Gupta and Kyle Kranen and Pawel Morkisz}, + year={2024}, + eprint={2312.17100}, + archivePrefix={arXiv}, + primaryClass={cs.LG} +} +``` diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/callbacks.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/callbacks.py index 72b30bcf5..9cb063a46 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/callbacks.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/callbacks.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 class Callback(object): """ Base class for building new callbacks. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/ctl_callbacks.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/ctl_callbacks.py index e417246bb..7cf4e8698 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/ctl_callbacks.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/ctl_callbacks.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 import time import dllogger diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/hydra_callbacks.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/hydra_callbacks.py index 682c6d558..eb29d658f 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/hydra_callbacks.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/callbacks/hydra_callbacks.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,18 +13,20 @@ # limitations under the License. import os +import mlflow import pandas as pd from omegaconf import OmegaConf from hydra.experimental.callback import Callback from loggers.log_helper import jsonlog_2_df +from mlflow.entities import Metric, Param class MergeLogs(Callback): def on_multirun_end(self, config, **kwargs): OmegaConf.resolve(config) - ALLOWED_KEYS=['timestamp', 'elapsed_time', 'step', 'loss', 'val_loss', 'MAE', 'MSE', 'RMSE', 'P50', 'P90'] + ALLOWED_KEYS=['timestamp', 'elapsed_time', 'step', 'loss', 'val_loss', 'MAE', 'MSE', 'RMSE', 'P50', 'P90', 'SMAPE', 'TDI'] dfs = [] for p, sub_dirs, files in os.walk(config.hydra.sweep.dir): @@ -32,7 +34,6 @@ def on_multirun_end(self, config, **kwargs): path = os.path.join(p, 'log.json') df = jsonlog_2_df(path, ALLOWED_KEYS) dfs.append(df) - # Transpose dataframes plots = {} for c in dfs[0].columns: @@ -49,3 +50,15 @@ def on_multirun_end(self, config, **kwargs): timestamps = (timestamps * 1000).astype(int) if not timestamps.is_monotonic: raise ValueError('Timestamps are not monotonic') + + metrics = [Metric('_'.join((k,name)), v, timestamp, step) + for k, df in plots.items() + for timestamp, (step, series) in zip(timestamps, df.iterrows()) + for name, v in series.items() + ] + client = mlflow.tracking.MlflowClient(tracking_uri=config.trainer.config.mlflow_store) + exp = client.get_experiment_by_name(config.trainer.config.get('experiment_name', '')) + run = client.create_run(exp.experiment_id if exp else '0') + for i in range(0, len(metrics), 1000): + client.log_batch(run.info.run_id, metrics=metrics[i:i+1000]) + client.set_terminated(run.info.run_id) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/conf_utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/conf_utils.py index 910723df6..3ea90b816 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/conf_utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/conf_utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,8 +14,10 @@ from omegaconf import OmegaConf from data.data_utils import InputTypes, DataTypes, FeatureSpec +import functools +from hydra.utils import get_method -OmegaConf.register_new_resolver("and", lambda x, y: x and y, use_cache=True) +OmegaConf.register_new_resolver("and", lambda x, y: bool(x and y), use_cache=True) OmegaConf.register_new_resolver("feature.selector", lambda x,feat_type,embed_type: OmegaConf.create([elem for elem in x if elem.feature_type == feat_type and elem.feature_embed_type == embed_type]) @@ -27,10 +29,12 @@ OmegaConf.register_new_resolver("cmp", lambda x, y: x == y) OmegaConf.register_new_resolver("cont.lower", lambda x, y: y.lower() in x.lower()) -# XXX I don't know whether it is the best idea to allow user to sum over nested structure without checks def sum_nested(*args): if len(args) == 1 and isinstance(args[0], (int, float)): return args[0] return sum(arg if isinstance(arg, (int, float)) else sum_nested(*arg) for arg in args) OmegaConf.register_new_resolver("sum", sum_nested) + +def partial(func, *args, **kwargs): + return functools.partial(get_method(func), *args, **kwargs) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/converter_config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/converter_config.yaml index 7e6541653..09ccb6b82 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/converter_config.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/converter_config.yaml @@ -1,18 +1,5 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 defaults: - deployment: convert -checkpoint: ??? \ No newline at end of file +checkpoint: ??? diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5.yaml new file mode 100755 index 000000000..9a6a612ad --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: MIT +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/M5/M5.csv + dest_path: /workspace/datasets/M5/ + iterable: False + encoder_length: 28 + input_length: 28 + example_length: 56 + valid_boundary: '2016-04-25' + train_samples: 1000000 + time_series_count: 30490 + drop_unseen: True + MultiID: False + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 30490 + - name: "date" + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: "weight" + feature_type: 'WEIGHT' + feature_embed_type: 'CONTINUOUS' + - name: "item_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 3050 + - name: "dept_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: "cat_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + - name: "store_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 11 + - name: "state_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + - name: "items_sold" + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: data.data_utils.Log1pScaler + - name: "wday" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: "month" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 13 + - name: "event_name_1" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 31 + - name: "event_type_1" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + - name: "event_type_2" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "event_name_2" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + - name: "snap_CA" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "snap_TX" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "snap_WI" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "sell_price" + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + binarized: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5_norm.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5_norm.yaml new file mode 100755 index 000000000..3beaf4a12 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5_norm.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: MIT +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/M5/M5.csv + dest_path: /workspace/datasets/M5_norm/ + iterable: False + encoder_length: 28 + input_length: 28 + example_length: 56 + valid_boundary: '2016-04-25' + train_samples: 1000000 + time_series_count: 30490 + drop_unseen: True + MultiID: False + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 30490 + - name: "date" + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: "weight" + feature_type: 'WEIGHT' + feature_embed_type: 'CONTINUOUS' + - name: "item_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 3050 + - name: "dept_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: "cat_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + - name: "store_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 11 + - name: "state_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + - name: "items_sold" + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.pipeline.Pipeline + steps: + - + - 'log1p' + - _target_: data.data_utils.Log1pScaler + - + - 'norm' + - _target_: sklearn.preprocessing.StandardScaler + - name: "wday" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: "month" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 13 + - name: "event_name_1" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 31 + - name: "event_type_1" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + - name: "event_type_2" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "event_name_2" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + - name: "snap_CA" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "snap_TX" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "snap_WI" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "sell_price" + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + binarized: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5_xgb.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5_xgb.yaml new file mode 100644 index 000000000..9775a9a2f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/M5_xgb.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: MIT +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/M5/M5.csv + dest_path: /workspace/datasets/M5/ + iterable: False + encoder_length: 28 + input_length: 28 + example_length: 56 + valid_boundary: '2016-04-25' + train_samples: 1000000 + time_series_count: 30490 + drop_unseen: True + MultiID: False + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 30490 + - name: "date" + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: "weight" + feature_type: 'WEIGHT' + feature_embed_type: 'CONTINUOUS' + - name: "item_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 3050 + - name: "dept_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: "cat_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + - name: "store_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 11 + - name: "state_id" + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 4 + - name: "items_sold" + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: data.data_utils.Log1pScaler + - name: "wday" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: "month" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 13 + - name: "event_name_1" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 31 + - name: "event_type_1" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + - name: "event_type_2" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "event_name_2" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + - name: "snap_CA" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "snap_TX" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "snap_WI" + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 3 + - name: "sell_price" + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + binarized: False diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity.yaml index 02d0a4d81..a15081ef7 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity.yaml @@ -1,35 +1,22 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: data.datasets.create_datasets config: graph: False source_path: /workspace/datasets/electricity/electricity.csv dest_path: /workspace/datasets/electricity/ - time_ids: 'days_from_start' train_range: - 0 - - 1315 + - 31560 valid_range: - - 1308 - - 1339 + - 31392 + - 32136 test_range: - - 1332 - - 10000 + - 31968 + - 35000 dataset_stride: 1 scale_per_id: True encoder_length: 168 + input_length: 168 example_length: 192 MultiID: False features: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity_xgb.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity_xgb.yaml new file mode 100755 index 000000000..030c9ae54 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/electricity_xgb.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: data.datasets.create_datasets +config: + graph: False + source_path: /workspace/datasets/electricity/electricity.csv + dest_path: /workspace/datasets/electricity_xgb/ + train_range: + - 0 + - 32136 + valid_range: + - 31392 + - 32136 + test_range: + - 31968 + - 35000 + dataset_stride: 1 + scale_per_id: True + encoder_length: 168 + input_length: 168 + example_length: 192 + MultiID: False + features: + - name: 'categorical_id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 371 + - name: 'hours_from_start' + feature_type: 'TIME' + feature_embed_type: 'CONTINUOUS' + - name: 'power_usage_weight' + feature_type: 'WEIGHT' + feature_embed_type: 'CONTINUOUS' + - name: 'power_usage' + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'hour' + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 25 + - name: 'day_of_week' + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: 'categorical_id' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 371 + + binarized: False + time_series_count: 369 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay.yaml new file mode 100644 index 000000000..06c42401a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/pems_bay/pems_bay.csv + dest_path: /workspace/datasets/pems_bay/ + binarized: False + graph: graph.bin + graph_partitions: 1 + partition_joining_coef: 1 + train_range: + - '2017-1-1' + - '2017-5-8' + valid_range: + - '2017-5-8' + - [2017,5,25,17,50] + test_range: + - [2017,5,25,17,50] + - '2017-7-01' + dataset_stride: 1 + scale_per_id: True + encoder_length: 12 + input_length: 12 + example_length: 24 + MultiID: True + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 325 + - name: 'Timestamp' + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: 'Avg Speed' + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Station' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 326 + - name: 'Freeway #' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 9 + - name: 'Direction of Travel' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + #- name: 'Station Length' + # feature_type: 'STATIC' + # feature_embed_type: 'CONTINUOUS' + # scaler: + # _target_: sklearn.preprocessing.StandardScaler + - name: 'Avg Occupancy' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Total Flow' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day of week' + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: 'Month' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Hour' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Minute' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + + time_series_count: 325 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc24.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc24.yaml new file mode 100644 index 000000000..f2af6d271 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc24.yaml @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/pems_bay/pems_bay.csv + dest_path: /workspace/datasets/pems_bay_enc24/ + binarized: True + graph: graph.bin + graph_partitions: 1 + partition_joining_coef: 1 + time_ids: 'Timestamp' + train_range: + - '2017-1-1' + - '2017-5-8' + valid_range: + #- '2017-5-8' + #- [2017,5,25,17,50] + - [2017,5,7,22,00] + - [2017,5,25,16,50] + test_range: + #- [2017,5,25,17,50] + - [2017,5,25,16,50] + - '2017-7-01' + dataset_stride: 1 + scale_per_id: False + encoder_length: 24 + input_length: 24 + example_length: 36 + MultiID: False + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 325 + - name: 'Timestamp' + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: 'Avg Speed' + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Station' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 326 + - name: 'Freeway #' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 9 + - name: 'Direction of Travel' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + #- name: 'Station Length' + # feature_type: 'STATIC' + # feature_embed_type: 'CONTINUOUS' + # scaler: + # _target_: sklearn.preprocessing.StandardScaler + - name: 'Avg Occupancy' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Total Flow' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day of week' + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: 'Month' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Hour' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Minute' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + + time_series_count: 325 + train_samples: 1000000 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc288.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc288.yaml new file mode 100644 index 000000000..cb0398c0c --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc288.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/pems_bay/pems_bay.csv + dest_path: /workspace/datasets/pems_bay_enc288/ + binarized: True + graph: graph.bin + graph_partitions: 1 + partition_joining_coef: 1 + time_ids: 'Timestamp' + train_range: + - '2017-1-1' + - '2017-3-8' + valid_range: + - '2017-3-8' + - [2017,4,25,17,50] + test_range: + - [2017,4,25,17,50] + - '2017-7-01' + dataset_stride: 1 + scale_per_id: False + encoder_length: 288 + input_length: 288 + example_length: 300 + MultiID: False + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 325 + - name: 'Timestamp' + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: 'Avg Speed' + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Station' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 326 + - name: 'Freeway #' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 9 + - name: 'Direction of Travel' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + #- name: 'Station Length' + # feature_type: 'STATIC' + # feature_embed_type: 'CONTINUOUS' + # scaler: + # _target_: sklearn.preprocessing.StandardScaler + - name: 'Avg Occupancy' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Total Flow' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day of week' + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: 'Month' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Hour' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Minute' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + + time_series_count: 325 + train_samples: 1000000 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc48.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc48.yaml new file mode 100644 index 000000000..2dd5877eb --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_enc48.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/pems_bay/pems_bay.csv + dest_path: /workspace/datasets/pems_bay_enc48/ + binarized: True + graph: graph.bin + graph_partitions: 1 + partition_joining_coef: 1 + time_ids: 'Timestamp' + train_range: + - '2017-1-1' + #- '2017-5-8' + - [2017,5,7,18,00] + valid_range: + #- '2017-5-8' + #- [2017,5,25,17,50] + - [2017,5,7,18,00] + - [2017,5,25,14,50] + test_range: + #- [2017,5,25,17,50] + - [2017,5,25,14,50] + - '2017-7-01' + dataset_stride: 1 + scale_per_id: False + encoder_length: 48 + input_length: 48 + example_length: 60 + MultiID: False + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 325 + - name: 'Timestamp' + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: 'Avg Speed' + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Station' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 326 + - name: 'Freeway #' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 9 + - name: 'Direction of Travel' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + #- name: 'Station Length' + # feature_type: 'STATIC' + # feature_embed_type: 'CONTINUOUS' + # scaler: + # _target_: sklearn.preprocessing.StandardScaler + - name: 'Avg Occupancy' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Total Flow' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day of week' + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: 'Month' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Hour' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Minute' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + + time_series_count: 325 + train_samples: 1000000 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_xgb.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_xgb.yaml new file mode 100644 index 000000000..b3068ff69 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/pems_bay_xgb.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: data.datasets.create_datasets +config: + source_path: /workspace/datasets/pems_bay/pems_bay.csv + dest_path: /workspace/datasets/pems_bay_xgb/ + binarized: False + graph: graph.bin + graph_partitions: 1 + partition_joining_coef: 1 + train_range: + - '2017-1-1' + - '2017-5-8' + valid_range: + - '2017-5-8' + - [2017,5,25,17,50] + test_range: + - [2017,5,25,17,50] + - '2017-7-01' + dataset_stride: 1 + scale_per_id: False + encoder_length: 12 + input_length: 12 + example_length: 24 + MultiID: False + features: + - name: 'id' + feature_type: 'ID' + feature_embed_type: 'CATEGORICAL' + cardinality: 325 + - name: 'Timestamp' + feature_type: 'TIME' + feature_embed_type: 'DATE' + - name: 'Avg Speed' + feature_type: 'TARGET' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Station' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 326 + - name: 'Freeway #' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 9 + - name: 'Direction of Travel' + feature_type: 'STATIC' + feature_embed_type: 'CATEGORICAL' + cardinality: 5 + - name: 'Avg Occupancy' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Total Flow' + feature_type: 'OBSERVED' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day of week' + feature_type: 'KNOWN' + feature_embed_type: 'CATEGORICAL' + cardinality: 8 + - name: 'Month' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Day' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Hour' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + - name: 'Minute' + feature_type: 'KNOWN' + feature_embed_type: 'CONTINUOUS' + scaler: + _target_: sklearn.preprocessing.StandardScaler + + time_series_count: 325 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/traffic.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/traffic.yaml index deb0b3ffe..89d962bd5 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/traffic.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/dataset/traffic.yaml @@ -1,34 +1,21 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: data.datasets.create_datasets config: source_path: /workspace/datasets/traffic/traffic.csv dest_path: /workspace/datasets/traffic/ - time_ids: 'sensor_day' train_range: - 0 - - 151 + - 3624 valid_range: - - 144 - - 166 + - 3456 + - 3984 test_range: - - 159 - - 2000 + - 3816 + - 4200 dataset_stride: 1 scale_per_id: False encoder_length: 168 + input_length: 168 example_length: 192 MultiID: False features: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert.yaml index 9d5909616..01246acec 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: inference.converter.run_converter defaults: - export: ts-trace diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/onnx.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/onnx.yaml index 9bf67362e..7a3f87d06 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/onnx.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/onnx.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 config: type: onnx diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/torchscript.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/torchscript.yaml index 56140db60..42c0643dd 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/torchscript.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/torchscript.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 config: type: torchscript diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/trt.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/trt.yaml index ad23c1526..d32e78a9c 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/trt.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/convert/trt.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 config: type: trt diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/deploy.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/deploy.yaml index 17c47c253..2c77e6edf 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/deploy.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/deploy.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: inference.launch_inference_server.run_server_launch config: gpu: 0 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/onnx.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/onnx.yaml index 9bf67362e..7a3f87d06 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/onnx.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/onnx.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 config: type: onnx diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-script.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-script.yaml index 65543ffa0..5ee321ae4 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-script.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-script.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 config: type: ts-script diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-trace.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-trace.yaml index fe751fdfb..53fcad632 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-trace.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment/export/ts-trace.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 config: type: ts-trace diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment_config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment_config.yaml index 2eaf5f0e7..2e0d651b8 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment_config.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/deployment_config.yaml @@ -1,18 +1,5 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 defaults: - deployment: deploy -checkpoint: ??? \ No newline at end of file +checkpoint: ??? diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/ensemble_conf.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/ensemble_conf.yaml new file mode 100644 index 000000000..9a0c8cb7b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/ensemble_conf.yaml @@ -0,0 +1,13 @@ +defaults: + - logger + +model: + _target_: models.ensembling.ModelEnsemble + config: + model_list: ??? + +# Used to override the defaults got from checkpoint +evaluator: + config: + metrics: ['MAE', 'RMSE', 'SMAPE'] + per_step_metrics: False diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/ctlevaluator.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/ctlevaluator.yaml index 36c71d596..17c3b5e7c 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/ctlevaluator.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/ctlevaluator.yaml @@ -1,16 +1,6 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 +defaults: + - postprocessor: _target_: evaluators.evaluator.CTLMetricEvaluator config: @@ -21,4 +11,5 @@ config: - MAE - RMSE - SMAPE + - TDI - ND diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/postprocessor/clip_and_round.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/postprocessor/clip_and_round.yaml new file mode 100644 index 000000000..e1a19e421 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/postprocessor/clip_and_round.yaml @@ -0,0 +1,8 @@ +_target_: evaluators.evaluator.Postprocessor +transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + - _target_: conf.conf_utils.partial + func: numpy.round \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/postprocessor/clip_to_zero.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/postprocessor/clip_to_zero.yaml new file mode 100644 index 000000000..ee679c6d0 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/postprocessor/clip_to_zero.yaml @@ -0,0 +1,6 @@ +_target_: evaluators.evaluator.Postprocessor +transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/statevaluator.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/statevaluator.yaml index e1012ccc1..bf0ca65a1 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/statevaluator.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/statevaluator.yaml @@ -1,16 +1,6 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 +defaults: + - postprocessor: _target_: evaluators.evaluator.StatMetricEvaluator config: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/xgbevaluator.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/xgbevaluator.yaml index dc443dab0..fe2ea771c 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/xgbevaluator.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/evaluator/xgbevaluator.yaml @@ -1,16 +1,6 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 +defaults: + - postprocessor: _target_: evaluators.evaluator.XGBMetricEvaluator config: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/callbacks/merge_logs.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/callbacks/merge_logs.yaml index 688b16812..d5a53e0fe 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/callbacks/merge_logs.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/callbacks/merge_logs.yaml @@ -1,15 +1,2 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. merge_logs: _target_: callbacks.hydra_callbacks.MergeLogs diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/primary.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/primary.yaml index 51699a43f..7caf6df7e 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/primary.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/primary.yaml @@ -1,18 +1,5 @@ # @package _group_ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 version: 1 formatters: simple: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/secondary.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/secondary.yaml index adc99dfaf..8b82e5dc8 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/secondary.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/hydra/job_logging/secondary.yaml @@ -1,18 +1,5 @@ # @package _group_ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 version: 1 formatters: simple: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/native.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/native.yaml index a1330080e..21bba8584 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/native.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/native.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: inference.inference.run_inference config: checkpoint: ??? diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/triton.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/triton.yaml index c5e3919c5..3b45fe3a1 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/triton.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference/triton.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: inference.inference_triton.run_inference_triton config: checkpoint: ??? diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_config.yaml index d0578fb57..f36aab549 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_config.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_config.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 defaults: - inference: native -checkpoint: ??? \ No newline at end of file +checkpoint: ??? diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_triton_config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_triton_config.yaml index 52a1256c9..a6daad51c 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_triton_config.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/inference_triton_config.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 defaults: - inference: triton diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/logger.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/logger.yaml new file mode 100644 index 000000000..6f6483a00 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/logger.yaml @@ -0,0 +1,27 @@ +logger: + _target_: loggers.log_helper.setup_logger + backends: + - _target_: dllogger.JSONStreamBackend + verbosity: 1 #dllogger.Verbosity.VERBOSE + filename: log.json + append: true + - _target_: loggers.backends.AggregatorBackend + verbosity: 1 #dllogger.Verbosity.VERBOSE + agg_dict: + loss: + _target_: loggers.backends.AverageMeter + - _target_: dllogger.StdOutBackend + verbosity: 0 #dllogger.Verbosity.DEFAULT + # The 3 following entries are hacks to prevent recursive instantiation + # and pass function as an argument to StdOutBackend + step_format: + _target_: hydra.utils.get_method + path: loggers.log_helper.empty_step_format + metric_format: + _target_: hydra.utils.get_method + path: loggers.log_helper.no_string_metric_format + prefix_format: + _target_: hydra.utils.get_method + path: loggers.log_helper.empty_prefix_format + #- _target_: loggers.backends.WandBBackend + # verbosity: 1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/auto_arima.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/auto_arima.yaml index 016853f1a..bb8ccefc1 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/auto_arima.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/auto_arima.yaml @@ -1,18 +1,21 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: models.stat_models.AutoARIMA +config: + m: 1 + start_p: 2 + start_q: 2 + max_p: 5 + max_q: 5 + max_d: 2 + start_P: 1 + start_Q: 1 + max_P: 2 + max_Q: 2 + max_D: 1 + information_criterion: aic + method: lbfgs + maxiter: 50 + defaults: - _self_ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dask_xgboost.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dask_xgboost.yaml index 7e3ca8473..2cf58f23a 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dask_xgboost.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dask_xgboost.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: models.tspp_xgboost.TSPPDaskXGBoost config: max_depth: 10 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dcrnn.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dcrnn.yaml new file mode 100644 index 000000000..83a0f79e3 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/dcrnn.yaml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: models.dcrnn.DCRNN +config: + cl_decay_steps: 2000 + horizon: 12 + use_embedding: True + include_static_data: True + input_dim: 2 + max_diffusion_step: 2 + num_nodes: 325 + num_rnn_layers: 2 + output_dim: 1 + rnn_units: 64 + encoder_length: 12 + use_curriculum_learning: true + activation: tanh + model_type: graph + +defaults: + - _self_ + - /trainer@_global_/trainer: ctltrainer diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/deepar.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/deepar.yaml new file mode 100755 index 000000000..71f173f59 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/deepar.yaml @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: models.deepar.DeepAR +config: + model_type: autoregressive + num_layers: 3 + hidden_size: 40 + use_embedding: true + embedding_dim: 20 + dropout: 0.1 + quantiles: [0.5, 0.9] +defaults: + - _self_ + - /trainer@_global_/trainer: ctltrainer diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/lstm.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/lstm.yaml index 5891dc660..277358d45 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/lstm.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/lstm.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: models.lstm.LSTM config: hidden_size: 128 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/mtgnn.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/mtgnn.yaml new file mode 100644 index 000000000..ba27fb447 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/mtgnn.yaml @@ -0,0 +1,23 @@ +_target_: models.mtgnn.MTGNN +config: + use_gcn: True + use_embedding: True + include_static_data: True + gcn_depth: 2 + num_nodes: ${dataset.config.time_series_count} # this will depend on the nodes/ids in the input dataset + dropout: 0.3 + subgraph_size: 20 + node_dim: 40 + dilation_exponential: 1 + conv_channels: 32 + residual_channels: 32 + skip_channels: 64 + end_channels: 128 + in_dim: 2 + out_channels: 12 + num_layers: 3 + propalpha: 0.05 + tanhalpha: 3 +defaults: + - _self_ + - /trainer@_global_/trainer: ctltrainer diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nbeats.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nbeats.yaml new file mode 100644 index 000000000..ce3b6ab0c --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nbeats.yaml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: MIT +_target_: models.nbeats.NBeatsNet +config: + stacks: + - type: "trend" + num_blocks: 3 + theta_dim: 2 + share_weights: True + hidden_size: 256 + - type: "seasonality" + num_blocks: 3 + theta_dim: null + share_weights: True + hidden_size: 2048 +defaults: + - _self_ + - /trainer@_global_/trainer: ctltrainer \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nhits.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nhits.yaml new file mode 100644 index 000000000..d0ab55123 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/nhits.yaml @@ -0,0 +1,15 @@ +_target_: models.nhits.NHITS +config: + n_blocks: [1, 1, 1] + n_mlp_layers: 3 + hidden_size: 512 + n_pool_kernel_size: [2, 2, 1] + n_freq_downsample: [4, 2, 1] + pooling_mode: 'MaxPool1d' + interpolation_mode: 'linear' + dropout_prob_theta: 0. #unused + activation: 'ReLU' + +defaults: + - _self_ + - /trainer@_global_/trainer: ctltrainer diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/tft.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/tft.yaml index ccf27becd..3e4c8d813 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/tft.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/tft.yaml @@ -1,24 +1,11 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -_target_: models.tft_pyt.modeling.TemporalFusionTransformer +# SPDX-License-Identifier: Apache-2.0 +_target_: models.tft.InterpretableTFT config: quantiles: [ .5 ] n_head: 4 hidden_size: 160 dropout: 0.1 - attn_dropout: 0 + attn_dropout: 0.0 output_selector: 0 defaults: - _self_ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/toy_gnn.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/toy_gnn.yaml new file mode 100644 index 000000000..c4d0a1efe --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/toy_gnn.yaml @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: models.gnn.ToyModel +config: + model_type: graph + hidden_size: 128 + num_layers: 3 +defaults: + - _self_ + - /trainer@_global_/trainer: ctltrainer diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/trivial.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/trivial.yaml index 36edaada1..33f0d8233 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/trivial.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/trivial.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: models.trivial_model.TrivialModel defaults: - _self_ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/xgboost.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/xgboost.yaml index a55aeecb9..0d8cb8081 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/xgboost.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model/xgboost.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: models.tspp_xgboost.TSPPXGBoost config: max_depth: 10 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/dcrnn_pems_bay.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/dcrnn_pems_bay.yaml new file mode 100644 index 000000000..5f1278a3f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/dcrnn_pems_bay.yaml @@ -0,0 +1,12 @@ +trainer: + config: + batch_size: 64 + num_epochs: 50 + +dataset: + config: + binarized: False + +evaluator: + config: + batch_size: 64 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_M5.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_M5.yaml new file mode 100644 index 000000000..74961a3b5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_M5.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 100000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_M5_norm.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_M5_norm.yaml new file mode 100644 index 000000000..74961a3b5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_M5_norm.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 100000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_pems_bay.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_pems_bay.yaml new file mode 100644 index 000000000..caefbf770 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/deepar_pems_bay.yaml @@ -0,0 +1,8 @@ +dataset: + config: + train_samples: 1000000 + MultiID: false + binarized: true +trainer: + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/mtgnn_pems_bay.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/mtgnn_pems_bay.yaml new file mode 100644 index 000000000..5f1278a3f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/mtgnn_pems_bay.yaml @@ -0,0 +1,12 @@ +trainer: + config: + batch_size: 64 + num_epochs: 50 + +dataset: + config: + binarized: False + +evaluator: + config: + batch_size: 64 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_M5.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_M5.yaml new file mode 100644 index 000000000..aad3b1ae5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_M5.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 1000000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_M5_norm.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_M5_norm.yaml new file mode 100644 index 000000000..aad3b1ae5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_M5_norm.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 1000000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_electricity.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_electricity.yaml new file mode 100644 index 000000000..14784570b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_electricity.yaml @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: MIT +model: + config: + stacks: + - type: "generic" + num_blocks: 4 + theta_dim: 8 + share_weights: False + hidden_size: 1024 + - type: "generic" + num_blocks: 4 + theta_dim: 8 + share_weights: False + hidden_size: 2048 + +trainer: + config: + batch_size: 16384 + num_epochs: 20 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_pems_bay.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_pems_bay.yaml new file mode 100644 index 000000000..de0ea27eb --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_pems_bay.yaml @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: MIT +trainer: + config: + batch_size: 16384 + num_epochs: 20 + +dataset: + config: + MultiID: false diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_traffic.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_traffic.yaml new file mode 100644 index 000000000..fd654f8e4 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nbeats_traffic.yaml @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: MIT +model: + config: + stacks: + - type: "generic" + num_blocks: 8 + theta_dim: 2 + share_weights: True + hidden_size: 2048 + - type: "generic" + num_blocks: 8 + theta_dim: 2 + share_weights: False + hidden_size: 1024 + +trainer: + config: + batch_size: 16384 + num_epochs: 20 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nhits_M5.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nhits_M5.yaml new file mode 100644 index 000000000..aad3b1ae5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nhits_M5.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 1000000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nhits_M5_norm.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nhits_M5_norm.yaml new file mode 100644 index 000000000..aad3b1ae5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/nhits_M5_norm.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 1000000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_M5.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_M5.yaml new file mode 100755 index 000000000..74961a3b5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_M5.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 100000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_M5_norm.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_M5_norm.yaml new file mode 100755 index 000000000..74961a3b5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_M5_norm.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: MIT +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + +dataset: + config: + train_samples: 100000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_electricity.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_electricity.yaml index 562183d56..b482208c0 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_electricity.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_electricity.yaml @@ -1,23 +1,13 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 model: config: n_head: 4 hidden_size: 128 dropout: 0.1 - attn_dropout: 0 + attn_dropout: 0.0 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + trainer: config: batch_size: 1024 @@ -25,4 +15,15 @@ trainer: gradient_norm: 1.0 optimizer: lr: .001 + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_favorita.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_favorita.yaml new file mode 100755 index 000000000..6322ea221 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_favorita.yaml @@ -0,0 +1,13 @@ +model: + config: + n_head: 4 + hidden_size: 240 + dropout: 0.1 + attn_dropout: 0.0 +trainer: + config: + batch_size: 1024 + num_epochs: 20 + gradient_norm: 1.0 + optimizer: + lr: .001 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_pems_bay.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_pems_bay.yaml new file mode 100644 index 000000000..73e77cec9 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_pems_bay.yaml @@ -0,0 +1,13 @@ +dataset: + config: + MultiID: false + +model: + config: + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +trainer: + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_traffic.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_traffic.yaml index 3d701bdf0..385ecf3b0 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_traffic.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/tft_traffic.yaml @@ -1,23 +1,10 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 model: config: n_head: 4 hidden_size: 128 dropout: 0.3 - attn_dropout: 0 + attn_dropout: 0.0 trainer: config: batch_size: 1024 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_M5.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_M5.yaml new file mode 100644 index 000000000..7b6de3cb1 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_M5.yaml @@ -0,0 +1,15 @@ +dataset: + config: + lag_features: + - name: value + min_value: 1 + max_value: 25 +model: + config: + max_depth: 6 + learning_rate: 0.17 + subsample: 1.0 + colsample_bytree: 0.8 + colsample_bylevel: 0.8 + gamma: 0.1 + n_rounds: 300 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_M5_xgb.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_M5_xgb.yaml new file mode 100644 index 000000000..ef810f033 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_M5_xgb.yaml @@ -0,0 +1,59 @@ +dataset: + config: + lag_features: + - name: items_sold + min_value: 1 + max_value: 15 + moving_average_features: + - name: items_sold + window_size: 28 + op: median + - name: items_sold + window_size: 28 + op: mean + - name: items_sold + window_size: 28 + op: max + - name: items_sold + window_size: 28 + op: min + - name: items_sold + window_size: 28 + op: std + - name: items_sold + window_size: 7 + op: median + - name: items_sold + window_size: 7 + op: mean + - name: items_sold + window_size: 7 + op: max + - name: items_sold + window_size: 7 + op: min + - name: items_sold + window_size: 7 + op: std +model: + config: + max_depth: 8 + learning_rate: 0.04 + eta: 0.04 + subsample: 0.85 + colsample_bytree: 0.95 + objective: reg:absoluteerror + nthread: 28 + n_rounds: 10000 + eval_metric: mae + +evaluator: + postprocessor: + _target_: evaluators.evaluator.Postprocessor + transformations: + - _target_: conf.conf_utils.partial + func: numpy.clip + a_min: 0 + a_max: .inf + - _target_: conf.conf_utils.partial + func: numpy.round \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_electricity.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_electricity.yaml index 239bc3c19..b4d7d5920 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_electricity.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_electricity.yaml @@ -1,29 +1,15 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - dataset: config: + binarized: false lag_features: - name: power_usage min_value: 1 - max_value: 96 + max_value: 168 model: config: - max_depth: 14 - learning_rate: 0.017 - subsample: 0.8 - colsample_bytree: 1.0 - colsample_bylevel: 0.4 - gamma: 0.3 - n_rounds: 250 + max_depth: 8 + learning_rate: 0.05 # alias: eta + subsample: 1.00 + colsample_bytree: 0.90 + objective: reg:absoluteerror + n_rounds: 1250 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_electricity_xgb.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_electricity_xgb.yaml new file mode 100644 index 000000000..632b01187 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_electricity_xgb.yaml @@ -0,0 +1,20 @@ +dataset: + config: + binarized: false + lag_features: + - name: power_usage + min_value: 1 + max_value: 168 +model: + config: + max_depth: 8 + learning_rate: 0.01 # alias: eta + subsample: 1.00 + colsample_bytree: 0.90 + objective: reg:absoluteerror + n_rounds: 1250 + +trainer: + callbacks: + early_stopping: + patience: null diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_pems_bay_xgb.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_pems_bay_xgb.yaml new file mode 100644 index 000000000..dfdd46d69 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/model_dataset/xgboost_pems_bay_xgb.yaml @@ -0,0 +1,20 @@ +dataset: + config: + binarized: false + lag_features: + - name: 'Avg Speed' + min_value: 1 + max_value: 12 +model: + config: + max_depth: 7 + learning_rate: 0.01 # alias: eta + subsample: 0.95 + colsample_bytree: 0.95 + objective: reg:absoluteerror + n_rounds: 5000 + +trainer: + callbacks: + early_stopping: + patience: 100 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_0.yaml new file mode 100644 index 000000000..d52a430ba --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_0.yaml @@ -0,0 +1,38 @@ +trainer: + config: + ema_decay: 0.9898414465903542 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 0.007960833618894748 + + criterion: + _target_: criterion.TweedieLoss + p: 1.4874648950107958 + +model: + config: + stacks: + - type: "trend" + num_blocks: 2 + theta_dim: 2 + share_weights: False + hidden_size: 2048 + - type: "seasonality" + num_blocks: 2 + theta_dim: 0 + share_weights: False + hidden_size: 2048 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_1.yaml new file mode 100644 index 000000000..32aa95f1e --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_1.yaml @@ -0,0 +1,37 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 0.005938839698979487 + + criterion: + _target_: criterion.TweedieLoss + p: 1.6113852243885698 + +model: + config: + stacks: + - type: "generic" + num_blocks: 8 + theta_dim: 8 + share_weights: False + hidden_size: 4096 + - type: "seasonality" + num_blocks: 8 + theta_dim: 8 + share_weights: True + hidden_size: 256 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_2.yaml new file mode 100644 index 000000000..62cd05cc3 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_2.yaml @@ -0,0 +1,38 @@ +trainer: + config: + ema_decay: 0.9592185308032316 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 0.00018694983658104237 + + criterion: + _target_: criterion.TweedieLoss + p: 1.01229737216246 + +model: + config: + stacks: + - type: "trend" + num_blocks: 8 + theta_dim: 8 + share_weights: False + hidden_size: 2048 + - type: "seasonality" + num_blocks: 2 + theta_dim: 0 + share_weights: False + hidden_size: 512 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_3.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_3.yaml new file mode 100644 index 000000000..6b6a5bbb5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/best_3.yaml @@ -0,0 +1,37 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 0.00018694983658104237 + + criterion: + _target_: criterion.TweedieLoss + p: 1.1348446229080165 + +model: + config: + stacks: + - type: "trend" + num_blocks: 8 + theta_dim: 2 + share_weights: False + hidden_size: 2048 + - type: "generic" + num_blocks: 2 + theta_dim: 0 + share_weights: False + hidden_size: 2048 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/hp_search.yaml new file mode 100644 index 000000000..27440a4f0 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nbeats/hp_search.yaml @@ -0,0 +1,28 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(256,512,1024,2048,4096) + model.config.stacks.1.hidden_size: choice(256,512,1024,2048) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(tweedie) + trainer.criterion.p: interval(1.01, 1.9) + +trainer: + config: + batch_size: 16384 + num_epochs: 30 + +dataset: + config: + train_samples: 100000 + memory_mapped: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_0.yaml new file mode 100644 index 000000000..1b773dd6a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_0.yaml @@ -0,0 +1,33 @@ +trainer: + config: + ema_decay: 0.9101936248008481 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 0.0004632887748560879 + + criterion: + _target_: criterion.TweedieLoss + p: 1.033391495108709 + +model: + config: + activation: ReLU + pooling_mode: MaxPool1d + hidden_size: 1024 + n_blocks: [1,2,1] + n_freq_downsample: [4,2,1] + n_pool_kernel_size: [4,2,1] + n_mlp_layers: 4 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_1.yaml new file mode 100644 index 000000000..ef9286812 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_1.yaml @@ -0,0 +1,32 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 2.2641405995693264e-05 + + criterion: + _target_: criterion.TweedieLoss + p: 1.033391495108709 + +model: + config: + activation: ReLU + pooling_mode: AvgPool1d + hidden_size: 2048 + n_blocks: [1,1,2] + n_freq_downsample: [4,2,1] + n_pool_kernel_size: [2,2,1] + n_mlp_layers: 4 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_2.yaml new file mode 100644 index 000000000..c3b2d59ea --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_2.yaml @@ -0,0 +1,33 @@ +trainer: + config: + ema_decay: 0.960244325551214 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 0.005050844709519404 + + criterion: + _target_: criterion.TweedieLoss + p: 1.474664464655759 + +model: + config: + activation: SELU + pooling_mode: MaxPool1d + hidden_size: 2048 + n_blocks: [1,1,2] + n_freq_downsample: [4,2,1] + n_pool_kernel_size: [6,3,1] + n_mlp_layers: 3 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_3.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_3.yaml new file mode 100644 index 000000000..585a34d6c --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/best_3.yaml @@ -0,0 +1,33 @@ +trainer: + config: + ema_decay: 0.9722933574544365 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 3.848204675023239e-05 + + criterion: + _target_: criterion.TweedieLoss + p: 1.8099786820097208 + +model: + config: + activation: Sigmoid + pooling_mode: MaxPool1d + hidden_size: 256 + n_blocks: [2,2,2] + n_freq_downsample: [2,2,1] + n_pool_kernel_size: [3,3,1] + n_mlp_layers: 3 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/hp_search.yaml new file mode 100644 index 000000000..12ecb550a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/nhits/hp_search.yaml @@ -0,0 +1,27 @@ +hydra: + sweeper: + params: + model.config.n_mlp_layers: choice(2,3,4) + model.config.hidden_size: choice(256,512,1024,2048) + model.config.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.n_blocks: choice([1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]) + model.config.n_pool_kernel_size: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + model.config.n_freq_downsample: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(tweedie) + trainer.criterion.p: interval(1.01,1.9) + +trainer: + config: + batch_size: 16384 + num_epochs: 15 + +dataset: + config: + train_samples: 100000 + memory_mapped: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_0.yaml new file mode 100644 index 000000000..cc2408269 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_0.yaml @@ -0,0 +1,28 @@ +trainer: + config: + ema_decay: 0.9412710347501564 + batch_size: 1024 + ema: True + num_epochs: 20 + + optimizer: + lr: 0.0003946489348284673 + + criterion: + _target_: criterion.TweedieLoss + p: 1.1011198699619675 + +model: + config: + dropout: 0.8065306916236111 + hidden_size: 256 + n_head: 1 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_1.yaml new file mode 100644 index 000000000..1c44ed1bc --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_1.yaml @@ -0,0 +1,27 @@ +trainer: + config: + batch_size: 1024 + ema: False + num_epochs: 20 + + optimizer: + lr: 0.0005273969385515224 + + criterion: + _target_: criterion.TweedieLoss + p: 1.2220328364966142 + +model: + config: + dropout: 0.6037804765285399 + hidden_size: 384 + n_head: 1 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_2.yaml new file mode 100644 index 000000000..ca36da4c3 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/best_2.yaml @@ -0,0 +1,28 @@ +trainer: + config: + batch_size: 1024 + ema: True + ema_decay: 0.9797380207850296 + num_epochs: 20 + + optimizer: + lr: 0.008005401622327324 + + criterion: + _target_: criterion.TweedieLoss + p: 1.271190112897211 + +model: + config: + dropout: 0.23499650892965934 + hidden_size: 384 + n_head: 4 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/hp_search.yaml new file mode 100644 index 000000000..009ef77b4 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5/tft/hp_search.yaml @@ -0,0 +1,21 @@ +hydra: + sweeper: + params: + model.config.n_head: choice(1,2,4) + model.config.hidden_size: choice(128,196,256,384) + model.config.dropout: interval(0.0, 0.9) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer.config.batch_size: choice(1024) + trainer/criterion: choice(tweedie) + trainer.criterion.p: interval(1.1,1.7) + +trainer: + config: + num_epochs: 10 + +dataset: + config: + train_samples: 100000 + memory_mapped: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_0.yaml new file mode 100644 index 000000000..2bb2d4225 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_0.yaml @@ -0,0 +1,27 @@ +trainer: + config: + ema_decay: 0.9602099240857632 + ema: True + batch_size: 128 + num_epochs: 20 + optimizer: + lr: 0.000530089353065201 + criterion: + _target_: torch.nn.L1Loss + + +model: + config: + dropout: 0.31763710503690956 + embedding_dim: 8 + hidden_size: 512 + num_layers: 4 + +dataset: + config: + train_samples: 1000000 + memory_mapped: True + +evaluator: + config: + save_predictions: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_1.yaml new file mode 100644 index 000000000..a499cc69f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_1.yaml @@ -0,0 +1,26 @@ +trainer: + config: + ema: False + batch_size: 128 + num_epochs: 20 + optimizer: + lr: 0.0050003507487785225 + criterion: + _target_: torch.nn.L1Loss + + +model: + config: + dropout: 0.6408337621928981 + embedding_dim: 32 + hidden_size: 512 + num_layers: 4 + +dataset: + config: + train_samples: 1000000 + memory_mapped: True + +evaluator: + config: + save_predictions: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_2.yaml new file mode 100644 index 000000000..fd15d9f60 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/best_2.yaml @@ -0,0 +1,27 @@ +trainer: + config: + ema: True + ema_decay: 0.9801014862597447 + batch_size: 128 + num_epochs: 20 + optimizer: + lr: 1.9813457277507318e-05 + criterion: + _target_: torch.nn.L1Loss + + +model: + config: + dropout: 0.6075438265717921 + embedding_dim: 32 + hidden_size: 512 + num_layers: 4 + +dataset: + config: + train_samples: 1000000 + memory_mapped: True + +evaluator: + config: + save_predictions: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/hp_search.yaml new file mode 100644 index 000000000..fb2e97f8b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/deepar/hp_search.yaml @@ -0,0 +1,25 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(1,2,3,4,5) + model.config.hidden_size: choice(64, 128, 256, 384, 512) + model.config.embedding_dim: choice(8, 16, 32, 64) + model.config.dropout: interval(0, 1) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer.config.batch_size: choice(128) +model: + config: + use_embedding: true + +trainer: + config: + num_epochs: 20 + criterion: + _target_: torch.nn.L1Loss + +dataset: + config: + train_samples: 100000 + memory_mapped: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_0.yaml new file mode 100644 index 000000000..af952dd75 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_0.yaml @@ -0,0 +1,37 @@ +trainer: + config: + ema_decay: 0.9453562159037722 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 0.000718489072451614 + + criterion: + _target_: torch.nn.L1Loss + +model: + config: + stacks: + - type: "trend" + num_blocks: 8 + theta_dim: 16 + share_weights: True + hidden_size: 256 + - type: "generic" + num_blocks: 8 + theta_dim: 2 + share_weights: False + hidden_size: 1024 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_1.yaml new file mode 100644 index 000000000..562763e18 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_1.yaml @@ -0,0 +1,36 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 0.00034901859204728374 + + criterion: + _target_: torch.nn.L1Loss + +model: + config: + stacks: + - type: "generic" + num_blocks: 4 + theta_dim: 2 + share_weights: True + hidden_size: 4096 + - type: "generic" + num_blocks: 4 + theta_dim: 0 + share_weights: True + hidden_size: 1024 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_2.yaml new file mode 100644 index 000000000..9c6880860 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_2.yaml @@ -0,0 +1,37 @@ +trainer: + config: + ema_decay: 0.9964991211236364 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 0.001319875127042448 + + criterion: + _target_: torch.nn.L1Loss + +model: + config: + stacks: + - type: "trend" + num_blocks: 8 + theta_dim: 2 + share_weights: True + hidden_size: 4096 + - type: "seasonality" + num_blocks: 8 + theta_dim: 2 + share_weights: True + hidden_size: 1024 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_3.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_3.yaml new file mode 100644 index 000000000..cca890a8b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/best_3.yaml @@ -0,0 +1,37 @@ +trainer: + config: + ema_decay: 0.9713445961834636 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 1.0430232386402735e-05 + + criterion: + _target_: torch.nn.L1Loss + +model: + config: + stacks: + - type: "trend" + num_blocks: 8 + theta_dim: 2 + share_weights: True + hidden_size: 2048 + - type: "seasonality" + num_blocks: 8 + theta_dim: 0 + share_weights: True + hidden_size: 1024 + + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/hp_search.yaml new file mode 100644 index 000000000..e79107040 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nbeats/hp_search.yaml @@ -0,0 +1,28 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(256,512,1024,2048,4096) + model.config.stacks.1.hidden_size: choice(256,512,1024,2048) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +trainer: + config: + batch_size: 16384 + num_epochs: 30 + criterion: + _target_: torch.nn.L1Loss + +dataset: + config: + train_samples: 100000 + memory_mapped: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_0.yaml new file mode 100644 index 000000000..b94143e7e --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_0.yaml @@ -0,0 +1,32 @@ +trainer: + config: + ema_decay: 0.9718722865939765 + batch_size: 16384 + ema: True + num_epochs: 30 + + optimizer: + lr: 0.00035461667991371743 + + criterion: + _target_: torch.nn.L1Loss + +model: + config: + activation: LeakyReLU + pooling_mode: AvgPool1d + hidden_size: 2048 + n_blocks: [1,1,1] + n_freq_downsample: [6,2,1] + n_pool_kernel_size: [4,2,1] + n_mlp_layers: 4 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_1.yaml new file mode 100644 index 000000000..a8067c065 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_1.yaml @@ -0,0 +1,31 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 0.00015674511791776498 + + criterion: + _target_: torch.nn.L1Loss + +model: + config: + activation: LeakyReLU + pooling_mode: AvgPool1d + hidden_size: 2048 + n_blocks: [2,1,2] + n_freq_downsample: [6,2,1] + n_pool_kernel_size: [4,2,1] + n_mlp_layers: 4 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_2.yaml new file mode 100644 index 000000000..396299a14 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_2.yaml @@ -0,0 +1,31 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 0.00048837469680114 + + criterion: + _target_: torch.nn.MSELoss + +model: + config: + activation: Sigmoid + pooling_mode: AvgPool1d + hidden_size: 2048 + n_blocks: [2,1,1] + n_freq_downsample: [2,2,1] + n_pool_kernel_size: [6,3,1] + n_mlp_layers: 2 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_3.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_3.yaml new file mode 100644 index 000000000..e5926fee9 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_3.yaml @@ -0,0 +1,31 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 0.003778126865168513 + + criterion: + _target_: torch.nn.L1Loss + +model: + config: + activation: Tanh + pooling_mode: MaxPool1d + hidden_size: 2048 + n_blocks: [1,2,2] + n_freq_downsample: [6,2,1] + n_pool_kernel_size: [3,3,1] + n_mlp_layers: 3 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_4.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_4.yaml new file mode 100644 index 000000000..72879acb2 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/best_4.yaml @@ -0,0 +1,31 @@ +trainer: + config: + batch_size: 16384 + ema: False + num_epochs: 30 + + optimizer: + lr: 0.0013416697802442908 + + criterion: + _target_: torch.nn.MSELoss + +model: + config: + activation: Sigmoid + pooling_mode: AvgPool1d + hidden_size: 2048 + n_blocks: [2,1,1] + n_freq_downsample: [6,2,1] + n_pool_kernel_size: [6,3,1] + n_mlp_layers: 2 + +dataset: + config: + memory_mapped: True + train_samples: 1000000 + +evaluator: + config: + save_predictions: True + batch_size: 16384 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/hp_search.yaml new file mode 100644 index 000000000..49d8e31bd --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/M5_norm/nhits/hp_search.yaml @@ -0,0 +1,26 @@ +hydra: + sweeper: + params: + model.config.n_mlp_layers: choice(2,3,4) + model.config.hidden_size: choice(256,512,1024,2048) + model.config.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.n_blocks: choice([1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]) + model.config.n_pool_kernel_size: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + model.config.n_freq_downsample: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +trainer: + config: + batch_size: 16384 + num_epochs: 15 + +dataset: + config: + train_samples: 100000 + memory_mapped: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/best_0.yaml new file mode 100644 index 000000000..04b8fb933 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/best_0.yaml @@ -0,0 +1,18 @@ +model: + config: + dropout: 0.4606209738408481 + embedding_dim: 16 + hidden_size: 1024 + num_layers: 2 + use_embedding: True + +trainer: + config: + ema_decay: 0.9706002746650126 + ema: True + num_epochs: 5 + batch_size: 128 + optimizer: + lr: 0.0019708069790932334 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/best_1.yaml new file mode 100644 index 000000000..58ef7204e --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/best_1.yaml @@ -0,0 +1,18 @@ +model: + config: + dropout: 0.27372390753918013 + embedding_dim: 32 + hidden_size: 256 + num_layers: 2 + use_embedding: True + +trainer: + config: + ema_decay: 0.9822555327211008 + ema: True + num_epochs: 5 + batch_size: 128 + optimizer: + lr: 0.0010081454440377322 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search.yaml new file mode 100644 index 000000000..f6e8c055b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search.yaml @@ -0,0 +1,20 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(256,512,1024) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.6) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.95, 0.9999) + trainer.config.batch_size: choice(128,512,1024) +model: + config: + use_embedding: true + +trainer: + config: + num_epochs: 10 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search_bs128_cl.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search_bs128_cl.yaml new file mode 100644 index 000000000..a657faf84 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search_bs128_cl.yaml @@ -0,0 +1,22 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(256,512,1024) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.6) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.95, 0.9999) + +trainer.config.cl_update: choice(300,500,1000,1500) +model: + config: + use_embedding: true + +trainer: + config: + cl_start_horizon: 1 + batch_size: 128 + num_epochs: 7 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search_bs128_enc_dec.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search_bs128_enc_dec.yaml new file mode 100644 index 000000000..d9e3c7754 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/deepar/hp_search_bs128_enc_dec.yaml @@ -0,0 +1,21 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.6) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + _target_: models.deepar_v2.DeepAR + config: + use_embedding: true + use_decoder: true +trainer: + config: + batch_size: 128 + num_epochs: 7 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/best_0.yaml new file mode 100644 index 000000000..4b23a216d --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/best_0.yaml @@ -0,0 +1,37 @@ +model: + config: + in_dim: 32 + conv_channels: 32 + end_channels: 32 + residual_channels: 16 + skip_channels: 64 + subgraph_size: 15 + num_layers: 2 + node_dim: 128 + gcn_depth: 3 + propalpha: 0.1436050341698628 + dropout: 0.39020897175131136 + tanhalpha: 2.761077470114226 + temporal_observed_continuous_inp_size: 0 + +trainer: + config: + ema: True + ema_decay: 0.9831133243513078 + batch_size: 16 + num_epochs: 25 + optimizer: + lr: 0.00024334834818612688 + criterion: + _target_: torch.nn.L1Loss + +dataset: + config: + binarized: False + MultiID: True + train_samples: -1 + valid_samples: -1 + +evaluator: + config: + batch_size: 16 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/hp_search.yaml new file mode 100644 index 000000000..3042888e4 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/hp_search.yaml @@ -0,0 +1,38 @@ +hydra: + sweeper: + params: + model.config.gcn_depth: choice(2,3,4) + model.config.dropout: interval(0,0.5) + model.config.subgraph_size: choice(10,15,20) + model.config.node_dim: choice(32,40,64,128) + model.config.conv_channels: choice(16,32,64) + model.config.residual_channels: choice(16,32,64) + model.config.skip_channels: choice(32,64) + model.config.end_channels: choice(32,64) + model.config.num_layers: choice(2,3,4) + model.config.propalpha: interval(0.01, 0.2) + model.config.tanhalpha: interval(2, 4) + model.config.in_dim: choice(16, 24, 32, 64) + trainer.optimizer.lr: tag(log, interval(5e-5, 5e-3)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +model: + config: + use_embedding: true + temporal_observed_continuous_inp_size: 0 +trainer: + config: + batch_size: 16 + num_epochs: 25 +evaluator: + config: + batch_size: 16 + +dataset: + config: + binarized: False + MultiID: True + train_samples: -1 + valid_samples: -1 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/hp_search_cl.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/hp_search_cl.yaml new file mode 100644 index 000000000..ffe671123 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/mtgnn/hp_search_cl.yaml @@ -0,0 +1,40 @@ +hydra: + sweeper: + params: + model.config.gcn_depth: choice(2,3,4) + model.config.dropout: interval(0,0.5) + model.config.subgraph_size: choice(10,15,20) + model.config.node_dim: choice(32,40,64,128) + model.config.conv_channels: choice(16,32,64) + model.config.residual_channels: choice(16,32,64) + model.config.skip_channels: choice(32,64) + model.config.end_channels: choice(32,64) + model.config.num_layers: choice(2,3,4) + model.config.propalpha: interval(0.01, 0.2) + model.config.tanhalpha: interval(2, 4) + model.config.in_dim: choice(16, 24, 32, 64) + trainer.optimizer.lr: tag(log, interval(5e-5, 5e-3)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +trainer.config.cl_update: choice(100,300,500,1000,1500) + +model: + config: + use_embedding: true + temporal_observed_continuous_inp_size: 0 +trainer: + config: + cl_start_horizon: 1 + batch_size: 16 + num_epochs: 25 +evaluator: + config: + batch_size: 16 + +dataset: + config: + binarized: False + MultiID: True + train_samples: -1 + valid_samples: -1 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/best_0.yaml new file mode 100644 index 000000000..8ada84937 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/best_0.yaml @@ -0,0 +1,22 @@ +model: + config: + stacks: + - type: "trend" + num_blocks: 4 + theta_dim: 2 + share_weights: True + hidden_size: 1024 + - type: "generic" + num_blocks: 8 + theta_dim: 0 + share_weights: False + hidden_size: 2048 + +trainer: + config: + batch_size: 16384 + num_epochs: 20 + ema: true + ema_decay: 0.9497343596459132 + optimizer: + lr: 0.00020687079735984997 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/best_1.yaml new file mode 100644 index 000000000..d949e3915 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/best_1.yaml @@ -0,0 +1,22 @@ +model: + config: + stacks: + - type: "trend" + num_blocks: 4 + theta_dim: 2 + share_weights: True + hidden_size: 2048 + - type: "seasonality" + num_blocks: 2 + theta_dim: 0 + share_weights: False + hidden_size: 2048 + +trainer: + config: + batch_size: 16384 + num_epochs: 20 + ema: true + ema_decay: 0.9463339577642854 + optimizer: + lr: 0.0002713846381337294 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search.yaml new file mode 100644 index 000000000..4d9b2fed8 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search.yaml @@ -0,0 +1,21 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(512,1024,2048) + model.config.stacks.1.hidden_size: choice(512,1024,2048,4096) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +trainer: + config: + batch_size: 16384 + num_epochs: 15 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search_bs.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search_bs.yaml new file mode 100644 index 000000000..28c58af06 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search_bs.yaml @@ -0,0 +1,21 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(512,1024,2048) + model.config.stacks.1.hidden_size: choice(512,1024,2048,4096) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer.config.batch_size: choice(2048, 4096, 8192, 16384) + +trainer: + config: + num_epochs: 15 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search_cl.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search_cl.yaml new file mode 100644 index 000000000..f64cf9c67 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nbeats/hp_search_cl.yaml @@ -0,0 +1,22 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(512,1024,2048) + model.config.stacks.1.hidden_size: choice(512,1024,2048,4096) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +trainer.config.cl_update: choice(10,20,40,80) + +trainer: + config: + cl_start_horizon: 1 + num_epochs: 30 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_0.yaml new file mode 100644 index 000000000..6844895b7 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_0.yaml @@ -0,0 +1,23 @@ +model: + config: + n_mlp_layers: 4 + hidden_size: 2048 + activation: ReLU + pooling_mode: MaxPool1d + + n_blocks: [2,1,2] + n_pool_kernel_size: [2,2,1] + n_freq_downsample: [6,3,1] + +trainer: + config: + ema: True + ema_decay: 0.9703328617748128 + batch_size: 16384 + num_epochs: 25 + + optimizer: + lr: 0.0003483066522056015 + + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_1.yaml new file mode 100644 index 000000000..9d8160e05 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_1.yaml @@ -0,0 +1,23 @@ +model: + config: + n_mlp_layers: 4 + hidden_size: 2048 + activation: LeakyReLU + pooling_mode: MaxPool1d + + n_blocks: [1,1,1] + n_pool_kernel_size: [4,2,1] + n_freq_downsample: [3,3,1] + +trainer: + config: + ema: True + ema_decay: 0.9502714434518807 + batch_size: 16384 + num_epochs: 25 + + optimizer: + lr: 0.000172795261984175 + + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_2.yaml new file mode 100644 index 000000000..0ff0a72e6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/best_2.yaml @@ -0,0 +1,23 @@ +model: + config: + n_mlp_layers: 4 + hidden_size: 2048 + activation: LeakyReLU + pooling_mode: MaxPool1d + + n_blocks: [1,1,2] + n_pool_kernel_size: [4,2,1] + n_freq_downsample: [3,3,1] + +trainer: + config: + ema: True + ema_decay: 0.9335330777104768 + batch_size: 16384 + num_epochs: 25 + + optimizer: + lr: 0.00022546442573097015 + + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/hp_search.yaml new file mode 100644 index 000000000..1edf8ed6c --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/nhits/hp_search.yaml @@ -0,0 +1,21 @@ +hydra: + sweeper: + params: + model.config.n_mlp_layers: choice(2,3,4) + model.config.hidden_size: choice(256,512,1024,2048) + model.config.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.n_blocks: choice([1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]) + model.config.n_pool_kernel_size: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + model.config.n_freq_downsample: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +trainer: + config: + batch_size: 16384 + num_epochs: 15 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_0.yaml new file mode 100644 index 000000000..4bbf048a6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_0.yaml @@ -0,0 +1,21 @@ +model: + config: + dropout: 0.016031236175686903 + hidden_size: 192 + n_head: 2 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +trainer: + config: + ema: True + ema_decay: 0.9960484760709238 + batch_size: 1024 + num_epochs: 15 + + optimizer: + lr: 0.002173780101542564 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_1.yaml new file mode 100644 index 000000000..17ae4feaf --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_1.yaml @@ -0,0 +1,21 @@ +model: + config: + dropout: 0.07066822668168525 + hidden_size: 192 + n_head: 2 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +trainer: + config: + ema: True + ema_decay: 0.9975301913477509 + batch_size: 1024 + num_epochs: 15 + + optimizer: + lr: 0.001887233159762666 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_2.yaml new file mode 100644 index 000000000..832f6193c --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/best_2.yaml @@ -0,0 +1,21 @@ +model: + config: + dropout: 0.04391771729319136 + hidden_size: 256 + n_head: 2 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +trainer: + config: + ema: True + ema_decay: 0.9965621619369646 + batch_size: 1024 + num_epochs: 15 + + optimizer: + lr: 0.003036631689885819 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/hp_search.yaml new file mode 100644 index 000000000..aaf6ee246 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/hp_search.yaml @@ -0,0 +1,15 @@ +hydra: + sweeper: + params: + model.config.n_head: choice(1,2,4) + model.config.hidden_size: choice(128,192,256,512) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer.config.batch_size: choice(256, 512, 1024) + +trainer: + config: + num_epochs: 15 + diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/hp_search_cl.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/hp_search_cl.yaml new file mode 100644 index 000000000..0d9c563bc --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity/tft/hp_search_cl.yaml @@ -0,0 +1,16 @@ +hydra: + sweeper: + params: + model.config.n_head: choice(1,2,4) + model.config.hidden_size: choice(128,192,256,512) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +trainer.config.cl_update: choice(300,500,1000,1500) + +trainer: + config: + cl_start_horizon: 1 + num_epochs: 15 + diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity_xgb/xgboost/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity_xgb/xgboost/best_0.yaml new file mode 100644 index 000000000..8c2ed3aa3 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity_xgb/xgboost/best_0.yaml @@ -0,0 +1,20 @@ +dataset: + config: + binarized: false + lag_features: + - name: power_usage + min_value: 1 + max_value: 168 +model: + config: + max_depth: 8 + learning_rate: 0.01 # alias: eta + subsample: 1.00 + colsample_bytree: 0.90 + objective: reg:absoluteerror + n_rounds: 1250 + +trainer: + callbacks: + early_stopping: + patience: null \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity_xgb/xgboost/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity_xgb/xgboost/hp_search.yaml new file mode 100644 index 000000000..741b3d5d6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/electricity_xgb/xgboost/hp_search.yaml @@ -0,0 +1,10 @@ +hydra: + sweeper: + params: + model.config.max_depth: choice(4,5,6,7,8,9) + model.config.learning_rate: interval(1e-4, 1e-2) + model.config.subsample: interval(0.7,1) + model.config.colsample_bytree: interval(0.8,1) + model.config.n_rounds: choice(300, 500, 750, 1000, 1250, 1500, 2000) + model.config.objective: choice(reg:squarederror, reg:absolutederror) + +model.config.min_child_weight: choice(1,2,4,8,16,32) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/best_0.yaml new file mode 100644 index 000000000..70dff6b40 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/best_0.yaml @@ -0,0 +1,23 @@ +model: + config: + activation: tanh + include_static_data: True + input_dim: 4 + max_diffusion_step: 1 + num_rnn_layers: 3 + rnn_units: 64 + use_embedding: True +trainer: + config: + ema_decay: 0.9950636293275859 + ema: True + batch_size: 64 + num_epochs: 50 + optimizer: + lr: 0.0031505002992112388 + criterion: + _target_: torch.nn.L1Loss + +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/best_1.yaml new file mode 100644 index 000000000..70f55fa6d --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/best_1.yaml @@ -0,0 +1,23 @@ +model: + config: + activation: tanh + include_static_data: True + input_dim: 8 + max_diffusion_step: 1 + num_rnn_layers: 2 + rnn_units: 64 + use_embedding: True +trainer: + config: + ema_decay: 0.9971634063439073 + ema: True + batch_size: 64 + num_epochs: 50 + optimizer: + lr: 0.002047912357577 + criterion: + _target_: torch.nn.MSELoss + +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search.yaml new file mode 100644 index 000000000..1780aec38 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search.yaml @@ -0,0 +1,21 @@ +hydra: + sweeper: + params: + model.config.max_diffusion_step: choice(1,2) + model.config.num_rnn_layers: choice(2,3) + model.config.rnn_units: choice(32,64,128) + model.config.activation: choice(tanh,relu) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9,0.9999) + trainer.optimizer.lr: tag(log,interval(1e-5,1e-2)) + trainer/criterion: choice(L1,MSE) +trainer: + config: + batch_size: 64 + num_epochs: 30 +evaluator: + config: + batch_size: 64 +dataset: + config: + graph: true \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search_embedding_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search_embedding_1.yaml new file mode 100644 index 000000000..ee6ff34b6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search_embedding_1.yaml @@ -0,0 +1,20 @@ +hydra: + sweeper: + params: + model.config.max_diffusion_step: choice(1,2) + model.config.num_rnn_layers: choice(2,3) + model.config.input_dim: choice(4,8,16,32) + model.config.rnn_units: choice(32,64) + model.config.activation: choice(tanh,relu) + model.config.include_static_data: choice(true,false) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9,0.9999) + trainer.optimizer.lr: tag(log,interval(1e-5,1e-2)) + trainer/criterion: choice(L1,MSE) +trainer: + config: + batch_size: 64 + num_epochs: 30 +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search_embedding_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search_embedding_2.yaml new file mode 100644 index 000000000..184af98e5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/dcrnn/hp_search_embedding_2.yaml @@ -0,0 +1,23 @@ +hydra: + sweeper: + params: + model.config.max_diffusion_step: choice(1,2) + model.config.input_dim: choice(4,8,16,32) + model.config.activation: choice(tanh,relu) + model.config.include_static_data: choice(true,false) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9,0.9999) + trainer.optimizer.lr: tag(log,interval(1e-5,1e-2)) + trainer/criterion: choice(L1,MSE) + +model: + config: + num_rnn_layers: 2 + rnn_units: 128 +trainer: + config: + batch_size: 64 + num_epochs: 30 +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/best_0.yaml new file mode 100644 index 000000000..03c6ad8ff --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/best_0.yaml @@ -0,0 +1,24 @@ +model: + config: + dropout: 0.4314910225729797 + embedding_dim: 32 + hidden_size: 512 + num_layers: 2 + use_embedding: True + +trainer: + config: + ema_decay: 0.977085992883599 + ema: True + num_epochs: 30 + batch_size: 1024 + optimizer: + lr: 0.000290039852036727 + criterion: + _target_: criterion.GaussianLogLikelihood + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs1024_embed_broad.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs1024_embed_broad.yaml new file mode 100644 index 000000000..b80dca249 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs1024_embed_broad.yaml @@ -0,0 +1,17 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024,2048) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + config: + use_embedding: true +trainer: + config: + batch_size: 1024 + num_epochs: 20 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs1024_enc_dec.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs1024_enc_dec.yaml new file mode 100644 index 000000000..4b7cd8ef4 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs1024_enc_dec.yaml @@ -0,0 +1,19 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024,2048) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + _target_: models.deepar_v2.DeepAR + config: + use_embedding: true + use_decoder: true +trainer: + config: + batch_size: 1024 + num_epochs: 20 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs128_embed_broad.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs128_embed_broad.yaml new file mode 100644 index 000000000..41619b2ad --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs128_embed_broad.yaml @@ -0,0 +1,17 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024,2048) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + config: + use_embedding: true +trainer: + config: + batch_size: 128 + num_epochs: 20 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs128_enc_dec.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs128_enc_dec.yaml new file mode 100644 index 000000000..e6168447d --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/deepar/hp_search_bs128_enc_dec.yaml @@ -0,0 +1,21 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024,2048) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + _target_: models.deepar_v2.DeepAR + config: + use_embedding: true + use_decoder: true +trainer: + config: + batch_size: 128 + num_epochs: 20 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_0.yaml new file mode 100644 index 000000000..a0f7ba4b6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_0.yaml @@ -0,0 +1,31 @@ +model: + config: + gcn_depth: 2 + dropout: 0.310003985579664 + subgraph_size: 10 + node_dim: 32 + conv_channels: 64 + residual_channels: 64 + skip_channels: 64 + end_channels: 128 + num_layers: 4 + propalpha: 0.15996611468287789 + tanhalpha: 4.654361783608888 + in_dim: 2 + use_embedding: false + include_static_data: false + +trainer: + config: + ema: false + batch_size: 64 + num_epochs: 70 + optimizer: + lr: 0.00021696215676879772 + # IDK how to do a proper subtree substitution. That's the problem for the future me + criterion: + _target_: torch.nn.L1Loss + +evaluator: + config: + batch_size: 64 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_0.yaml new file mode 100644 index 000000000..3ae2e0c02 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_0.yaml @@ -0,0 +1,24 @@ +model: + config: + gcn_depth: 2 + dropout: 0.2343982914636077 + subgraph_size: 10 + node_dim: 32 + conv_channels: 64 + residual_channels: 16 + skip_channels: 64 + end_channels: 32 + num_layers: 4 + propalpha: 0.11253629460631774 + tanhalpha: 2.1088432196246396 + in_dim: 64 + include_static_data: true + +trainer: + config: + ema: false + optimizer: + lr: 0.00019277514803525111 + # IDK how to do a proper subtree substitution. That's the problem for the future me + criterion: + _target_: torch.nn.L1Loss diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_1.yaml new file mode 100644 index 000000000..c3279973a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_1.yaml @@ -0,0 +1,24 @@ +model: + config: + conv_channels: 32 + dropout: 0.19360183884699175 + end_channels: 32 + gcn_depth: 2 + in_dim: 64 + include_static_data: true + node_dim: 64 + num_layers: 4 + propalpha: 0.17556084891019508 + residual_channels: 16 + subgraph_size: 10 + skip_channels: 32 + tanhalpha: 2.1088432196246396 + +trainer: + config: + ema: false + optimizer: + lr: 0.0002885058906688422 + # IDK how to do a proper subtree substitution. That's the problem for the future me + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_2.yaml new file mode 100644 index 000000000..113d5a476 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_2.yaml @@ -0,0 +1,25 @@ +model: + config: + conv_channels: 32 + dropout: 0.19360183884699175 + end_channels: 128 + gcn_depth: 4 + in_dim: 64 + include_static_data: true + node_dim: 40 + num_layers: 4 + propalpha: 0.03239291131895511 + residual_channels: 16 + subgraph_size: 10 + skip_channels: 64 + tanhalpha: 5.414053470339306 + +trainer: + config: + ema: true + ema_decay: 0.9140421620182122 + optimizer: + lr: 0.0002885058906688422 + # IDK how to do a proper subtree substitution. That's the problem for the future me + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_3.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_3.yaml new file mode 100644 index 000000000..84505ff92 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/best_embed_3.yaml @@ -0,0 +1,24 @@ +model: + config: + conv_channels: 64 + dropout: 0.255082136691957 + end_channels: 128 + gcn_depth: 4 + in_dim: 32 + include_static_data: true + node_dim: 64 + num_layers: 3 + propalpha: 0.1685560057680006 + residual_channels: 16 + subgraph_size: 10 + skip_channels: 32 + tanhalpha: 5.528962634102463 + +trainer: + config: + ema: false + optimizer: + lr: 0.0001702892094689578 + # IDK how to do a proper subtree substitution. That's the problem for the future me + criterion: + _target_: torch.nn.MSELoss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search.yaml new file mode 100644 index 000000000..0a1687e48 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search.yaml @@ -0,0 +1,30 @@ +hydra: + sweeper: + params: + model.config.gcn_depth: choice(1,2,3,4) + model.config.dropout: interval(0,0.4) + model.config.subgraph_size: choice(10,15,20) + model.config.node_dim: choice(32,40,64,128) + model.config.conv_channels: choice(16,32,64) + model.config.residual_channels: choice(16,32,64) + model.config.skip_channels: choice(16,32,64) + model.config.end_channels: choice(32,64,128) + model.config.num_layers: choice(2,3,4,5) + model.config.propalpha: interval(0.01, 0.2) + model.config.tanhalpha: interval(2, 6) + model.config.in_dim: choice(4, 8, 16, 24, 32, 64) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +model: + config: + use_embedding: false +trainer: + config: + batch_size: 64 + num_epochs: 50 +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search_cl.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search_cl.yaml new file mode 100644 index 000000000..fda0d459b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search_cl.yaml @@ -0,0 +1,32 @@ +hydra: + sweeper: + params: + model.config.gcn_depth: choice(2,3,4) + model.config.dropout: interval(0,0.4) + model.config.subgraph_size: choice(7,10,15) + model.config.node_dim: choice(32,40,64,128) + model.config.conv_channels: choice(16,32,64) + model.config.residual_channels: choice(16,32,64) + model.config.skip_channels: choice(32,64) + model.config.end_channels: choice(32,64) + model.config.num_layers: choice(3,4,5) + model.config.propalpha: interval(0.01, 0.2) + model.config.tanhalpha: interval(2, 6) + model.config.in_dim: choice(4, 8, 16, 24, 32, 64) + trainer.optimizer.lr: tag(log, interval(1e-5, 5e-3)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +trainer.config.cl_update: choice(300,500,1000,1500) + +model: + config: + use_embedding: false +trainer: + config: + cl_start_horizon: 1 + batch_size: 64 + num_epochs: 50 +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search_cl_embedding.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search_cl_embedding.yaml new file mode 100644 index 000000000..755cb4887 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/mtgnn/hp_search_cl_embedding.yaml @@ -0,0 +1,32 @@ +hydra: + sweeper: + params: + model.config.gcn_depth: choice(2,3,4) + model.config.dropout: interval(0,0.4) + model.config.subgraph_size: choice(7,10,15) + model.config.node_dim: choice(32,40,64,128) + model.config.conv_channels: choice(16,32,64) + model.config.residual_channels: choice(16,32,64) + model.config.skip_channels: choice(32,64) + model.config.end_channels: choice(32,64) + model.config.num_layers: choice(3,4,5) + model.config.propalpha: interval(0.01, 0.2) + model.config.tanhalpha: interval(2, 6) + model.config.in_dim: choice(4, 8, 16, 24, 32, 64) + trainer.optimizer.lr: tag(log, interval(1e-5, 5e-3)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +trainer.config.cl_update: choice(300,500,1000,1500) + +model: + config: + use_embedding: true +trainer: + config: + cl_start_horizon: 1 + batch_size: 64 + num_epochs: 50 +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nbeats/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nbeats/best_0.yaml new file mode 100644 index 000000000..d01b15675 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nbeats/best_0.yaml @@ -0,0 +1,29 @@ +model: + config: + stacks: + - type: "generic" + num_blocks: 8 + theta_dim: 8 + share_weights: False + hidden_size: 512 + - type: "generic" + num_blocks: 4 + theta_dim: 8 + share_weights: True + hidden_size: 256 + +trainer: + config: + ema: True + ema_decay: 0.9765061653846568 + batch_size: 16384 + num_epochs: 20 + + optimizer: + lr: 0.00018968004265854346 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nbeats/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nbeats/hp_search.yaml new file mode 100644 index 000000000..56a2ac0b2 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nbeats/hp_search.yaml @@ -0,0 +1,28 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(256,512,1024,2048,4096) + model.config.stacks.1.hidden_size: choice(256,512,1024,2048) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(MSE,L1) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/best_0.yaml new file mode 100644 index 000000000..608dbbed0 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/best_0.yaml @@ -0,0 +1,23 @@ +model: + config: + n_mlp_layers: 4 + hidden_size: 512 + activation: LeakyReLU + pooling_mode: AvgPool1d + + n_blocks: [1,2,2] + n_pool_kernel_size: [6,2,1] + n_freq_downsample: [6,2,1] + +trainer: + config: + ema: True + ema_decay: 0.9293868139171646 + batch_size: 16384 + num_epochs: 30 + + optimizer: + lr: 0.0004157952480153801 + + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/best_1.yaml new file mode 100644 index 000000000..ddcee5898 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/best_1.yaml @@ -0,0 +1,23 @@ +model: + config: + n_mlp_layers: 4 + hidden_size: 1024 + activation: PReLU + pooling_mode: MaxPool1d + + n_blocks: [2,2,2] + n_pool_kernel_size: [6,3,1] + n_freq_downsample: [3,3,1] + +trainer: + config: + ema: True + ema_decay: 0.9502718434543242 + batch_size: 16384 + num_epochs: 30 + + optimizer: + lr: 0.00011277779029888044 + + criterion: + _target_: torch.nn.MSELoss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/hp_search.yaml new file mode 100644 index 000000000..cee93889a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/nhits/hp_search.yaml @@ -0,0 +1,27 @@ +hydra: + sweeper: + params: + model.config.n_mlp_layers: choice(2,3,4) + model.config.hidden_size: choice(256,512,1024,2048) + model.config.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.n_blocks: choice([1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]) + model.config.n_pool_kernel_size: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + model.config.n_freq_downsample: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/tft/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/tft/best_0.yaml new file mode 100644 index 000000000..36ec13f83 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/tft/best_0.yaml @@ -0,0 +1,27 @@ +model: + config: + dropout: 0.10148515144264411 + hidden_size: 256 + n_head: 2 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +trainer: + config: + ema: True + ema_decay: 0.9896705542628265 + batch_size: 1024 + num_epochs: 20 + + optimizer: + lr: 0.0016277005911992646 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/tft/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/tft/best_1.yaml new file mode 100644 index 000000000..0eb800f90 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay/tft/best_1.yaml @@ -0,0 +1,27 @@ +model: + config: + dropout: 0.09332825894020993 + hidden_size: 192 + n_head: 4 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +trainer: + config: + ema: True + ema_decay: 0.9896705542628265 + batch_size: 1024 + num_epochs: 20 + + optimizer: + lr: 0.0025260625827691675 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/dcrnn/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/dcrnn/hp_search.yaml new file mode 100644 index 000000000..ee6ff34b6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/dcrnn/hp_search.yaml @@ -0,0 +1,20 @@ +hydra: + sweeper: + params: + model.config.max_diffusion_step: choice(1,2) + model.config.num_rnn_layers: choice(2,3) + model.config.input_dim: choice(4,8,16,32) + model.config.rnn_units: choice(32,64) + model.config.activation: choice(tanh,relu) + model.config.include_static_data: choice(true,false) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9,0.9999) + trainer.optimizer.lr: tag(log,interval(1e-5,1e-2)) + trainer/criterion: choice(L1,MSE) +trainer: + config: + batch_size: 64 + num_epochs: 30 +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/deepar/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/deepar/hp_search.yaml new file mode 100644 index 000000000..8e556512f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/deepar/hp_search.yaml @@ -0,0 +1,19 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + config: + use_embedding: true +trainer: + config: + batch_size: 128 + num_epochs: 20 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/best_0.yaml new file mode 100644 index 000000000..768cb21c0 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/best_0.yaml @@ -0,0 +1,26 @@ +model: + config: + gcn_depth: 3 + dropout: 0.2081066469771208 + subgraph_size: 20 + node_dim: 128 + conv_channels: 128 + residual_channels: 64 + skip_channels: 128 + end_channels: 32 + num_layers: 4 + propalpha: 0.06357426061559499 + tanhalpha: 2.653185128206206 + in_dim: 8 + +trainer: + config: + num_epochs: 40 + ema: false + batch_size: 64 + + optimizer: + lr: 0.0002002605445914143 + + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/best_1.yaml new file mode 100644 index 000000000..ae7c74bcf --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/best_1.yaml @@ -0,0 +1,26 @@ +model: + config: + gcn_depth: 3 + dropout: 0.12315010192393012 + subgraph_size: 20 + node_dim: 64 + conv_channels: 128 + residual_channels: 64 + skip_channels: 128 + end_channels: 32 + num_layers: 4 + propalpha: 0.09174372739797018 + tanhalpha: 2.5474477583663107 + in_dim: 8 + +trainer: + config: + num_epochs: 40 + ema: false + batch_size: 64 + + optimizer: + lr: 0.0001968907925105414 + + criterion: + _target_: torch.nn.MSELoss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/hp_search.yaml new file mode 100644 index 000000000..88cfff40b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/mtgnn/hp_search.yaml @@ -0,0 +1,23 @@ +hydra: + sweeper: + params: + model.config.gcn_depth: choice(1,2,3) + model.config.dropout: interval(0,0.4) + model.config.subgraph_size: choice(10,15,20) + model.config.node_dim: choice(32,40,64,128) + model.config.conv_channels: choice(16,32,64,128) + model.config.residual_channels: choice(16,32,64,128) + model.config.skip_channels: choice(16,32,64,128) + model.config.end_channels: choice(32,64,128) + model.config.num_layers: choice(2,3,4) + model.config.propalpha: interval(0.01, 0.2) + model.config.tanhalpha: interval(2, 6) + model.config.in_dim: choice(4, 8, 16, 24, 32, 64) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +trainer: + config: + num_epochs: 40 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/nbeats/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/nbeats/hp_search.yaml new file mode 100644 index 000000000..56a2ac0b2 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/nbeats/hp_search.yaml @@ -0,0 +1,28 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(256,512,1024,2048,4096) + model.config.stacks.1.hidden_size: choice(256,512,1024,2048) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(MSE,L1) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/nhits/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/nhits/hp_search.yaml new file mode 100644 index 000000000..3d93bb293 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/nhits/hp_search.yaml @@ -0,0 +1,48 @@ +hydra: + sweeper: + params: + model.config.stacks.0.n_blocks: choice(1,2,4,8) + model.config.stacks.1.n_blocks: choice(1,2,4,8) + model.config.stacks.2.n_blocks: choice(1,2,4,8) + + model.config.stacks.0.n_freq_downsample: choice(1,2,4,8) + model.config.stacks.1.n_freq_downsample: choice(1,2,4,8) + model.config.stacks.2.n_freq_downsample: choice(1,2,4,8) + + model.config.stacks.0.n_pool_kernel_size: choice(1,2,4) + model.config.stacks.1.n_pool_kernel_size: choice(1,2,4) + model.config.stacks.2.n_pool_kernel_size: choice(1,2,4) + + model.config.stacks.0.pooling_mode: choice(MaxPool1d,AvgPool1d) + model.config.stacks.1.pooling_mode: choice(MaxPool1d,AvgPool1d) + model.config.stacks.2.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.stacks.0.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.stacks.1.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.stacks.2.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + + model.config.stacks.0.hidden_size: choice(512,1024,2048) + model.config.stacks.1.hidden_size: choice(512,1024,2048) + model.config.stacks.2.hidden_size: choice(512,1024,2048) + + model.config.stacks.0.mlp_layers: choice(2,3,4,5) + model.config.stacks.1.mlp_layers: choice(2,3,4,5) + model.config.stacks.2.mlp_layers: choice(2,3,4,5) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + + trainer/criterion: choice(L1,MSE) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/best_0.yaml new file mode 100644 index 000000000..66309828b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/best_0.yaml @@ -0,0 +1,27 @@ +model: + config: + n_head: 1 + hidden_size: 256 + dropout: 0.3010440002313035 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 1024 + num_epochs: 15 + ema: true + ema_decay: 0.9936653681182668 + + optimizer: + lr: 0.0012094445645442153 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/best_1.yaml new file mode 100644 index 000000000..d7769e2ad --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/best_1.yaml @@ -0,0 +1,27 @@ +model: + config: + n_head: 4 + hidden_size: 192 + dropout: 0.2662993510864524 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 1024 + num_epochs: 15 + ema: true + ema_decay: 0.9529502308809386 + + optimizer: + lr: 0.001082857288295992 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/hp_search.yaml new file mode 100644 index 000000000..263f9f965 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc24/tft/hp_search.yaml @@ -0,0 +1,29 @@ +hydra: + sweeper: + params: + model.config.n_head: choice(1,2,4) + model.config.hidden_size: choice(96,128,192,256) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +model: + config: + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 1024 + num_epochs: 10 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/deepar/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/deepar/hp_search.yaml new file mode 100644 index 000000000..8e556512f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/deepar/hp_search.yaml @@ -0,0 +1,19 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + config: + use_embedding: true +trainer: + config: + batch_size: 128 + num_epochs: 20 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_0.yaml new file mode 100644 index 000000000..ffbd920af --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_0.yaml @@ -0,0 +1,31 @@ +model: + config: + stacks: + - type: "generic" + num_blocks: 8 + theta_dim: 16 + share_weights: False + hidden_size: 4096 + - type: "generic" + num_blocks: 8 + theta_dim: 16 + share_weights: False + hidden_size: 2048 + +trainer: + config: + ema: True + ema_decay: 0.9140485910165678 + batch_size: 16384 + num_epochs: 30 + criterion: + _target_: torch.nn.L1Loss + + optimizer: + lr: 0.00022462141327530337 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_1.yaml new file mode 100644 index 000000000..5c7c47bf6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_1.yaml @@ -0,0 +1,31 @@ +model: + config: + stacks: + - type: "generic" + num_blocks: 8 + theta_dim: 16 + share_weights: False + hidden_size: 4096 + - type: "generic" + num_blocks: 8 + theta_dim: 16 + share_weights: True + hidden_size: 2048 + +trainer: + config: + ema: True + ema_decay: 0.9140485910165678 + batch_size: 16384 + num_epochs: 30 + criterion: + _target_: torch.nn.L1Loss + + optimizer: + lr: 0.00022462141327530337 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_2.yaml new file mode 100644 index 000000000..f74bff13f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/best_2.yaml @@ -0,0 +1,31 @@ +model: + config: + stacks: + - type: "generic" + num_blocks: 8 + theta_dim: 8 + share_weights: False + hidden_size: 1024 + - type: "generic" + num_blocks: 4 + theta_dim: 0 + share_weights: False + hidden_size: 2048 + +trainer: + config: + ema: True + ema_decay: 0.969555169903302 + batch_size: 16384 + num_epochs: 30 + criterion: + _target_: torch.nn.MSELoss + + optimizer: + lr: 0.0008749171957806745 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/hp_search.yaml new file mode 100644 index 000000000..56a2ac0b2 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nbeats/hp_search.yaml @@ -0,0 +1,28 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(256,512,1024,2048,4096) + model.config.stacks.1.hidden_size: choice(256,512,1024,2048) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(MSE,L1) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits/hp_search.yaml new file mode 100644 index 000000000..8d5cdc645 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits/hp_search.yaml @@ -0,0 +1,27 @@ +hydra: + sweeper: + params: + model.config.n_mlp_layers: choice(2,3,4) + model.config.hidden_size: choice(256,512,1024,2048) + model.config.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.n_blocks: choice([1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]) + model.config.n_pool_kernel_size: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + model.config.n_freq_downsample: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 16384 + num_epochs: 30 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/best_0.yaml new file mode 100644 index 000000000..3026c3154 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/best_0.yaml @@ -0,0 +1,29 @@ +model: + config: + n_mlp_layers: 3 + hidden_size: 2048 + activation: PReLU + pooling_mode: MaxPool1d + + n_blocks: [1,1,2] + n_pool_kernel_size: [6,3,1] + n_freq_downsample: [6,3,1] + +trainer: + config: + ema: True + ema_decay: 0.9258194689741 + batch_size: 16384 + num_epochs: 35 + + optimizer: + lr: 0.00027516815654480837 + + criterion: + _target_: torch.nn.L1Loss + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/best_1.yaml new file mode 100644 index 000000000..7e30012ae --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/best_1.yaml @@ -0,0 +1,29 @@ +model: + config: + n_mlp_layers: 4 + hidden_size: 1024 + activation: ReLU + pooling_mode: MaxPool1d + + n_blocks: [2,2,2] + n_pool_kernel_size: [6,3,1] + n_freq_downsample: [3,3,1] + +trainer: + config: + ema: True + ema_decay: 0.941526189213896 + batch_size: 16384 + num_epochs: 35 + + optimizer: + lr: 0.000213020893268614 + + criterion: + _target_: torch.nn.MSELoss + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/hp_search.yaml new file mode 100644 index 000000000..cee93889a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/nhits_v2/hp_search.yaml @@ -0,0 +1,27 @@ +hydra: + sweeper: + params: + model.config.n_mlp_layers: choice(2,3,4) + model.config.hidden_size: choice(256,512,1024,2048) + model.config.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.n_blocks: choice([1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]) + model.config.n_pool_kernel_size: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + model.config.n_freq_downsample: choice([6,3,1],[6,2,1],[4,2,1],[3,3,1],[2,2,1]) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/tft/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/tft/hp_search.yaml new file mode 100644 index 000000000..d491b07bd --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc288/tft/hp_search.yaml @@ -0,0 +1,29 @@ +hydra: + sweeper: + params: + model.config.n_head: choice(1,2,4) + model.config.hidden_size: choice(96,128,192,256) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +model: + config: + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 512 + num_epochs: 10 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/dcrnn/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/dcrnn/best_0.yaml new file mode 100644 index 000000000..0471b0ca0 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/dcrnn/best_0.yaml @@ -0,0 +1,23 @@ +model: + config: + activation: tanh + include_static_data: false + input_dim: 4 + max_diffusion_step: 1 + num_rnn_layers: 2 + rnn_units: 64 + use_embedding: True +trainer: + config: + ema_decay: 0.9950577865524792 + ema: True + batch_size: 64 + num_epochs: 60 + optimizer: + lr: 0.001899686550575439 + criterion: + _target_: torch.nn.L1Loss + +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/dcrnn/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/dcrnn/hp_search.yaml new file mode 100644 index 000000000..034a30054 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/dcrnn/hp_search.yaml @@ -0,0 +1,22 @@ +hydra: + sweeper: + params: + model.config.num_rnn_layers: choice(2,3) + model.config.input_dim: choice(4,8,16) + model.config.rnn_units: choice(32,64) + model.config.activation: choice(tanh,relu) + model.config.include_static_data: choice(true,false) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9,0.9999) + trainer.optimizer.lr: tag(log,interval(1e-5,1e-2)) + trainer/criterion: choice(L1,MSE) +model: + config: + max_diffusion_step: 1 +trainer: + config: + batch_size: 64 + num_epochs: 30 +evaluator: + config: + batch_size: 64 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/best_0_bs1024.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/best_0_bs1024.yaml new file mode 100644 index 000000000..7ad4991e5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/best_0_bs1024.yaml @@ -0,0 +1,20 @@ +model: + config: + num_layers: 4 + use_embedding: true + hidden_size: 128 + embedding_dim: 16 + dropout: 0.16832806164488054 + +trainer: + config: + batch_size: 1024 + num_epochs: 20 + ema: true + ema_decay: 0.9643261358904808 + + optimizer: + lr: 0.0027090116333391865 + + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/best_1_bs1024.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/best_1_bs1024.yaml new file mode 100644 index 000000000..4e262b14d --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/best_1_bs1024.yaml @@ -0,0 +1,20 @@ +model: + config: + num_layers: 3 + use_embedding: true + hidden_size: 128 + embedding_dim: 32 + dropout: 0.29292913799044984 + +trainer: + config: + batch_size: 1024 + num_epochs: 20 + ema: true + ema_decay: 0.9021546955089202 + + optimizer: + lr: 0.00681494151214559 + + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/hp_search.yaml new file mode 100644 index 000000000..8e556512f --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/hp_search.yaml @@ -0,0 +1,19 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + config: + use_embedding: true +trainer: + config: + batch_size: 128 + num_epochs: 20 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/hp_search_bs1024.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/hp_search_bs1024.yaml new file mode 100644 index 000000000..533356c49 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/deepar/hp_search_bs1024.yaml @@ -0,0 +1,19 @@ +hydra: + sweeper: + params: + model.config.num_layers: choice(2,3,4,5) + model.config.hidden_size: choice(64,128,256,512,1024) + model.config.embedding_dim: choice(16,32,64,128) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-4, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) +model: + config: + use_embedding: true +trainer: + config: + batch_size: 1024 + num_epochs: 20 + criterion: + _target_: criterion.GaussianLogLikelihood \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/best_0.yaml new file mode 100644 index 000000000..316c21821 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/best_0.yaml @@ -0,0 +1,26 @@ +model: + config: + gcn_depth: 1 + dropout: 0.01757525023094229 + subgraph_size: 10 + node_dim: 128 + conv_channels: 128 + residual_channels: 128 + skip_channels: 128 + end_channels: 128 + num_layers: 2 + propalpha: 0.01950469803970105 + tanhalpha: 4.167126012423724 + in_dim: 16 + +trainer: + config: + num_epochs: 40 + ema: false + batch_size: 64 + + optimizer: + lr: 0.00029154436869926136 + + criterion: + _target_: torch.nn.L1Loss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/best_1.yaml new file mode 100644 index 000000000..59fb03359 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/best_1.yaml @@ -0,0 +1,27 @@ +model: + config: + gcn_depth: 2 + dropout: 0.016036807238775166 + subgraph_size: 10 + node_dim: 128 + conv_channels: 128 + residual_channels: 128 + skip_channels: 128 + end_channels: 128 + num_layers: 4 + propalpha: 0.06561429105075554 + tanhalpha: 2.830891112175783 + in_dim: 16 + +trainer: + config: + num_epochs: 20 + ema: true + ema_decay: 0.9524567685080492 + batch_size: 64 + + optimizer: + lr: 0.0004674225053420664 + + criterion: + _target_: torch.nn.MSELoss \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/hp_search.yaml new file mode 100644 index 000000000..88cfff40b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/mtgnn/hp_search.yaml @@ -0,0 +1,23 @@ +hydra: + sweeper: + params: + model.config.gcn_depth: choice(1,2,3) + model.config.dropout: interval(0,0.4) + model.config.subgraph_size: choice(10,15,20) + model.config.node_dim: choice(32,40,64,128) + model.config.conv_channels: choice(16,32,64,128) + model.config.residual_channels: choice(16,32,64,128) + model.config.skip_channels: choice(16,32,64,128) + model.config.end_channels: choice(32,64,128) + model.config.num_layers: choice(2,3,4) + model.config.propalpha: interval(0.01, 0.2) + model.config.tanhalpha: interval(2, 6) + model.config.in_dim: choice(4, 8, 16, 24, 32, 64) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(L1,MSE) + +trainer: + config: + num_epochs: 40 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/nbeats/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/nbeats/hp_search.yaml new file mode 100644 index 000000000..56a2ac0b2 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/nbeats/hp_search.yaml @@ -0,0 +1,28 @@ +hydra: + sweeper: + params: + model.config.stacks.0.type: choice(trend,generic) + model.config.stacks.1.type: choice(seasonality,generic) + model.config.stacks.0.num_blocks: choice(2,4,8) + model.config.stacks.1.num_blocks: choice(2,4,8) + model.config.stacks.0.theta_dim: choice(2,4,8,16) + model.config.stacks.1.theta_dim: choice(0,2,4,8,16) + model.config.stacks.0.share_weights: choice(True,False) + model.config.stacks.1.share_weights: choice(True,False) + model.config.stacks.0.hidden_size: choice(256,512,1024,2048,4096) + model.config.stacks.1.hidden_size: choice(256,512,1024,2048) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + trainer/criterion: choice(MSE,L1) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/nhits/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/nhits/hp_search.yaml new file mode 100644 index 000000000..718666e77 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/nhits/hp_search.yaml @@ -0,0 +1,46 @@ +hydra: + sweeper: + params: + model.config.stacks.0.n_blocks: choice(1,2,4,8) + model.config.stacks.1.n_blocks: choice(1,2,4,8) + model.config.stacks.2.n_blocks: choice(1,2,4,8) + + model.config.stacks.0.n_freq_downsample: choice(1,2,4,8) + model.config.stacks.1.n_freq_downsample: choice(1,2,4,8) + model.config.stacks.2.n_freq_downsample: choice(1,2,4,8) + + model.config.stacks.0.n_pool_kernel_size: choice(1,2,4) + model.config.stacks.1.n_pool_kernel_size: choice(1,2,4) + model.config.stacks.2.n_pool_kernel_size: choice(1,2,4) + + model.config.stacks.0.pooling_mode: choice(MaxPool1d,AvgPool1d) + model.config.stacks.1.pooling_mode: choice(MaxPool1d,AvgPool1d) + model.config.stacks.2.pooling_mode: choice(MaxPool1d,AvgPool1d) + + model.config.stacks.0.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.stacks.1.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + model.config.stacks.2.activation: choice(ReLU,Softplus,Tanh,SELU,LeakyReLU,PReLU,Sigmoid) + + model.config.stacks.0.hidden_size: choice(512,1024,2048) + model.config.stacks.1.hidden_size: choice(512,1024,2048) + model.config.stacks.2.hidden_size: choice(512,1024,2048) + + model.config.stacks.0.mlp_layers: choice(2,3,4,5) + model.config.stacks.1.mlp_layers: choice(2,3,4,5) + model.config.stacks.2.mlp_layers: choice(2,3,4,5) + + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + + +trainer: + config: + batch_size: 16384 + num_epochs: 30 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_0.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_0.yaml new file mode 100644 index 000000000..2ec8c61f3 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_0.yaml @@ -0,0 +1,27 @@ +model: + config: + n_head: 4 + hidden_size: 96 + dropout: 0.06882608768793705 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 1024 + num_epochs: 15 + ema: true + ema_decay: 0.9964063331909582 + + optimizer: + lr: 0.0033915804555236305 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_1.yaml new file mode 100644 index 000000000..1da5cc9b6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_1.yaml @@ -0,0 +1,27 @@ +model: + config: + n_head: 4 + hidden_size: 96 + dropout: 0.25725939394508646 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 1024 + num_epochs: 10 + ema: true + ema_decay: 0.988802692015398 + + optimizer: + lr: 0.003381676106644342 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_2.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_2.yaml new file mode 100644 index 000000000..e8bc3c191 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/best_2.yaml @@ -0,0 +1,27 @@ +model: + config: + n_head: 4 + hidden_size: 192 + dropout: 0.07450385624465683 + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 1024 + num_epochs: 10 + ema: true + ema_decay: 0.996038853840747 + + optimizer: + lr: 0.001851534782143349 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/hp_search.yaml new file mode 100644 index 000000000..263f9f965 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_enc48/tft/hp_search.yaml @@ -0,0 +1,29 @@ +hydra: + sweeper: + params: + model.config.n_head: choice(1,2,4) + model.config.hidden_size: choice(96,128,192,256) + model.config.dropout: interval(0,0.5) + trainer.optimizer.lr: tag(log, interval(1e-5, 1e-2)) + trainer.config.ema: choice(true, false) + +trainer.config.ema_decay: interval(0.9, 0.9999) + +model: + config: + quantiles: [0.1, 0.5, 0.9] + output_selector: 1 + +dataset: + config: + train_samples: 1000000 + MultiID: False + binarized: True + +trainer: + config: + batch_size: 1024 + num_epochs: 10 + + criterion: + _target_: criterion.QuantileLoss + quantiles: [0.1, 0.5, 0.9] \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_xgb/xgboost/hp_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_xgb/xgboost/hp_search.yaml new file mode 100644 index 000000000..216b4e5b7 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/overrides/pems_bay_xgb/xgboost/hp_search.yaml @@ -0,0 +1,10 @@ +hydra: + sweeper: + params: + model.config.max_depth: choice(4,5,6,7,8) + model.config.learning_rate: interval(1e-4, 1e-2) + model.config.subsample: interval(0.7,1) + model.config.colsample_bytree: interval(0.8,1) + model.config.n_rounds: choice(500, 1000, 2000, 3000, 4000, 5000, 7000) + model.config.objective: choice(reg:squarederror, reg:absolutederror) + +model.config.min_child_weight: choice(1,2,4,8,16,32) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/preproc_config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/preproc_config.yaml index bde934111..a01c50eeb 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/preproc_config.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/preproc_config.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 defaults: - dataset@_here_: ??? _target_: data.data_utils.Preprocessor diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_config.yaml index e5f601e53..c6816a1d3 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_config.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_config.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 # # The order in this list matters a lot! An element in this list can only be modified by a subsequent one! defaults: @@ -19,7 +6,9 @@ defaults: - dataset: electricity - evaluator: ${if:${cmp:${oc.select:trainer, ctltrainer}, xgbtrainer}, xgbevaluator, ${if:${cmp:${oc.select:trainer, ctltrainer}, stattrainer}, statevaluator, ctlevaluator}} - optional model_dataset@_global_: ${model}_${dataset} + - logger - train_derived_fields + - optional overrides@_global_: # Empty by default - _self_ seed: 1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_derived_fields.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_derived_fields.yaml index a28c54fe7..981bb691e 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_derived_fields.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/train_derived_fields.yaml @@ -1,24 +1,8 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 # @package _global_ dataset: config: - # The line below is equivalent to python's `model.config.get(model_type, 'default') == 'graph' and dataset.config.get('graph', False)` - # For more info on resolvers see: https://omegaconf.readthedocs.io/en/2.1_branch/custom_resolvers.html - # We cannot reuse `graph: ...` because during resolution it queries dataset.config.graph which causes infinite recursion construct_graph: ${and:${cmp:${oc.select:model.config.model_type,default},graph},${oc.select:dataset.config.graph,false}} xgb: ${cont.lower:${oc.select:trainer._target_, ctltrainer}, xgbtrainer} stat: ${cont.lower:${oc.select:trainer._target_, ctltrainer}, stattrainer} @@ -29,6 +13,7 @@ trainer: config: encoder_length: ${dataset.config.encoder_length} example_length: ${dataset.config.example_length} + input_length: ${dataset.config.input_length} model_type: ${oc.select:model.config.model_type,default} evaluator: @@ -38,8 +23,7 @@ evaluator: encoder_length: ${dataset.config.encoder_length} output_selector: ${oc.select:model.config.output_selector,0} model_type: ${oc.select:model.config.model_type,default} - - + num_workers: ${oc.select:trainer.config.num_workers} # We want to inform model about shape of the data model: @@ -47,11 +31,11 @@ model: device: ${trainer.config.device} encoder_length: ${dataset.config.encoder_length} example_length: ${dataset.config.example_length} - num_ts: ${dataset.config.time_series_count} + input_length: ${dataset.config.input_length} temporal_known_continuous_inp_size: ${len:${feature.selector:${dataset.config.features}, KNOWN, CONTINUOUS}} temporal_observed_continuous_inp_size: ${if:${dataset.config.MultiID},${add:${len:${feature.selector:${dataset.config.features}, OBSERVED, CONTINUOUS}},${dataset.config.time_series_count}},${len:${feature.selector:${dataset.config.features}, OBSERVED, CONTINUOUS}}} static_continuous_inp_size: ${len:${feature.selector:${dataset.config.features}, STATIC, CONTINUOUS}} - temporal_target_size: ${len:${feature.selector:${dataset.config.features}, TARGET, CONTINUOUS}} # XXX: we currently support only continuous targets + temporal_target_size: ${len:${feature.selector:${dataset.config.features}, TARGET, CONTINUOUS}} static_categorical_inp_lens: ${feature.cardinalities:${feature.selector:${dataset.config.features}, STATIC, CATEGORICAL}} temporal_known_categorical_inp_lens: ${feature.cardinalities:${feature.selector:${dataset.config.features}, KNOWN, CATEGORICAL}} temporal_observed_categorical_inp_lens: ${feature.cardinalities:${feature.selector:${dataset.config.features}, OBSERVED, CATEGORICAL}} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/early_stopping.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/early_stopping.yaml index d184227d0..db7b0206a 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/early_stopping.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/early_stopping.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: callbacks.ctl_callbacks.EarlyStopping metric: val_loss min_delta: 0 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/logging.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/logging.yaml index 5441e4b2a..8d0192a8f 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/logging.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/logging.yaml @@ -1,15 +1,2 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: callbacks.ctl_callbacks.LoggingCallback diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_best_checkpoint.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_best_checkpoint.yaml index cf6e1cda1..409143d14 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_best_checkpoint.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_best_checkpoint.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: callbacks.ctl_callbacks.SaveBestCheckpoint metric: val_loss diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_checkpoint.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_checkpoint.yaml index 0052a0484..24acdb803 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_checkpoint.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/save_checkpoint.yaml @@ -1,15 +1,2 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: callbacks.ctl_callbacks.SaveCheckpoint diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/throughput_benchmark.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/throughput_benchmark.yaml index 392ae00d5..e5eb6e74e 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/throughput_benchmark.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/callbacks/throughput_benchmark.yaml @@ -1,16 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: callbacks.ctl_callbacks.ThroughputBenchmark warmup_epochs: 0 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/standard.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/standard.yaml index a435b790d..dde1c7dcb 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/standard.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/callbacks/standard.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 early_stopping: _target_: callbacks.ctl_callbacks.EarlyStopping metric: val_loss diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/GLL.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/GLL.yaml index e98ed7ae7..4eafd5a96 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/GLL.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/GLL.yaml @@ -1,15 +1,2 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: criterion.GaussianLogLikelihood diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/L1.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/L1.yaml index 7294d1f42..9581eb631 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/L1.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/L1.yaml @@ -1,15 +1,2 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.nn.L1Loss diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/MSE.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/MSE.yaml index 81bac25bc..ac30927c4 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/MSE.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/MSE.yaml @@ -1,15 +1,2 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.nn.MSELoss diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/overrides/quantile_overrides.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/overrides/quantile_overrides.yaml index 56baea05c..a05b48c6b 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/overrides/quantile_overrides.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/overrides/quantile_overrides.yaml @@ -1,17 +1,3 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - trainer: criterion: quantiles: [0.1, 0.5, 0.9] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/quantile.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/quantile.yaml index 9fe5d7a95..33f57a2bb 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/quantile.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/quantile.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 defaults: - overrides@_global_: quantile_overrides _target_: criterion.QuantileLoss diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/tweedie.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/tweedie.yaml new file mode 100644 index 000000000..98ede42c1 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/criterion/tweedie.yaml @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 +_target_: criterion.TweedieLoss +p: 1.1 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/ctltrainer.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/ctltrainer.yaml index 377b3e810..ed04f1dcd 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/ctltrainer.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/ctltrainer.yaml @@ -1,22 +1,10 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: training.trainer.CTLTrainer defaults: - callbacks: standard - criterion: MSE - optimizer: Adam + - optional scheduler: None config: device: cuda @@ -28,3 +16,4 @@ config: ema: False log_interval: 25 logfile_name: log.json + mlflow_store: '' diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/ASGD.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/ASGD.yaml index 927f16902..c41d2b787 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/ASGD.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/ASGD.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.ASGD lr: 0.01 lambd: 0.0001 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adadelta.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adadelta.yaml index b01af6909..851e71b0e 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adadelta.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adadelta.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.Adadelta lr: 1.0 rho: 0.9 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adagrad.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adagrad.yaml index 21b804f3d..24e7b7b09 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adagrad.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adagrad.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.Adagrad lr: 0.01 lr_decay: 0.0 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adam.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adam.yaml index de508ea14..8713923c7 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adam.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adam.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: apex.optimizers.FusedAdam lr: 0.001 betas: [0.9, 0.999] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/AdamW.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/AdamW.yaml index b9f81a3ec..f552e37b1 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/AdamW.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/AdamW.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.AdamW lr: 0.001 betas: [0.9, 0.999] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adamax.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adamax.yaml index 423140e5d..97d006464 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adamax.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Adamax.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.Adamax lr: 0.002 betas: [0.9, 0.999] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/LBFGS.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/LBFGS.yaml index 8a9f25d7c..51a6a4f70 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/LBFGS.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/LBFGS.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.LBFGS lr: 1.0 max_iter: 20 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/RMSprop.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/RMSprop.yaml index 28ac48c75..b9f75e7b7 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/RMSprop.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/RMSprop.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.RMSprop lr: 0.01 alpha: 0.99 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Rprop.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Rprop.yaml index e5a6bbeec..72fa603ec 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Rprop.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/Rprop.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.Rprop lr: 0.01 etas: [0.5, 1.2] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SGD.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SGD.yaml index 56193887d..7dde636e6 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SGD.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SGD.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.SGD lr: 0.01 momentum: 0.0 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SparseAdam.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SparseAdam.yaml index 33f42b714..5d1d11a91 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SparseAdam.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/SparseAdam.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.SparseAdam lr: 0.001 betas: [0.9, 0.999] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/TorchAdam.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/TorchAdam.yaml index 489717d25..db8fd3503 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/TorchAdam.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/optimizer/TorchAdam.yaml @@ -1,17 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: torch.optim.Adam lr: 0.001 betas: [0.9, 0.999] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/StepLR.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/StepLR.yaml deleted file mode 100644 index 9dedf3e9d..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/StepLR.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -target: torch.optim.lr_scheduler.StepLR -gamma: .5 -step_size: 1 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/multistep.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/multistep.yaml new file mode 100644 index 000000000..54b65f418 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/multistep.yaml @@ -0,0 +1,3 @@ +target: torch.optim.lr_scheduler.MultiStepLR +milestones: [20, 30, 40, 50] +gamma: 0.1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/step.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/step.yaml new file mode 100644 index 000000000..2a64ae996 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/scheduler/step.yaml @@ -0,0 +1,3 @@ +target: torch.optim.lr_scheduler.StepLR +gamma: .5 +step_size: 1 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/stattrainer.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/stattrainer.yaml index b930dc641..d53a9efcd 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/stattrainer.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/stattrainer.yaml @@ -1,18 +1,8 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: training.trainer.StatTrainer config: + log_interval: 25 + logfile_name: log.json + mlflow_store: '' device: cpu diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/xgbtrainer.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/xgbtrainer.yaml index 50c609f7c..b91056af6 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/xgbtrainer.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/trainer/xgbtrainer.yaml @@ -1,20 +1,8 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 _target_: training.trainer.XGBTrainer defaults: - callbacks: standard config: device: cuda + log_interval: 100 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/criterion.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/criterion.py index 20d2793ee..19281261d 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/criterion.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/criterion.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 import torch import torch.nn as nn import torch.nn.functional as F @@ -33,6 +34,13 @@ def __init__(self, criterion, cl_start_horizon=None, cl_update=None): self.cl_counter = 0 def forward(self, preds, labels, weights=None, **kwargs): + """ + preds: Tensor of size BS x time x num_targets x num_estimators + or BS x time x num_ids x num_targets x num_estimators in case of MultiTarget dataset + labels: Tensor of size BS x time x num_targets + or BS x time x num_ids x num_targets case of MultiTarget dataset + weights: Tensor of the same shape as labels + """ disallowed_kwargs = set(kwargs.keys()) - self.allowed_arguments if disallowed_kwargs: raise TypeError(f'Invalid keyword arguments {disallowed_kwargs} for {type(self.criterion)}') @@ -47,8 +55,6 @@ def forward(self, preds, labels, weights=None, **kwargs): self.curr_horizon += 1 self.cl_counter += 1 - # We expect preds to be shaped batch_size x time x num_estimators in 3D case - # or batch_size x time x num_targets x num_estimators in 4D case if len(preds.shape) == 4 and len(labels.shape) == 3: labels = labels.unsqueeze(-1) if weights is not None: @@ -56,7 +62,6 @@ def forward(self, preds, labels, weights=None, **kwargs): loss = self.criterion(preds, labels, **kwargs) if weights is not None and weights.numel(): - # Presence of weights is detected on config level. Loss is reduced accordingly loss *= weights loss = loss.view(-1, *loss.shape[2:]).mean(0) @@ -69,7 +74,7 @@ def __init__(self, quantiles, reduction='mean'): self.quantiles = quantiles self.reduce = reduction == 'mean' - def forward(self, predictions, targets,weights=None): + def forward(self, predictions, targets): if not hasattr(self, 'q'): self.register_buffer('q', predictions.new(self.quantiles)) diff = predictions - targets @@ -88,12 +93,35 @@ def forward(self, predictions, targets): # Targets with shape [BS, window, 1] mu = predictions[..., 0:1] - sigma = predictions[..., 1:2] - distribution = torch.distributions.normal.Normal(mu, sigma) - likelihood = distribution.log_prob(targets) - likelihood = -likelihood.view(targets.shape[0], targets.shape[1]) - loss = torch.unsqueeze(likelihood,-1) + sig = predictions[..., 1:2] + var = sig ** 2 + loss = -((targets - mu) ** 2) / (2 * var) - sig.log() + if self.reduce: + loss = loss.mean(0) + return -loss + + +class TweedieLoss(nn.Module): + def __init__(self, reduction='mean', p=1.1): + super().__init__() + assert 1.0 < p < 2.0, 'Variance power should be in 1..2 interval' + self.reduce = reduction == 'mean' + self.register_buffer('variance_power', torch.tensor(p)) + + def forward(self, predictions, targets): + # Inputs with shape [BS, window, 1] + # Targets with shape [BS, window, 1] + + rho = self.get_buffer('variance_power').to(device=predictions.device) + predictions[predictions < 1e-10] = 1e-10 + log_preds = torch.log(predictions) + likelihood = -targets * torch.exp(log_preds * (1 - rho)) / (1 - rho) + torch.exp(log_preds * (2 - rho)) / (2 - rho) + + likelihood = likelihood.view(targets.shape[0], targets.shape[1]) + + loss = torch.unsqueeze(likelihood, -1) if self.reduce: loss = loss.mean(0) return loss + diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/data_utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/data_utils.py index 964b10bf9..ee365fe3c 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/data_utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/data_utils.py @@ -1,4 +1,4 @@ -# Copyright 2021-2022 NVIDIA Corporation +# Copyright 2021-2024 NVIDIA Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ from omegaconf.listconfig import ListConfig from sklearn.impute import SimpleImputer from sklearn.preprocessing import FunctionTransformer -from typing import Union +from typing import Union, List, Dict class DataTypes(enum.IntEnum): @@ -52,7 +52,7 @@ class DataTypes(enum.IntEnum): DTYPE_MAP = { DataTypes.CONTINUOUS: np.float32, DataTypes.CATEGORICAL: np.int64, - DataTypes.DATE: np.datetime64, + DataTypes.DATE: 'datetime64[ns]', #This can be a string because this is meant to be used as an argument to ndarray.astype DataTypes.STR: str, } @@ -95,39 +95,54 @@ def __str__(self): def __repr__(self): return str(self) +# Since Python 3.7, dictionaries are ordered by default and maintain their insertion order +FEAT_NAME_MAP = { + "s_cat": (InputTypes.STATIC, DataTypes.CATEGORICAL), + "s_cont": (InputTypes.STATIC, DataTypes.CONTINUOUS), + "k_cat": (InputTypes.KNOWN, DataTypes.CATEGORICAL), + "k_cont": (InputTypes.KNOWN, DataTypes.CONTINUOUS), + "o_cat": (InputTypes.OBSERVED, DataTypes.CATEGORICAL), + "o_cont": (InputTypes.OBSERVED, DataTypes.CONTINUOUS), + "target": (InputTypes.TARGET, DataTypes.CONTINUOUS), + "weight": (InputTypes.WEIGHT, DataTypes.CONTINUOUS), + "sample_weight": (InputTypes.SAMPLE_WEIGHT, DataTypes.CONTINUOUS), + "id": (InputTypes.ID, DataTypes.CATEGORICAL), + "timestamp": (InputTypes.TIME, DataTypes.CATEGORICAL) # During preprocessing we cast all time data to int +} -FEAT_ORDER = [ - (InputTypes.STATIC, DataTypes.CATEGORICAL), - (InputTypes.STATIC, DataTypes.CONTINUOUS), - (InputTypes.KNOWN, DataTypes.CATEGORICAL), - (InputTypes.KNOWN, DataTypes.CONTINUOUS), - (InputTypes.OBSERVED, DataTypes.CATEGORICAL), - (InputTypes.OBSERVED, DataTypes.CONTINUOUS), - (InputTypes.TARGET, DataTypes.CONTINUOUS), - (InputTypes.WEIGHT, DataTypes.CONTINUOUS), - (InputTypes.SAMPLE_WEIGHT, DataTypes.CONTINUOUS), - (InputTypes.ID, DataTypes.CATEGORICAL), -] -FEAT_NAMES = ["s_cat", "s_cont", "k_cat", "k_cont", "o_cat", "o_cont", "target", "weight", "sample_weight", "id"] def group_ids(df, features): - col_names = ["_id_"] + [ - x.name - for x in features - if x.feature_embed_type != DataTypes.STR - and x.feature_type != InputTypes.TIME - and x.feature_type != InputTypes.ID + sizes = df['_id_'].value_counts(dropna=False, sort=False).sort_index() + #sizes = sizes[sizes >= example_length] + #valid_ids = set(sizes.index) + sizes = sizes.values + + feature_col_map = {k: [ + f.name for f in features + if (f.feature_type, f.feature_embed_type) == v ] - grouped = [x[1][col_names].values.astype(np.float32).view(dtype=np.int32) for x in df.groupby("_id_")] - return grouped + for k, v in FEAT_NAME_MAP.items() + } + + # These 2 columns are defined at preprocessing stage. We should redesign it so it wouldn't be necessary + feature_col_map['id'] = ['_id_'] + feature_col_map['timestamp'] = ['_timestamp_'] + + # df is sorted by _id_ and time feature, so there is no need to group df + grouped = [ + df.loc[:, feature_col_map[feat]].values.astype(DTYPE_MAP[dtype]) + for feat, (_, dtype) in FEAT_NAME_MAP.items() + ] + return grouped, sizes + def translate_features(features, preproc=False): all_features = [FeatureSpec(feature) for feature in features] if preproc: return all_features - return [FeatureSpec({"name": "_id_", "feature_type": "ID", "feature_embed_type": "CATEGORICAL"})] + [ - feature for feature in all_features if feature.feature_type != InputTypes.ID - ] + return [FeatureSpec({"name": "_id_", "feature_type": "ID", "feature_embed_type": "CATEGORICAL"}), + FeatureSpec({"name": "_timestamp_", "feature_type": "TIME", "feature_embed_type": "CATEGORICAL"})] + \ + [feature for feature in all_features if feature.feature_type not in [InputTypes.ID, InputTypes.TIME]] def map_dt(dt): @@ -136,7 +151,11 @@ def map_dt(dt): elif isinstance(dt, ListConfig): dt = datetime.datetime(*dt) elif isinstance(dt, str): - dt = datetime.datetime.strptime(dt, "%Y-%m-%d") + try: + dt = datetime.datetime.strptime(dt, "%Y-%m-%d") + except ValueError: + dt = datetime.datetime.strptime(dt, '%Y-%m-%d %H:%M:%S') + return dt @@ -163,6 +182,10 @@ def map_scalers(features): return mapping +def get_alignment_compliment_bytes(size, dtype): + # return two's compliment for the dtype, so new array starts on multiple of dtype + return (~size + 1) & (dtype.alignment - 1) + class Log1pScaler(FunctionTransformer): @staticmethod def _inverse(x): @@ -183,10 +206,13 @@ def __init__(self, target_features, input_continuous, scale_per_id): self.target_scalers = {} def fit(self, df): + if self.scale_per_id: + grouped_df = df.groupby("_id_") + for k, v in self.continuous_mapping.items(): self.continuous_scalers[k] = {} if self.scale_per_id: - for identifier, sliced in df.groupby("_id_"): + for identifier, sliced in grouped_df: scaler = hydra.utils.instantiate(k).fit(sliced[v]) self.continuous_scalers[k][identifier] = scaler @@ -197,7 +223,7 @@ def fit(self, df): for k, v in self.target_mapping.items(): self.target_scalers[k] = {} if self.scale_per_id: - for identifier, sliced in df.groupby("_id_"): + for identifier, sliced in grouped_df: scaler = hydra.utils.instantiate(k).fit(sliced[v]) self.target_scalers[k][identifier] = scaler @@ -220,31 +246,34 @@ def transform(self, df): else: df = self.apply_scalers(df, name="") return df - + def inverse_transform_targets(self, values, ids=None): - # TODO: Assuming single targets for now. This has to be adapted to muti-target - if len(self.target_scalers) > 0: + if len(self.target_scalers) <= 0: + return values + scalers = list(self.target_scalers.values())[0] - shape = values.shape - scalers = list(self.target_scalers.values())[0] - if self.scale_per_id: - assert ids is not None - flat_values = values.flatten() - flat_ids = np.repeat(ids, values.shape[1]) - df = pd.DataFrame({"id": flat_ids, "value": flat_values}) - df_list = [] - for identifier, sliced in df.groupby("id"): - df_list.append(np.stack( - [scalers[identifier].inverse_transform(sliced["value"].values.reshape(-1, 1)).flatten(), - sliced.index.values], axis=-1)) - tmp = np.concatenate(df_list) - tmp = tmp[tmp[:, -1].argsort()] - return tmp[:, 0].reshape(shape) - else: - flat_values = values.reshape(-1, 1) - flat_values = scalers[""].inverse_transform(flat_values) - return flat_values.reshape(shape) - return values + # Assumption in 4D case: ids: NxI, values: NxTxIxH + if self.scale_per_id: + assert ids is not None + # Move time id to the second dim + if len(values.shape) == 4: + values = values.transpose(0,2,1,3) + + uids = np.unique(ids) + inversed = np.zeros_like(values) + for i in uids: + idx = ids == i + x = values[idx] + x = scalers[i].inverse_transform(x) + inversed[idx] = x + + if len(values.shape) == 4: + inversed = inversed.transpose(0,2,1,3) + return inversed + else: + flat_values = values.reshape(-1, 1) + flat_values = scalers[""].inverse_transform(flat_values) + return flat_values.reshape(values.shape) class Preprocessor: def __init__(self, config): @@ -255,6 +284,8 @@ def __init__(self, config): self.dest_path = self.config.dest_path self.source_path = self.config.source_path self.preprocessor_state = {} + self.scaler = None + self.alt_scaler = None def _get_feature_splits(self): splits = {} @@ -313,8 +344,14 @@ def _map_categoricals(self, df): df[categorical.name] = cat_feature.cat.codes + 1 self.preprocessor_state["categorical_mappings"] = input_categorical_map_dict + def _map_time_col(self, df): + time_feat = self.feat_splits["time_feature"].name + df['_timestamp_'] = df[time_feat] + self.preprocessor_state['timestamp_embed_type'] = self.feat_splits["time_feature"].feature_embed_type + def _get_dataset_splits(self, df): print("Splitting datasets") + time_feat = self.feat_splits['time_feature'] if hasattr(self.config, "valid_boundary") and self.config.valid_boundary is not None: forecast_len = self.config.example_length - self.config.encoder_length # The valid split is shifted from the train split by number of the forecast steps to the future. @@ -323,69 +360,103 @@ def _get_dataset_splits(self, df): grouped = df.groupby('_id_') - train_mask = grouped[self.config.time_ids].apply(lambda dates: dates < valid_boundary) + train_mask = grouped[time_feat.name].apply(lambda dates: dates < valid_boundary) train = df[train_mask] print('Calculated train.') train_sizes = train.groupby('_id_').size() + exclude_name = train_sizes < self.config.example_length - valid_indexes = grouped[self.config.time_ids].apply( + valid_indexes = grouped[time_feat.name].apply( lambda dates: dates.iloc[(train_sizes[dates.name] - self.config.encoder_length): (train_sizes[dates.name] + forecast_len)].index - if dates.name in train_sizes else pd.Series() + if dates.name in train_sizes and not exclude_name[dates.name] else pd.Series() ) valid = df.loc[np.concatenate(valid_indexes)] print('Calculated valid.') - test_indexes = grouped[self.config.time_ids].apply( + test_indexes = grouped[time_feat.name].apply( lambda dates: dates.iloc[(train_sizes[dates.name] - self.config.encoder_length + forecast_len): (train_sizes[dates.name] + 2 * forecast_len)].index - if dates.name in train_sizes else pd.Series() + if dates.name in train_sizes and not exclude_name[dates.name] else pd.Series() ) test = df.loc[np.concatenate(test_indexes)] print('Calculated test.') - elif df.dtypes[self.config.time_ids] not in [np.float64, np.int]: - index = df[self.config.time_ids] + elif time_feat.feature_embed_type == DataTypes.DATE: + index = df[time_feat.name] train = df.loc[(index >= map_dt(self.config.train_range[0])) & (index < map_dt(self.config.train_range[1]))] valid = df.loc[(index >= map_dt(self.config.valid_range[0])) & (index < map_dt(self.config.valid_range[1]))] test = df.loc[(index >= map_dt(self.config.test_range[0])) & (index < map_dt(self.config.test_range[1]))] else: - index = df[self.config.time_ids] + index = df[time_feat.name] + train = df.loc[(index >= self.config.train_range[0]) & (index < self.config.train_range[1])] valid = df.loc[(index >= self.config.valid_range[0]) & (index < self.config.valid_range[1])] test = df.loc[(index >= self.config.test_range[0]) & (index < self.config.test_range[1])] - train = train[(train.groupby('_id_').size()[train['_id_']] > self.config.encoder_length).values] - valid = valid[(valid.groupby('_id_').size()[valid['_id_']] > self.config.encoder_length).values] - test = test[(test.groupby('_id_').size()[test['_id_']] > self.config.encoder_length).values] + train = train[(train.groupby('_id_').size()[train['_id_']] >= self.config.example_length).values] + valid = valid[(valid.groupby('_id_').size()[valid['_id_']] >= self.config.example_length).values] + test = test[(test.groupby('_id_').size()[test['_id_']] >= self.config.example_length).values] return train, valid, test - - def _recombine_datasets(self, train, valid, test): + + def _get_dataset_splits_stat(self, df): + print("Splitting stats datasets") + time_feat = self.feat_splits['time_feature'] + forecast_len = self.config.example_length - self.config.encoder_length if hasattr(self.config, "valid_boundary") and self.config.valid_boundary is not None: - forecast_len = self.config.example_length - self.config.encoder_length # The valid split is shifted from the train split by number of the forecast steps to the future. # The test split is shifted by the number of the forecast steps from the valid split - train_temp = [] - valid_temp = [] - for g0, g1 in zip(train.groupby("_id_"), valid.groupby("_id_")): - _train = g0[1].iloc[: -self.config.encoder_length] - _valid = g1[1].iloc[:forecast_len] - train_temp.append(_train) - valid_temp.append(_valid) - train = pd.concat(train_temp, axis=0) - valid = pd.concat(valid_temp, axis=0) - elif train.dtypes[self.config.time_ids] not in [np.float64, np.int]: - - train = train[train[self.config.time_ids] < map_dt(self.config.valid_range[0])] - valid = valid[valid[self.config.time_ids] < map_dt(self.config.test_range[0])] + valid_boundary = map_dt(self.config.valid_boundary) + + data_sizes = df['_id_'].value_counts(dropna=False, sort=False) + train_sizes = df.loc[df[time_feat.name] < valid_boundary, '_id_'].value_counts(dropna=False, sort=False) + exclude_name = train_sizes < self.config.example_length + + grouped = df.groupby('_id_') + + train_stat_index = grouped[time_feat.name].apply( + lambda dates: dates.iloc[:train_sizes[dates.name] + forecast_len].index + if dates.name in train_sizes and not exclude_name[dates.name] and train_sizes[dates.name] + 2*forecast_len <= data_sizes[dates.name] else pd.Series() + ) + train_stat = df.loc[np.concatenate(train_stat_index)] + print('Calculated stat train.') + test_stat_indexes = grouped[time_feat.name].apply( + lambda dates: dates.iloc[train_sizes[dates.name] + forecast_len: + train_sizes[dates.name] + 2*forecast_len].index + if dates.name in train_sizes and not exclude_name[dates.name] and train_sizes[dates.name] + 2*forecast_len <= data_sizes[dates.name] else pd.Series() + ) + test_stat = df.loc[np.concatenate(test_stat_indexes)] + print('Calculated stat test.') + return train_stat, test_stat + elif time_feat.feature_embed_type == DataTypes.DATE: + index = df[time_feat.name] + + delta = (index[1] - index[0]) * self.config.encoder_length + + train_stat = df.loc[(index >= map_dt(self.config.train_range[0])) & (index < map_dt(self.config.test_range[0]) + delta)] + test_stat = df.loc[(index >= map_dt(self.config.test_range[0]) + delta) & (index < map_dt(self.config.test_range[1]))] else: - train = train[train[self.config.time_ids] < self.config.valid_range[0]] - valid = valid[valid[self.config.time_ids] < self.config.test_range[0]] - return pd.concat((train, valid, test)) + index = df[time_feat.name] + train_stat = df.loc[(index >= self.config.train_range[0]) & (index < self.config.test_range[0] + self.config.encoder_length)] + test_stat = df.loc[(index >= self.config.test_range[0] + self.config.encoder_length) & (index < self.config.test_range[1])] + + train_sizes = train_stat['_id_'].value_counts(dropna=False, sort=False) + test_sizes = test_stat['_id_'].value_counts(dropna=False, sort=False) + + # filter short examples + train_sizes = train_sizes[train_sizes >= self.config.example_length] + test_sizes = test_sizes[test_sizes >= forecast_len] + + # cross check sets to ensure that train and test contain the same _id_'s + train_sizes = train_sizes[train_sizes.index.isin(test_sizes.index)] + test_sizes = test_sizes[test_sizes.index.isin(train_sizes.index)] - def _drop_unseen_categoricals(self, train, valid, test, drop_unseen=True): - # TODO: Handle this for inference preprocess function + train_stat[train_stat['_id_'].isin(train_sizes.index)] + test_stat[test_stat['_id_'].isin(test_sizes.index)] + return train_stat, test_stat + + def _drop_unseen_categoricals(self, train, valid=None, test=None, drop_unseen=True): if self.config.get("drop_unseen", False): print("Dropping unseen categoricals") if not drop_unseen: @@ -396,44 +467,69 @@ def _drop_unseen_categoricals(self, train, valid, test, drop_unseen=True): else: arriter = [cat.name for cat in self.feat_splits["input_categoricals"]] + ["_id_"] - if train is not None: + if train is not None and (valid is not None or test is not None): for categorical in arriter: seen_values = train[categorical].unique() - valid = valid[valid[categorical].isin(seen_values)] - test = test[test[categorical].isin(seen_values)] + if valid is not None: + valid = valid[valid[categorical].isin(seen_values)] + if test is not None: + test = test[test[categorical].isin(seen_values)] return train, valid, test - def fit_scalers(self, df): + def fit_scalers(self, df, alt_scaler=False): print("Calculating scalers") - self.scaler = CompositeScaler( + scaler = CompositeScaler( self.feat_splits["target_features"], self.feat_splits["input_continuous"], scale_per_id=self.config.get('scale_per_id', False) ) - self.scaler.fit(df) - self.preprocessor_state["scalers"] = self.scaler + scaler.fit(df) + if alt_scaler: + self.alt_scaler = scaler + self.preprocessor_state["alt_scalers"] = scaler + else: + self.scaler = scaler + self.preprocessor_state["scalers"] = scaler - def apply_scalers(self, df): + def apply_scalers(self, df, alt_scaler=False): print("Applying scalers") - return self.preprocessor_state["scalers"].transform(df) + return self.preprocessor_state["alt_scalers" if alt_scaler else "scalers"].transform(df) - def save_datasets(self, train, valid, test): + def save_datasets(self, train, valid, test, train_stat, test_stat): print(F"Saving processed data at {self.dest_path}") os.makedirs(self.dest_path, exist_ok=True) train.to_csv(os.path.join(self.dest_path, "train.csv")) valid.to_csv(os.path.join(self.dest_path, "valid.csv")) test.to_csv(os.path.join(self.dest_path, "test.csv")) - self._recombine_datasets(train, valid, test).to_csv(os.path.join(self.dest_path, "full.csv")) + train_stat.to_csv(os.path.join(self.dest_path, "train_stat.csv")) + test_stat.to_csv(os.path.join(self.dest_path, "test_stat.csv")) # Save relevant columns in binary form for faster dataloading # IMORTANT: We always expect id to be a single column indicating the complete timeseries # We also expect a copy of id in form of static categorical input!!!]] if self.config.get("binarized", False): - grouped_train = group_ids(train, self.features) - grouped_valid = group_ids(valid, self.features) - grouped_test = group_ids(test, self.features) - pickle.dump(grouped_train, open(os.path.join(self.dest_path, "train.bin"), "wb")) - pickle.dump(grouped_valid, open(os.path.join(self.dest_path, "valid.bin"), "wb")) - pickle.dump(grouped_test, open(os.path.join(self.dest_path, "test.bin"), "wb")) + train = group_ids(train, self.features) + valid = group_ids(valid, self.features) + test = group_ids(test, self.features) + train_stat = group_ids(train_stat, self.features) + test_stat = group_ids(test_stat, self.features) + + for file, (grouped_ds, sizes) in (('train.bin', train), + ('valid.bin', valid), + ('test.bin', test), + ('train_stat.bin', train_stat), + ('test_stat.bin', test_stat)): + metadata = { + 'group_sizes': sizes, + 'col_desc': [ + (g.dtype, g.shape, g.nbytes) for g in grouped_ds + ] + } + with open(os.path.join(self.dest_path, file), "wb") as f: + pickle.dump(metadata, f) + for col in grouped_ds: + f.write(b'\0' * get_alignment_compliment_bytes(f.tell(), col.dtype)) + col.tofile(f) + def save_state(self): filepath = os.path.join(self.dest_path, "tspp_preprocess.bin") @@ -469,16 +565,15 @@ def _init_setup(self, dataset=None, drop_na=True): df = pd.read_csv(dataset, parse_dates=[d.name for d in self.feat_splits["dates"]]) elif isinstance(dataset, pd.DataFrame): print("Input DataFrame provided for preprocessing") - #TODO: check support for parse dates as done during read csv # Currently date related features are only used for dataset splits during training df = dataset.copy() else: raise ValueError(F"Function either accepts a path to a csv file or a dataframe") + print("Sorting on time feature") - #TODO: Check if we sort df for inference only case - df = df.sort_values([self.feat_splits["time_feature"].name]) - f_names = [feature.name for feature in self.features] + [self.config.time_ids] - df = df[list(dict.fromkeys(f_names))] + df = df.sort_values([id_feat.name for id_feat in self.feat_splits["id_features"]] + [self.feat_splits["time_feature"].name]) + f_names = {feature.name for feature in self.features} + df = df[f_names] if self.config.get("missing_data_label", False): df = df.replace(self.config.get("missing_data_label"), np.NaN) @@ -491,15 +586,18 @@ def _init_setup(self, dataset=None, drop_na=True): def preprocess(self): df = self._init_setup() self._map_ids(df) + self._map_time_col(df) self._map_categoricals(df) train, valid, test = self._get_dataset_splits(df) train, valid, test = self._drop_unseen_categoricals(train, valid, test) - return train, valid, test + + train_stat, test_stat = self._get_dataset_splits_stat(df) + train_stat, _, test_stat = self._drop_unseen_categoricals(train_stat, test=test_stat) + return train, valid, test, train_stat, test_stat def preprocess_test(self, dataset: Union[str, pd.DataFrame]) -> pd.DataFrame: df = self._init_setup(dataset=dataset, drop_na=False) self._map_ids(df) self._map_categoricals(df) - #TODO: this is a workaround and maybe needs to be handled properly in the future _, _, df = self._drop_unseen_categoricals(None, None, df, drop_unseen=False) - return df \ No newline at end of file + return df diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/datasets.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/datasets.py index 1335001aa..8cd1a8522 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/datasets.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/datasets.py @@ -1,4 +1,4 @@ -# Copyright 2021-2022 NVIDIA Corporation +# Copyright 2021-2024 NVIDIA Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,66 +26,200 @@ # See the License for the specific language governing permissions and # limitations under the License. +from abc import abstractmethod +from typing import Union, List +import enum +import warnings +import mmap import math import os import pickle +import logging from bisect import bisect +from collections import Counter, namedtuple, Iterable +from itertools import product -import dgl import numpy as np import pandas as pd import torch -from data.data_utils import InputTypes, DataTypes, FEAT_NAMES, FEAT_ORDER, DTYPE_MAP, translate_features import dgl -from dgl.transform import metis_partition_assignment +from dgl import metis_partition_assignment from torch.utils.data import Dataset from torch.utils.data.dataloader import default_collate -from data.xgb_util import load_xgb_df, feat_adder, data_label_split, select_test_group, target_shift, \ - xgb_multiID_preprocess -from bisect import bisect -from data.data_utils import InputTypes, DataTypes, FEAT_NAMES, FEAT_ORDER, DTYPE_MAP, translate_features, group_ids +from data.xgb_util import feat_adder, data_label_split, select_test_group, target_shift, xgb_multiID_preprocess +from bisect import bisect, bisect_left +from data.data_utils import InputTypes, DataTypes, FEAT_NAME_MAP, DTYPE_MAP, translate_features, group_ids, get_alignment_compliment_bytes + + +ArgDesc = namedtuple( + 'ArgDesc', + ['name', 'required', 'default', 'extractor'], +) + +DatasetDesc = namedtuple( + 'DatasetDesc', + ['type', # ether xgb, stat or default (DL) dataset + 'data_layout', # e.g. binarized + 'entity_type', # e.g. graph, multi_id, ect + 'target_type'], # single or multi target +) + +class DatasetType(enum.IntEnum): + DL = 0 + XGB = 1 + STAT = 2 + + @staticmethod + def parse(config): + dataset_type = DatasetType.DL + if config.get('xgb', False): + dataset_type = DatasetType.XGB + elif config.get('stat', False): + dataset_type = DatasetType.STAT + return dataset_type + +class DataLayout(enum.IntEnum): + DEFAULT = 0 + BINARIZED = 1 + MEMORY_MAPPED = 2 + + @staticmethod + def parse(config): + data_layout = DataLayout.DEFAULT + if config.get('memory_mapped', False): + data_layout = DataLayout.MEMORY_MAPPED + elif config.get('binarized', False): + data_layout = DataLayout.BINARIZED + return data_layout + +class EntityType(enum.IntEnum): + DEFAULT = 0 + GRAPH = 1 + SHARDED = 2 + MULTIID = 3 + + @staticmethod + def parse(config): + entity_type = EntityType.DEFAULT + if config.get("construct_graph", False): + entity_type = EntityType.GRAPH + elif config.get('sharded', False): + entity_type = EntityType.SHARDED + elif config.get("MultiID", False): + entity_type = EntityType.MULTIID + return entity_type + +class TargetType(enum.IntEnum): + SINGLE = 0 + MULTI = 1 + + @staticmethod + def parse(config): + target_type = TargetType.MULTI if config.get("MultiID", False) else TargetType.SINGLE + if config.get('single_target', False) or config.get('construct_graph', False): + target_type = TargetType.SINGLE + return target_type + + +class BaseDataset(Dataset): + configuration_args = [ + ArgDesc(name='features', required=True, default=None, extractor=lambda config: translate_features(config.features)), + ArgDesc(name='encoder_length', required=True, default=None, extractor=None), + ArgDesc(name='example_length', required=True, default=None, extractor=None), + ArgDesc(name='stride', required=False, default=1, extractor=None) + ] + + @abstractmethod + def __getitem__(self, index): + raise NotImplementedError -class TSBaseDataset(Dataset): + +class DatasetFactory: + _dataset_registry = {} + + @classmethod + def register(cls, type: Union[DatasetType, List[DatasetType]], + data_layout: Union[DataLayout, List[DataLayout]], + entity_type: Union[EntityType, List[EntityType]], + target_type: Union[TargetType, List[TargetType]] + ): + def inner_wrapper(wrapped_class: BaseDataset): + descriptions = [d if isinstance(d, Iterable) else [d] + for d in (type, data_layout, entity_type, target_type)] + for desc in product(*descriptions): + if desc in cls._dataset_registry: + raise ValueError(f'{wrapped_class.__class__.__name__} and {cls._dataset_registry[desc].__class__.__name__} ' + 'datasets match same description. Please, resolve the conflict manually.') + cls._dataset_registry[desc] = wrapped_class + return wrapped_class + return inner_wrapper + + @classmethod + def construct_dataset(cls, dataset_desc, df, config): + if dataset_desc not in cls._dataset_registry: + raise ValueError(f'Failed to create dataset: There is no dataset that matches description {dataset_desc}.') + dataset_class: BaseDataset = cls._dataset_registry[dataset_desc] + dataset_kwargs = {} + for arg in dataset_class.configuration_args: + val = arg.default + if arg.extractor: + try: + val = arg.extractor(config) + except Exception as e: + if arg.required: + raise + else: + print('Encountered error during config parsing', e) + else: + if arg.required: + val = config[arg.name] + else: + val = config.get(arg.name, arg.default) + dataset_kwargs[arg.name] = val + + ds = dataset_class(df=df, **dataset_kwargs) + return ds + + +class TSBaseDataset(BaseDataset): def __init__(self, features, df, encoder_length, example_length, stride=1, **kwargs): super().__init__() assert example_length > encoder_length self.features = features + self.time_feat = [i for i in self.features if i.feature_type == InputTypes.TIME][0] self.encoder_length = encoder_length self.example_length = example_length self.stride = stride self.df = df self.load() - self.features = [i for i in self.features if i.feature_type != InputTypes.TIME] - self.feature_type_col_map = [ - [i for i, f in enumerate(self.features) if (f.feature_type, f.feature_embed_type) == x] for x in FEAT_ORDER - ] + @abstractmethod def load(self): raise NotImplementedError + +@DatasetFactory.register( + type=DatasetType.DL, + data_layout=DataLayout.DEFAULT, + entity_type=EntityType.DEFAULT, + target_type=TargetType.SINGLE +) class TSDataset(TSBaseDataset): def __init__(self, features, df=None, encoder_length=52, example_length=54, stride=1, **kwargs): super().__init__(features, df, encoder_length, example_length, stride) - self.grouped = [x for x in self.grouped if x.shape[0] >= self.example_length] - self.group_lens = [(g.shape[0] - self.example_length + 1) // self.stride for g in self.grouped] - self._cum_examples_in_group = np.cumsum(self.group_lens) - - self.grouped = [ - [ - arr[:, idxs].view(dtype=np.float32).astype(DTYPE_MAP[t[1]]) - for t, idxs in zip(FEAT_ORDER, self.feature_type_col_map) - ] - for arr in self.grouped - ] + + group_lens = (self.group_sizes - self.example_length + 1) // self.stride + self._cum_examples_in_group = np.cumsum(group_lens) + self._group_last_idx = np.cumsum(self.group_sizes) def load(self): if isinstance(self.df, pd.DataFrame): data = self.df else: - data = pd.read_csv(self.df, index_col=0) - self.grouped = group_ids(data, self.features) + data = pd.read_csv(self.df, index_col=0, engine='pyarrow') + self.grouped, self.group_sizes = group_ids(data, self.features) def get_probabilities(self): sampled = [] @@ -102,28 +236,136 @@ def __len__(self): def __getitem__(self, idx): g_idx = bisect(self._cum_examples_in_group, idx) + offset = self._group_last_idx[g_idx - 1] if g_idx else 0 e_idx = idx - self._cum_examples_in_group[g_idx - 1] if g_idx else idx - group = self.grouped[g_idx] + start = offset + e_idx * self.stride + end = offset + e_idx * self.stride + self.example_length + assert end <= self._group_last_idx[g_idx] - tensors = [ - torch.from_numpy(feat[e_idx * self.stride: e_idx * self.stride + self.example_length]) - if feat.size - else torch.empty(0) - for feat in group - ] + out = { + name: torch.from_numpy(feat[start:end]) + for name, feat in zip(FEAT_NAME_MAP.keys(), self.grouped) + } - out = dict(zip(FEAT_NAMES, tensors)) out["id"] = out["id"][0, :] + out["timestamp"] = out["timestamp"][0, :] + return out + +@DatasetFactory.register( + type=DatasetType.DL, + data_layout=DataLayout.DEFAULT, + entity_type=EntityType.SHARDED, + target_type=TargetType.SINGLE +) +class TSShardedDataset(TSBaseDataset): + """ + Experimental class. + """ + def __init__(self, features, df=None, encoder_length=52, example_length=54, stride=1, **kwargs): + super().__init__(features, df, encoder_length, example_length, stride) + + def autodetect_shards(self, df): + time_feat = [i for i in self.features if i.feature_type == InputTypes.TIME][0] + time_diffs = df[time_feat.name].diff() + counter = Counter(time_diffs) + timestep = counter.most_common()[0][0] + + # create groups based on consecutive time differences + groups = (time_diffs != timestep).cumsum() + # group the DataFrame by the groups and create a dictionary of continuous blocks + shards = {group: data for group, data in df.groupby(groups) if len(data) >= self.encoder_length} + return shards + + def load(self): + if isinstance(self.df, pd.DataFrame): + data = self.df + else: + data = pd.read_csv(self.df, index_col=0, engine='pyarrow') + + shards = self.autodetect_shards(data) + + self.shards = [TSDataset(self.features, + df=shard, + encoder_length=self.encoder_length, + example_length=self.example_length, + stride=1) + for shard in shards.values() + ] + self._cum_shards_len = np.cumsum([len(ds) for ds in self.shards]) + + def __len__(self): + return self._cum_shards_len[-1] + + def __getitem__(self, idx): + g_idx = bisect(self._cum_shards_len, idx) + e_idx = idx - self._cum_shards_len[g_idx - 1] if g_idx else idx + + return self.shards[g_idx][e_idx] + + +@DatasetFactory.register( + type=DatasetType.DL, + data_layout=DataLayout.BINARIZED, + entity_type=EntityType.DEFAULT, + target_type=TargetType.SINGLE +) class TSBinaryDataset(TSDataset): def load(self): if isinstance(self.df, pd.DataFrame): data = self.df - self.grouped = group_ids(data, self.features) + self.grouped, self.group_sizes = group_ids(data, self.features) else: - self.grouped = pickle.load(open(self.df, "rb")) + with open(self.df, "rb") as f: + metadata = pickle.load(f) + self.group_sizes = metadata['group_sizes'] + self.grouped = [] + for dtype, shape, _ in metadata['col_desc']: + offset = get_alignment_compliment_bytes(f.tell(), dtype) + self.grouped.append( + np.fromfile(f, dtype=dtype, count=np.prod(shape), offset=offset).reshape(*shape) + ) + + +@DatasetFactory.register( + type=DatasetType.DL, + data_layout=DataLayout.MEMORY_MAPPED, + entity_type=EntityType.DEFAULT, + target_type=TargetType.SINGLE +) +class TSMemoryMappedDataset(TSDataset): + warnings.filterwarnings('ignore', category=UserWarning, message='The given NumPy array is not writable,') + + def load(self): + if isinstance(self.df, pd.DataFrame): + raise ValueError(f'{self.__class__.__name__} does not support loading from DataFrame') + + f = open(self.df, "rb") + metadata = pickle.load(f) + self.group_sizes = metadata['group_sizes'] + + offset = f.tell() + buf = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + try: + # try to enable huge pages to improve performance + buf.madvise(mmap.MADV_HUGEPAGE) + except Exception: + logging.info("Failed to enable huge pages on mapped dataset") + + # it would be nice for the OS to load some pages ahead + # in case they are on an actual file system and not shmem/tmpfs + buf.madvise(mmap.MADV_WILLNEED) + + self.grouped = [] + for dtype, shape, nbytes in metadata['col_desc']: + offset += get_alignment_compliment_bytes(offset, dtype) + self.grouped.append( + np.frombuffer(buffer=buf, dtype=dtype, count=np.prod(shape), offset=offset).reshape(*shape) + ) + offset += nbytes + class TSMultiIDDatasetBase(TSBaseDataset): def __init__(self, @@ -137,10 +379,6 @@ def __init__(self, ): super().__init__(features, df, encoder_length, example_length, stride) - # This part is tricky: we want to do this only for training dataset and then apply the same changes to valid and test splits to maintain coherence. - # We can't do this in the preprocessing step because many different dataset classes rely on the same csv file. Thus the first time dataset is created - # if we pass empty list of collumns to collapse and populate it here. This list is a part for common argument set for the train, valid and test splits - # so is maintained throughout construction of all the splits. if collumns_to_collapse is not None: if not collumns_to_collapse: for name, df in self.tables.items(): @@ -157,16 +395,15 @@ def __init__(self, self.tables[name] = self.tables[name].iloc[:, :1] self.data = {} - for fname, ftype in zip(FEAT_NAMES, FEAT_ORDER): + for fname, ftype in FEAT_NAME_MAP.items(): names = [f.name for f in self.features if (f.feature_type, f.feature_embed_type) == ftype] if names: - df = pd.concat([v for k,v in self.tables.items() if k in names], axis=1) - self.data[fname] = df.values.astype(dtype=DTYPE_MAP[ftype[1]]) + self.data[fname] = [v.values.astype(dtype=DTYPE_MAP[ftype[1]]) for k,v in self.tables.items() if k in names] else: self.data[fname] = None del self.tables - self._n_timeslices = (next(len(df) for df in self.data.values() if df is not None) - self.example_length + 1) // self.stride + self._n_timeslices = (next(len(x[0]) for x in self.data.values() if x is not None) - self.example_length + 1) // self.stride def load(self): time_col_name = next(x.name for x in self.features if x.feature_type == InputTypes.TIME) @@ -174,12 +411,30 @@ def load(self): if isinstance(self.df, pd.DataFrame): data = self.df else: - data = pd.read_csv(self.df, index_col=0) + data = pd.read_csv(self.df, index_col=0, engine='pyarrow') self.tables = {} for f in self.features: self.tables[f.name] = data.pivot(index=time_col_name, columns=id_col_name, values=f.name) + +@DatasetFactory.register( + type=DatasetType.DL, + data_layout=DataLayout.DEFAULT, + entity_type=EntityType.MULTIID, + target_type=TargetType.MULTI +) class TSMultiTargetDataset(TSMultiIDDatasetBase): + configuration_args = ( + TSMultiIDDatasetBase.configuration_args + + [ + ArgDesc(name='collumns_to_collapse', required=False, default=None, extractor=lambda config: [] if config.get('collapse_identical_columns', False) else None) + ] + ) + def __init__(self, *args, **kwargs): + assert kwargs.get('columns_to_collapse') is None, "Can't use TSMultiTargetDataset with collapse_identical_columns=True" + super().__init__(*args, **kwargs) + self.data = {k: np.stack(v, axis=-1) if v is not None else None for k, v in self.data.items()} + def __len__(self): return self._n_timeslices @@ -196,12 +451,29 @@ def __getitem__(self, idx): for k,v in self.data.items() } + # There is only one id column, so squeeze dimension which was produced by torch.stack + out['id'] = out['id'].squeeze(-1) + out['timestamp'] = out['timestamp'].squeeze(-1) + return out -class TSMultiIDDataset(TSMultiIDDatasetBase): +@DatasetFactory.register( + type=DatasetType.DL, + data_layout=DataLayout.DEFAULT, + entity_type=EntityType.MULTIID, + target_type=TargetType.SINGLE +) +class TSMultiIDDataset(TSMultiIDDatasetBase): + configuration_args = ( + TSMultiIDDatasetBase.configuration_args + + [ + ArgDesc(name='collumns_to_collapse', required=False, default=None, extractor=lambda config: [] if config.get('collapse_identical_columns', False) else None) + ] + ) def __init__(self, features, df=None, encoder_length=52, example_length=54, stride=1, collumns_to_collapse=None, **kwargs): super().__init__(features, df, encoder_length, example_length, stride, collumns_to_collapse) + self.data = {k: np.concatenate(v, axis=-1) if v is not None else None for k, v in self.data.items()} def __len__(self): return self._n_timeslices * self.data['id'].shape[1] @@ -217,7 +489,6 @@ def __getitem__(self, idx): for k,v in self.data.items() } out['o_cont'] = torch.cat([out['o_cont'], targets], dim=-1) - out['s_cat'] = out['s_cat'][:, g_idx].unsqueeze(1) if out['s_cat'].numel() else out['s_cat'] out['s_cont'] = out['s_cont'][:, g_idx].unsqueeze(1) if out['s_cont'].numel() else out['s_cont'] out['id'] = out['id'][:, g_idx] @@ -226,93 +497,173 @@ def __getitem__(self, idx): out['weight'] = out['weight'][:, g_idx].unsqueeze(1) if out['weight'].numel() else out['weight'] return out - -class StatDataset(Dataset): - def __init__(self, features, path_stat, df=None, encoder_length=52, example_length=54, stride=1, split=None, split_feature=None, ds_type=None): - self.ds_type = ds_type - if ds_type == "valid": - return - super().__init__() - assert example_length > encoder_length, "Length of example longer than encoder length" - assert split, "Split not given" - assert ds_type in ["train", "test"] - self.features = features - self.time_feature = split_feature - self.weight_features = [feature.name for feature in self.features if feature.feature_type == InputTypes.WEIGHT] - self.encoder_length = encoder_length - self.example_length = example_length - self.horizon = self.example_length - self.encoder_length - self.stride = stride - self.split = split - self.id_col_name = next(x.name for x in self.features if x.feature_type == InputTypes.ID) - self.col_dtypes = {v.name: DTYPE_MAP[v.feature_embed_type] for v in self.features} - if isinstance(df, pd.DataFrame): - self.data = df.astype(self.col_dtypes) - else: - self.data = pd.read_csv(os.path.join(path_stat, "full.csv"), dtype=self.col_dtypes) - self.data = self.data.groupby(self.id_col_name).filter(lambda group: len(group) >= self.example_length) - self.grouped = list(self.data.groupby(self.id_col_name)) - self.endog = [feature.name for feature in self.features if feature.feature_type == InputTypes.TARGET] - self.exog = [ - feature.name - for feature in self.features - if feature.feature_type in [InputTypes.KNOWN, InputTypes.OBSERVED, InputTypes.STATIC] - and feature.feature_embed_type == DataTypes.CONTINUOUS - ] - self.grouped = [group[1] for group in self.grouped] - self.grouped = [ - group - for group in self.grouped - if len(group[group[self.time_feature] <= self.split]) >= self.encoder_length - and len(group[group[self.time_feature] > self.split]) >= self.horizon +@DatasetFactory.register( + type=DatasetType.STAT, + data_layout=DataLayout.DEFAULT, + entity_type=EntityType.DEFAULT, + target_type=TargetType.SINGLE +) +class StatDataset(TSBaseDataset): + configuration_args = ( + TSBaseDataset.configuration_args + + [ + ArgDesc(name='use_last', required=False, default=0, extractor=None) ] + ) + def __init__(self, features, df=None, encoder_length=52, example_length=54, stride=1, use_last=0): + self.use_last = use_last + super().__init__(features, df, encoder_length, example_length, stride) + self.test = False - self._cum_examples_in_group = np.cumsum( - [(len(group[group[self.time_feature] > split]) - self.horizon) // self.stride + 1 for group in self.grouped] - ) + self.horizon = self.example_length - self.encoder_length + feat_names = list(FEAT_NAME_MAP.keys()) + self.id_col_id = feat_names.index('id') + self.weight_col_id = feat_names.index('weight') + self.endog_col_id = feat_names.index('target') + self.exog_col_id = [i for i, feat in enumerate(feat_names) if feat.endswith('cont')] + + self._group_last_idx = np.cumsum(self.group_sizes) + self._cum_examples_in_group = np.cumsum((self.group_sizes - self.horizon + 1) // self.stride) + + def load(self): + if isinstance(self.df, pd.DataFrame): + self.data = self.df + else: + data = pd.read_csv(self.df, index_col=0, engine='pyarrow') + self.grouped, self.group_sizes = group_ids(data, self.features) def __len__(self): - if self.ds_type == "valid": - raise ValueError - return self._cum_examples_in_group[-1] + return self._cum_examples_in_group[-1] if self.test else len(self.group_sizes) def __getitem__(self, idx): - if self.ds_type == "valid": - raise ValueError - if idx > self._cum_examples_in_group[-1]: + if ((self.test and idx > self._cum_examples_in_group[-1]) or + (not self.test and idx > len(self.group_sizes))): raise StopIteration - g_idx = bisect(self._cum_examples_in_group, idx) - e_idx = idx - self._cum_examples_in_group[g_idx - 1] if g_idx else idx - group = self.grouped[g_idx] - test = group[group[self.time_feature] > self.split] - if self.ds_type == "test": - test_slice = test[self.stride * e_idx: self.stride * e_idx + self.horizon] - test_out = {"endog": test_slice[self.endog], "exog": test_slice[self.exog], "id": test_slice[self.id_col_name]} - if len(self.weight_features): - test_out["weight"] = test_slice[self.weight_features] - return test_out + + if not self.test: + start = self._group_last_idx[idx - 1] if idx else 0 + end = self._group_last_idx[idx] + if self.use_last > 0: + start = end - self.use_last + + update_start = 0 + update_end = 0 else: - train = group[group[self.time_feature] <= self.split] - if (self.encoder_length - self.stride * e_idx) > 0: - train_slice = train[-(self.encoder_length - self.stride * e_idx):].append( - test[max(0, self.stride * e_idx - self.encoder_length): self.stride * e_idx] - ) - else: - train_slice = test[max(0, self.stride * e_idx - self.encoder_length): self.stride * e_idx] + g_idx = bisect(self._cum_examples_in_group, idx) + offset = self._group_last_idx[g_idx - 1] if g_idx else 0 + e_idx = idx - self._cum_examples_in_group[g_idx - 1] if g_idx else idx + + start = offset + e_idx * self.stride + end = offset + e_idx * self.stride + self.horizon + assert end <= self._group_last_idx[g_idx] + update_start = (e_idx - 1 if e_idx else 0) * self.stride + update_end = e_idx * self.stride + + out = { + 'endog': self.grouped[self.endog_col_id][start:end], + 'exog': np.hstack(self.grouped[i][start:end] for i in self.exog_col_id), + 'id': self.grouped[self.id_col_id][start].item(), + 'weight': self.grouped[self.weight_col_id][start:end], + 'endog_update': self.grouped[self.endog_col_id][update_start:update_end], + 'exog_update': np.hstack(self.grouped[i][update_start:update_end] for i in self.exog_col_id), + } + return out - train_out = {"endog": train_slice[self.endog], "exog": train_slice[self.exog]} - return train_out +@DatasetFactory.register( + type=DatasetType.STAT, + data_layout=DataLayout.BINARIZED, + entity_type=EntityType.DEFAULT, + target_type=TargetType.SINGLE +) +class BinaryStatDataset(StatDataset): + def load(self): + if isinstance(self.df, pd.DataFrame): + data = self.df + self.grouped, self.group_sizes = group_ids(data, self.features) + else: + with open(self.df, "rb") as f: + metadata = pickle.load(f) + self.group_sizes = metadata['group_sizes'] + self.grouped = [] + for dtype, shape, _ in metadata['col_desc']: + offset = get_alignment_compliment_bytes(f.tell(), dtype) + self.grouped.append( + np.fromfile(f, dtype=dtype, count=np.prod(shape), offset=offset).reshape(*shape) + ) + +@DatasetFactory.register( + type=DatasetType.STAT, + data_layout=DataLayout.MEMORY_MAPPED, + entity_type=EntityType.DEFAULT, + target_type=TargetType.SINGLE +) +class TSMemoryMappedDataset(StatDataset): + def load(self): + if isinstance(self.df, pd.DataFrame): + raise ValueError(f'{self.__class__.__name__} does not support loading from DataFrame') + + f = open(self.df, "rb") + metadata = pickle.load(f) + self.group_sizes = metadata['group_sizes'] + + offset = f.tell() + buf = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + try: + # try to enable huge pages to improve performance + buf.madvise(mmap.MADV_HUGEPAGE) + except Exception: + logging.info("Failed to enable huge pages on mapped dataset") + + # it would be nice for the OS to load some pages ahead + # in case they are on an actual file system and not shmem/tmpfs + buf.madvise(mmap.MADV_WILLNEED) + + self.grouped = [] + for dtype, shape, nbytes in metadata['col_desc']: + offset += get_alignment_compliment_bytes(offset, dtype) + self.grouped.append( + np.frombuffer(buffer=buf, dtype=dtype, count=np.prod(shape), offset=offset).reshape(*shape) + ) + offset += nbytes + + +@DatasetFactory.register( + type=DatasetType.XGB, + data_layout=DataLayout.DEFAULT, + entity_type=[EntityType.DEFAULT, EntityType.MULTIID], + target_type=TargetType.SINGLE +) +class XGBDataset(TSBaseDataset): + configuration_args = ( + TSBaseDataset.configuration_args + + [ + ArgDesc(name='lag_features', required=False, default=[], extractor=None), + ArgDesc(name='moving_average_features', required=False, default=[], extractor=None), + ArgDesc(name='MultiID', required=False, default=False, extractor=None), + ] + ) + def __init__(self, features, df, encoder_length, example_length, lag_features, moving_average_features, MultiID, **kwargs): + super().__init__(features, df, encoder_length, example_length, stride=1) -class XGBDataset(Dataset): - def __init__(self, df, path_xgb, features_xgb, lag_features, moving_average_features, example_length, encoder_length, time_series_count, MultiID, ds_type, **kwargs): - self.ds_type = ds_type - features = features_xgb - dest_path = df if isinstance(df, pd.DataFrame) else path_xgb - self.encoder_length = encoder_length - self.example_length = example_length + self.test = False + + self.horizon = example_length - encoder_length + self.target = [feature.name for feature in features if + feature.feature_type == InputTypes.TARGET] + self.time_feat = [feature.name for feature in features if + feature.feature_type == InputTypes.TIME] + + # Filter out special features + self.features = [f for f in self.features if not f.feature_type in (InputTypes.TIME, InputTypes.WEIGHT, InputTypes.ID)] + + self.observed = [feature.name for feature in features if + feature.feature_type == InputTypes.OBSERVED] + self.known = [feature.name for feature in features if + feature.feature_type in [InputTypes.KNOWN, InputTypes.STATIC]] + lag_features_conf = lag_features self.lag_features = {} for feat in lag_features_conf: @@ -329,31 +680,37 @@ def __init__(self, df, path_xgb, features_xgb, lag_features, moving_average_feat assert feat.get("window_size", None) is not None self.moving_average_features[feat.name] = self.moving_average_features.get(feat.name, []) + [ feat.window_size] - self.horizon = example_length - encoder_length - self.target = [feature.name for feature in features if - feature.feature_type == "TARGET"] - self.observed = [feature.name for feature in features if - feature.feature_type == "OBSERVED"] - self.known = [feature.name for feature in features if - feature.feature_type in ["KNOWN", "STATIC"]] - assert len(self.target) == 1, "Only 1 target feature is currently supported with xgboost" - self.data = load_xgb_df(dest_path, features, ds_type) - self.extra_columns = [[f'{k}_{i}' for i in v] for k, v in self.lag_features.items()] + if MultiID: target = self.target[0] lag_target_value = self.lag_features.pop(target, []) + + time_series_count = self.data['_id_'].nunique() for i in range(time_series_count): self.lag_features[f'{target}_{i}'] = lag_target_value self.moving_average_features[f'{target}_{i}'] = self.moving_average_features.pop(target, []) - self.data = xgb_multiID_preprocess(self.data, features, time_series_count) # XXX need to work with + self.data = xgb_multiID_preprocess(self.data, self.time_feat[0], target) + self.data = feat_adder(self.data, self.lag_features, self.moving_average_features) + self.data = self.data.loc[:, sorted(self.data.columns)] + + def load(self): + if isinstance(self.df, pd.DataFrame): + data = self.df + else: + data = pd.read_csv(self.df, index_col=0, engine='pyarrow') + + all_features = {f.name for f in self.features} + data = data[all_features] + data = data.select_dtypes(exclude='object') + self.data = data def __getitem__(self, idx): if idx >= self.horizon: raise StopIteration data_step = self.data.copy() - data_step = target_shift(data_step, self.target, self.known, idx) - if self.ds_type == 'test': + data_step = target_shift(data_step, self.target, [], idx) + if self.test: data_step = select_test_group(data_step, self.encoder_length, self.example_length) labels = data_label_split(data_step, [f'{i}_target' for i in self.target]) return data_step, labels @@ -361,16 +718,39 @@ def __getitem__(self, idx): def __len__(self): return self.horizon -class ClusteredGraphDataset(Dataset): - def __init__(self, graph, graph_partitions=10, partition_joining_coef=2, **kwargs): + +@DatasetFactory.register( + type=DatasetType.DL, + data_layout=DataLayout.DEFAULT, + entity_type=EntityType.GRAPH, + target_type=TargetType.SINGLE +) +class TemporalClusteredGraphDataset(TSMultiIDDatasetBase): + configuration_args = ( + TSMultiIDDatasetBase.configuration_args + + [ + ArgDesc(name='graph', required=True, default=None, extractor=lambda config: os.path.join(config.dest_path, config.graph)), + ArgDesc(name='graph_partitions', required=True, default=None, extractor=None), + ArgDesc(name='partition_joining_coef', required=True, default=None, extractor=None), + ] + ) + def __init__(self, features, graph, df=None, encoder_length=52, example_length=54, stride=1, graph_partitions=1, partition_joining_coef=1, **kwargs): + assert isinstance(graph_partitions, int) and graph_partitions > 0 + assert partition_joining_coef <= graph_partitions + assert graph is not None + + super().__init__(features, df, encoder_length, example_length, stride, collumns_to_collapse=None) + if isinstance(graph, str): self.graph = pickle.load(open(graph, "rb")) + if isinstance(self.graph, np.ndarray): + edges = np.nonzero(self.graph) + weights = self.graph[edges] + self.graph = dgl.graph(edges) + self.graph.edata['w'] = torch.tensor(weights) else: self.graph = graph - assert isinstance(graph_partitions, int) and graph_partitions > 0 - assert partition_joining_coef <= graph_partitions - self.part_count = graph_partitions if graph_partitions > 1: self.partition = metis_partition_assignment(self.graph, self.part_count) @@ -378,16 +758,30 @@ def __init__(self, graph, graph_partitions=10, partition_joining_coef=2, **kwarg self.partition = torch.zeros(self.graph.num_nodes(), dtype=torch.int64) self.joining_coef = partition_joining_coef + for k,v in self.data.items(): + if v is not None: + self.data[k] = np.stack(self.data[k], axis=1).transpose(2,0,1) + def __len__(self): - return math.comb(self.part_count, self.joining_coef) + return math.comb(self.part_count, self.joining_coef) * self._n_timeslices def __getitem__(self, idx): - indicator = self.idx_to_combination(self.part_count, self.joining_coef, idx) - c_ids = np.nonzero(indicator)[0] - subgraph = self.get_subgraph(c_ids) + g_idx = idx // self._n_timeslices + t_idx = idx - g_idx * self._n_timeslices + subgraph = self.get_subgraph(g_idx) + node_ids = np.array(subgraph.ndata["_ID"]) + for k, v in self.data.items(): + subgraph.ndata[k] = torch.from_numpy( + v[node_ids, t_idx * self.stride: t_idx * self.stride + self.example_length, :] + ) if v is not None else torch.empty((self.graph.num_nodes(),0)) + + subgraph.ndata['id'] = subgraph.ndata['id'][:,0,:] + return subgraph - def get_subgraph(self, c_ids): + def get_subgraph(self, idx): + indicator = self.idx_to_combination(self.part_count, self.joining_coef, idx) + c_ids = np.nonzero(indicator)[0] ids = sum([self.partition == i for i in c_ids]).bool() return self.graph.subgraph(ids) @@ -415,130 +809,46 @@ def idx_to_combination(self, n, r, m): return out -class TemporalClusteredGraphDataset(ClusteredGraphDataset): - def __init__(self, features, graph, df=None, encoder_length=52, example_length=54, stride=1, **kwargs): - super().__init__(graph, **kwargs) - assert example_length > encoder_length - self.features = [i for i in features if i.feature_type != InputTypes.TIME] - self.encoder_length = encoder_length - self.example_length = example_length - self.stride = stride - self.df = df - - self.feature_type_col_map = [ - np.array([i for i, f in enumerate(self.features) if (f.feature_type, f.feature_embed_type) == x]) - for x in FEAT_ORDER - ] - if isinstance(df, pd.DataFrame): - data = self.df - grouped = group_ids(data, self.features) - else: - grouped = pickle.load(open(self.df, "rb")) - # We assume that all the time series are of the same length and have the same set of features - assert all([x.shape == grouped[0].shape for x in grouped]) - - ndata = np.stack(grouped) - self.ndata = { - name: ndata[:, :, ids].view(dtype=np.float32).astype(DTYPE_MAP[f[1]]) - if not ids.size == 0 - else np.empty((*ndata.shape[:-1], 0)) - for name, f, ids in zip(FEAT_NAMES, FEAT_ORDER, self.feature_type_col_map) - } - - self.t_dim = ndata.shape[1] - self.n_timeslices = (self.t_dim - self.example_length + 1) // self.stride - - def __len__(self): - # the number of possible subgraphs times the number of possible time slices - return super().__len__() * self.n_timeslices - - def __getitem__(self, idx): - g_idx = idx // self.n_timeslices - t_idx = idx - g_idx * self.n_timeslices - subgraph = super().__getitem__(g_idx) - node_ids = np.array(subgraph.ndata["_ID"]) - for k, v in self.ndata.items(): - subgraph.ndata[k] = torch.from_numpy( - v[node_ids, t_idx * self.stride: t_idx * self.stride + self.example_length, :] - ) - - return subgraph - - +def _parse_dataset_description(config): + dataset_type = DatasetType.parse(config=config) + data_layout = DataLayout.parse(config=config) + entity_type = EntityType.parse(config=config) + target_type = TargetType.parse(config=config) + + return DatasetDesc( + type=dataset_type, + data_layout=data_layout, + entity_type=entity_type, + target_type=target_type + ) def create_datasets(config, input_df=None): - def select_dataset_class(config): - binarized = config.get("binarized", False) - graph_dataset = config.get("construct_graph", False) - multi_id_dataset = config.get("MultiID", False) - single_target = config.get('single_target', False) - if config.get("xgb", False): - specific_args = { - "path_xgb": config.dest_path, - "features_xgb": config.features, - "lag_features": config.get("lag_features", []), - "moving_average_features": config.get("moving_average_features", []), - "time_series_count": config.time_series_count, - "MultiID": config.get("MultiID", False) - } - return XGBDataset, specific_args - - if config.get("stat", False): - - specific_args = { - "path_stat": config.dest_path, - "split": config.test_range[0], - "split_feature": config.time_ids - } - return StatDataset, specific_args - if binarized and graph_dataset: - specific_args = { - "graph": os.path.join(config.dest_path, "graph.bin"), - "graph_partitions": config.graph_partitions, - "partition_joining_coef": config.partition_joining_coef, - } - return TemporalClusteredGraphDataset, specific_args - elif binarized and multi_id_dataset: - raise NotImplementedError - elif binarized: - return TSBinaryDataset, {} - elif not binarized and graph_dataset: - raise NotImplementedError - elif not binarized and multi_id_dataset and not single_target: - specific_args = {} - if config.get('collapse_identical_columns', False): - specific_args['collumns_to_collapse'] = [] - return TSMultiTargetDataset, specific_args - elif not binarized and multi_id_dataset and single_target: - specific_args = {} - if config.get('collapse_identical_columns', False): - specific_args['collumns_to_collapse'] = [] - return TSMultiIDDataset, specific_args - else: - return TSDataset, {} - - common_args = { - "features": translate_features(config.features), - "encoder_length": config.encoder_length, - "example_length": config.example_length, - "stride": config.get("stride", 1), - } - - dataset_class, specific_args = select_dataset_class(config) - + dataset_desc = _parse_dataset_description(config) if input_df is not None: print("Input DataFrame provided to create_datasets functions") print("Warning: Please make sure the dataframe is preprocessed") - test = dataset_class(df=input_df, **common_args, **specific_args, ds_type='test') + test = DatasetFactory.construct_dataset(dataset_desc, df=input_df, config=config) train = None valid = None else: path_template = os.path.join(config.dest_path, "{{subset}}.{extension}") - path_template = path_template.format(extension="bin" if config.get("binarized", False) else "csv") + path_template = path_template.format(extension="bin" if config.get("binarized", False) or config.get("memory_mapped", False) else "csv") - train = dataset_class(df=path_template.format(subset="train"), **common_args, **specific_args, ds_type="train") - valid = dataset_class(df=path_template.format(subset="valid"), **common_args, **specific_args, ds_type="valid") - test = dataset_class(df=path_template.format(subset="test"), **common_args, **specific_args, ds_type="test") + train = DatasetFactory.construct_dataset(dataset_desc, + df=path_template.format(subset="train" if dataset_desc.type is not DatasetType.STAT else "train_stat"), + config=config, + ) + + valid = DatasetFactory.construct_dataset(dataset_desc, + df=path_template.format(subset="valid"), + config=config, + ) if dataset_desc.type is not DatasetType.STAT else None + + test = DatasetFactory.construct_dataset(dataset_desc, + df=path_template.format(subset="test" if dataset_desc.type is not DatasetType.STAT else "test_stat"), + config=config, + ) + if not (config.get("xgb", False) or config.get("stat", False)): train = sample_data(train, config.get("train_samples", -1)) valid = sample_data(valid, config.get("valid_samples", -1)) @@ -568,24 +878,43 @@ def collate_graph(samples): weights = weights[:, encoder_length :, :] return batch, labels, weights - def collate_ar(samples): + def collate_dict(samples): + """Default TSPP collater""" batch = default_collate(samples) - labels = batch["target"] + labels = batch["target"][:, encoder_length :, :] + if test: + labels = labels.clone() + batch['target'][:, encoder_length :, :] = 0 + if batch['o_cat'].numel(): + batch['o_cat'][:, encoder_length :, :] = 0 + if batch['o_cont'].numel(): + batch['o_cont'][:, encoder_length :, :] = 0 weights = batch['weight'] + if weights is not None and weights.numel(): + weights = weights[:, encoder_length :, :] return batch, labels, weights - def collate_dict(samples): - """Default TSPP collater""" + def collate_ar(samples): + """A collater for autoregressive models""" batch = default_collate(samples) - labels = batch["target"][:, encoder_length:, :] + labels = batch["target"] weights = batch['weight'] - if weights is not None and weights.numel(): - weights = weights[:, encoder_length:, :] + if test: + labels = labels.clone() + labels = labels[:, encoder_length:, :] + batch['target'][:, encoder_length:, :] = 0 + if batch['o_cat'].numel(): + batch['o_cat'][:, encoder_length:, :] = 0 + if batch['o_cont'].numel(): + batch['o_cont'][:, encoder_length:, :] = 0 + if weights is not None and weights.numel(): + weights = weights[:, encoder_length:, :] + return batch, labels, weights if model_type == 'graph': return collate_graph - elif model_type == 'autoregressive' and not test: + if model_type == 'autoregressive': return collate_ar else: return collate_dict diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/script_download_data.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/script_download_data.py index 4571986ed..73cfb8068 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/script_download_data.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/script_download_data.py @@ -1,4 +1,4 @@ -# Copyright 2021-2022 NVIDIA Corporation +# Copyright 2021-2024 NVIDIA Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -50,6 +50,7 @@ import numpy as np import pandas as pd +import py7zr import pyunpack import wget import pickle @@ -72,11 +73,14 @@ def download_from_url(http://github.com/url,%20output_path): print("done") -def unzip(zip_path, output_file, data_folder): +def unzip(zip_path, output_file, data_folder, use_z=False): """Unzips files and checks successful completion.""" print("Unzipping file: {}".format(zip_path)) - pyunpack.Archive(zip_path).extractall(data_folder) + if use_z: + py7zr.SevenZipFile(zip_path, mode="r").extractall(path=data_folder) + else: + pyunpack.Archive(zip_path).extractall(data_folder) # Checks if unzip was successful if not os.path.exists(output_file): @@ -106,7 +110,7 @@ def download_and_unzip(url, zip_path, csv_path, data_folder): def download_electricity(data_folder): """Downloads electricity dataset from UCI repository.""" - url = "https://archive.ics.uci.edu/ml/machine-learning-databases/00321/LD2011_2014.txt.zip" + url = "https://archive.ics.uci.edu/static/public/321/electricityloaddiagrams20112014.zip" csv_path = os.path.join(data_folder, "LD2011_2014.txt") zip_path = csv_path + ".zip" @@ -167,8 +171,7 @@ def download_electricity(data_folder): output.to_csv(data_folder + "/electricity.csv") print("Done.") - - + def download_traffic(data_folder): """Downloads traffic dataset from UCI repository.""" @@ -332,6 +335,58 @@ def format_index_string(x): flat_df.to_csv(data_folder + "/traffic.csv") +def download_m5(data_folder): + """Processes M5 Kaggle competition dataset. + + Raw files can be manually downloaded from Kaggle (without test set) @ + https://www.kaggle.com/c/m5-forecasting-accuracy/data + + Data is downloaded from Google Drive from organizers @ + https://github.com/Mcompetitions/M5-methods + + Args: + config: Default experiment config for M5 + """ + required_files = ['sales_train_evaluation.csv', 'sales_test_evaluation.csv', + 'sell_prices.csv', 'calendar.csv', 'weights_validation.csv', + 'weights_evaluation.csv'] + + for file in required_files: + assert os.path.exists(os.path.join(data_folder, file)), "There are files missing from the data_folder. Please download following files from https://github.com/Mcompetitions/M5-methods" + + core_frame = pd.read_csv(os.path.join(data_folder, "sales_train_evaluation.csv")) + test_frame = pd.read_csv(os.path.join(data_folder, "sales_test_evaluation.csv")) + # Add 28 prediction values for final model evaluation + core_frame = core_frame.merge(test_frame, on=['item_id', 'dept_id', 'cat_id', 'store_id', 'state_id']) + del test_frame + + id_vars = ["id", "item_id", "dept_id", "cat_id", "store_id", "state_id"] + ts_cols = [col for col in core_frame.columns if col not in id_vars] + + core_frame['id'] = core_frame.item_id + '_' + core_frame.store_id + prices = pd.read_csv(os.path.join(data_folder, "sell_prices.csv")) + calendar = pd.read_csv(os.path.join(data_folder, "calendar.csv")) + + calendar = calendar.sort_values('date') + calendar['d'] = [f'd_{i}' for i in range(1, calendar.shape[0]+1)] + + core_frame = core_frame.melt( + id_vars, + value_vars=ts_cols, + var_name='d', + value_name='items_sold' + ) + core_frame = core_frame.merge(calendar, left_on="d", right_on='d') + core_frame = core_frame.merge(prices, on=['store_id', 'item_id', 'wm_yr_wk'], how='outer') + + # According to M5-Comperition-Guide-Final-10-March-2020: + # if not available, this means that the product was not sold during the examined week. + core_frame.sell_price.fillna(-1, inplace=True) + + core_frame['weight'] = 1.0 + core_frame.loc[core_frame.sell_price == -1, 'weight'] = 0 + + core_frame.to_csv(os.path.join(data_folder, "M5.csv")) def construct_graph(nodes_loc, k=0.8): """ @@ -350,6 +405,125 @@ def construct_graph(nodes_loc, k=0.8): graph = dgl.graph(edges, num_nodes=nodes_loc.shape[0]) return graph +def download_PEMS_BAY(data_folder): + def check_completeness(data_folder): + """Returns list of raw data files""" + + def daterange(start_date, end_date): + for n in range(int((end_date - start_date).days)): + yield start_date + timedelta(n) + + start_date = date(2017, 1, 1) + end_date = date(2017, 7, 1) + fnames = ['d04_text_station_5min_' + d.strftime('%Y_%m_%d') + '.txt.gz' for d in daterange(start_date, end_date)] + missing = set(fnames).difference(os.listdir(data_folder)) + assert not missing, f"""There are files missing from the data_folder. + Please download following files from https://pems.dot.ca.gov/?dnode=Clearinghouse + {missing}""" + + fnames = [os.path.join(data_folder, f) for f in fnames] + return fnames + + + def load_single_day(path, header, ids=None): + df = pd.read_csv(path, header=None) + df = df.rename(columns = lambda i: header[i]) + df.drop(columns=[c for c in df.columns if 'Lane' in c] + ['District'], inplace=True) + if ids: + df = df[df['Station'].isin(ids)] + df['Timestamp'] = pd.to_datetime(df['Timestamp']) + + # Identify gaps in timelines + num_gaps = 0 + all_timestamps = set(df['Timestamp']) + interpolated = [] + groups = df.groupby('Station') + for id, g in groups: + if len(g) != len(g.dropna(subset=['Total Flow'])): + _timestamps = set(g['Timestamp']).difference(set(g.dropna(subset=['Total Flow'])['Timestamp'])) + num_gaps += len(_timestamps) + print(f'Found NaN in "Total Flow" at timestamps {_timestamps}') + print('Interpolating...') + + diff = all_timestamps.difference(g['Timestamp']) + if diff: + num_gaps += len(diff) + print(f'Missing observations ID {id} Timestamps: {diff}', file=sys.stderr) + for elem in diff: + g = g.append({'Timestamp':elem}, ignore_index=True) + + g = g.sort_values('Timestamp') + g = g.interpolate(method='ffill') + g = g.fillna(method = 'pad') + interpolated.append(g) + + df = pd.concat(interpolated) + if num_gaps: + print(f'Missing {num_gaps/len(df) * 100}% of the data') + + # Add derived time info + #df['Year'] = df['Timestamp'].apply(lambda x: x.year) + df['Day of week'] = df['Timestamp'].apply(lambda x: x.dayofweek) + df['Month'] = df['Timestamp'].apply(lambda x: x.month) + df['Day'] = df['Timestamp'].apply(lambda x: x.day) + df['Hour'] = df['Timestamp'].apply(lambda x: x.hour) + df['Minute'] = df['Timestamp'].apply(lambda x: x.minute) + + return df + + raw_paths = check_completeness(data_folder) + for p in raw_paths: + if p.endswith('.txt.gz'): + unzip(p, p[:-3], data_folder) + paths = [p[:-3] for p in raw_paths] + + # PEMS website doesn't provide headers in any of the files, so they have to be infered from the hints on site itself + header = ['Timestamp', 'Station', 'District', 'Freeway #', 'Direction of Travel', 'Lane Type', 'Station Length', + 'Samples', '% Observed', 'Total Flow', 'Avg Occupancy', 'Avg Speed'] + header += [name.format(i) for i in range(8) for name in ['Lane {} Samples', 'Lane {} Flow', 'Lane {} Avg Occ', 'Lane {} Avg Speed', 'Lane {} Observed']] + ids = [400001, 400017, 400030, 400040, 400045, 400052, 400057, 400059, 400065, 400069, 400073, 400084, 400085, 400088, + 400096, 400097, 400100, 400104, 400109, 400122, 400147, 400148, 400149, 400158, 400160, 400168, 400172, 400174, + 400178, 400185, 400201, 400206, 400209, 400213, 400221, 400222, 400227, 400236, 400238, 400240, 400246, 400253, + 400257, 400258, 400268, 400274, 400278, 400280, 400292, 400296, 400298, 400330, 400336, 400343, 400353, 400372, + 400394, 400400, 400414, 400418, 400429, 400435, 400436, 400440, 400449, 400457, 400461, 400464, 400479, 400485, + 400499, 400507, 400508, 400514, 400519, 400528, 400545, 400560, 400563, 400567, 400581, 400582, 400586, 400637, + 400643, 400648, 400649, 400654, 400664, 400665, 400668, 400673, 400677, 400687, 400688, 400690, 400700, 400709, + 400713, 400714, 400715, 400717, 400723, 400743, 400750, 400760, 400772, 400790, 400792, 400794, 400799, 400804, + 400822, 400823, 400828, 400832, 400837, 400842, 400863, 400869, 400873, 400895, 400904, 400907, 400911, 400916, + 400922, 400934, 400951, 400952, 400953, 400964, 400965, 400970, 400971, 400973, 400995, 400996, 401014, 401129, + 401154, 401163, 401167, 401210, 401224, 401327, 401351, 401388, 401391, 401400, 401403, 401440, 401457, 401464, + 401489, 401495, 401507, 401534, 401541, 401555, 401560, 401567, 401597, 401606, 401611, 401655, 401808, 401809, + 401810, 401811, 401816, 401817, 401845, 401846, 401890, 401891, 401906, 401908, 401926, 401936, 401937, 401942, + 401943, 401948, 401957, 401958, 401994, 401996, 401997, 401998, 402056, 402057, 402058, 402059, 402060, 402061, + 402067, 402117, 402118, 402119, 402120, 402121, 402281, 402282, 402283, 402284, 402285, 402286, 402287, 402288, + 402289, 402359, 402360, 402361, 402362, 402363, 402364, 402365, 402366, 402367, 402368, 402369, 402370, 402371, + 402372, 402373, 403225, 403265, 403329, 403401, 403402, 403404, 403406, 403409, 403412, 403414, 403419, 404370, + 404434, 404435, 404444, 404451, 404452, 404453, 404461, 404462, 404521, 404522, 404553, 404554, 404585, 404586, + 404640, 404753, 404759, 405613, 405619, 405701, 407150, 407151, 407152, 407153, 407155, 407157, 407161, 407165, + 407172, 407173, 407174, 407176, 407177, 407179, 407180, 407181, 407184, 407185, 407186, 407187, 407190, 407191, + 407194, 407200, 407202, 407204, 407206, 407207, 407321, 407323, 407325, 407328, 407331, 407332, 407335, 407336, + 407337, 407339, 407341, 407342, 407344, 407348, 407352, 407359, 407360, 407361, 407364, 407367, 407370, 407372, + 407373, 407374, 407710, 407711, 408907, 408911, 409524, 409525, 409526, 409528, 409529, 413026, 413845, 413877, + 413878, 414284, 414694] + + from tqdm import tqdm + dfs = [load_single_day(p, header, ids) for p in tqdm(paths)] + df = pd.concat(dfs) + df['id'] = df['Station'] + df.reset_index(drop=True, inplace=True) + df.to_csv(os.path.join(data_folder, 'pems_bay.csv')) + print("Pems dataset created") + # Construct graph + print("Constructing graph") + metafile= 'd04_text_meta_2017_01_04.txt' + meta = pd.read_csv(os.path.join(data_folder, metafile), delimiter='\t', index_col='ID') + meta = meta.loc[ids] + nodes_loc = meta.loc[:,['Latitude', 'Longitude']].values + graph = construct_graph(nodes_loc) + normalized_loc = nodes_loc - nodes_loc.min(axis=0) + normalized_loc /= normalized_loc.max(axis=0) + graph.ndata['normalized_loc'] = torch.Tensor(normalized_loc) #Used for pretty printing + pickle.dump(graph, open(os.path.join(data_folder, 'graph.bin'), 'wb')) def main(args): """Runs main download routine. @@ -374,10 +548,11 @@ def main(args): print("Download completed.") - DOWNLOAD_FUNCTIONS = { "electricity": download_electricity, "traffic": download_traffic, + "M5": download_m5, + 'pems_bay': download_PEMS_BAY, } if __name__ == "__main__": diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/xgb_util.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/xgb_util.py index d56f19824..c8e79f027 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/data/xgb_util.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/data/xgb_util.py @@ -1,4 +1,4 @@ -# Copyright 2022 NVIDIA Corporation +# Copyright 2022-2024 NVIDIA Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import pandas as pd import os @@ -34,45 +35,22 @@ def select_test_group(df, encoder, example): final.append(g[encoder-1: encoder + len(g) - example]) return pd.concat((final)) -def load_xgb_df(dest_path, features, ds_type): - ''' - Loads and does some light preprocessing on the train, valid and test. - First the csvs are read for each, then the features not present in the feature spec are dropped, - and finally the features with datatype as object are dropped. The final step is to prevent issues with - xgboost training and cuDF casting. - ''' - path = dest_path - if not isinstance(path, pd.DataFrame): - df = pd.read_csv(os.path.join(path, f"{ds_type}.csv")) - else: - df = path - all_features = [f.name for f in features] + ['_id_'] - all_read = df.columns - to_drop = [c for c in all_read if c not in all_features] - df.drop(columns=to_drop, inplace=True) - - object_columns = [c for c, d in zip(df.columns, df.dtypes) if d == "object"] - df.drop(columns=object_columns, inplace=True) +def xgb_multiID_preprocess(df, time_feat, target_feat): + target_values = [] - return df + for i, g in df.groupby("_id_"): + d = g[[time_feat, target_feat]] + d.rename(columns={target_feat: f'{target_feat}_{i}'}, inplace=True) + target_values.append(d) -def xgb_multiID_preprocess(df, features, time_series_count): - date = [feature.name for feature in features if feature.feature_type == "TIME"][0] - target = [feature.name for feature in features if feature.feature_type == "TARGET"][0] - time_series_count = time_series_count - target_values = [] - for _, g in df.groupby("_id_"): - target_values.append(g[[date, target]]) + # faster than calling functools.reduce final = target_values[0] - final.rename(columns={target: f'{target}_{0}'}, inplace=True) - for i in range(1, time_series_count): - target_values[i].rename(columns={target: f'{target}_{i}'}, inplace=True) - final = final.merge(target_values[i], on=date, how='outer') + for t in target_values[1:]: + final = final.merge(t, on=time_feat, how='outer') - df = df.merge(final, on=date, how='outer') + df = df.merge(final, on=time_feat, how='outer') return df - def feat_adder(df, lag_feats, rolling_feats): ''' Main data preprocessing function for xgboost. lag_feats and rolling_feats are both @@ -113,4 +91,4 @@ def target_shift(df, target, feat, i): in_feat = target + feat out_feat = [f'{i}_target' for i in in_feat] df[out_feat] = df.groupby("_id_")[in_feat].shift(-1 * (i+1)) - return df \ No newline at end of file + return df diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_utils.py index bb8d1c7f2..70ca495a3 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 import os import random @@ -26,6 +27,7 @@ from hydra.core.hydra_config import HydraConfig from joblib.externals.loky.backend.context import get_context + def generate_seeds(rng, size): """ Generate list of random seeds @@ -51,7 +53,6 @@ def broadcast_seeds(seeds, device): seeds = seeds_tensor.tolist() return seeds - def setup_seeds(master_seed, epochs, device): """ Generates seeds from one master_seed. @@ -137,16 +138,19 @@ def is_main_process(): def init_parallel(): if is_parallel(): - torch.cuda.set_device(HydraConfig.get().job.num % torch.cuda.device_count()) + device_id = conf['device_id'] if 'device_id' in (conf := HydraConfig.get()) else conf.job.num % torch.cuda.device_count() + torch.cuda.set_device(device_id) + def is_parallel(): - return HydraConfig.get().launcher.get('n_jobs', 0) > 1 or HydraConfig.get().sweeper.get('n_jobs', 0) > 1 + return HydraConfig.get().launcher.get('n_jobs', 0) > 1 or \ + HydraConfig.get().launcher.get('max_workers', 0) > 1 or \ + HydraConfig.get().launcher.get('processes', 0) > 1 or \ + HydraConfig.get().sweeper.get('n_jobs', 0) > 1 def get_mp_context(): - if HydraConfig.get().launcher.get('n_jobs', 0) > 1 or HydraConfig.get().sweeper.get('n_jobs', 0) > 1: - return get_context('loky') - return None + return get_context('loky') def _pynvml_mem_size(kind="total", index=0): @@ -195,7 +199,7 @@ def calculate_frac(num_rows, num_feat, world_size): def create_client(config): - device_pool_frac = config.cluster.device_pool_frac + device_pool_frac = config.cluster.device_pool_frac # allocate 80% of total GPU memory on each GPU device_size = device_mem_size(kind="total") device_pool_size = int(device_pool_frac * device_size) dask_space = "/tmp/dask_space/" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluation_metrics.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluation_metrics.py index 02b647f12..ea375e17e 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluation_metrics.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluation_metrics.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,10 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 import sys import numpy as np from abc import ABC, abstractmethod +from numba import jit, prange class AbstractMetric(ABC): @@ -24,6 +26,86 @@ class AbstractMetric(ABC): def __call__(pred, label, weights): pass + +class TemporalDistortionIndex(AbstractMetric): + name = "TDI" + + @staticmethod + @jit(nopython=True, parallel=True) + def _calculate_tdi(X, Y): + """Calculate TDI scores + + Parameters + ---------- + X: np.ndarray + 2D array with shape (B x seq_len) of predictions + Y: np.ndarray + 2D array with shape (B x seq_len) of labels + + Returns + ------- + np.ndarray + tdi scores for each example + """ + + batch_size, n = X.shape + tdis = np.full(batch_size, 0, dtype=np.float64) + for tidx in prange(batch_size): + d = np.abs(X[tidx].reshape(-1, 1) - Y[tidx]) + dist_matrix = np.ones((n, 2), dtype=np.float64) * np.inf + step_matrix = np.full((n, n), -1, dtype=np.int8) + + dist_matrix[:, 0] = np.cumsum(d[:, 0]) + step_matrix[0, 1:] = 1 + step_matrix[1:, 0] = 2 + pattern_cost = np.ones(3, dtype=np.float64) + + for j in range(1, n): + dist_matrix[0, j%2] = dist_matrix[0, (j-1)%2] + d[0, j] + for i in range(1, n): + # modulo operator is used to avoid copying memory + # from column 1 to column 0 at the end of iteration (traid memops for ops) + #diagonal + pattern_cost[0] = dist_matrix[i-1, (j-1)%2] + d[i, j] * 2 + #left + pattern_cost[1] = dist_matrix[i, (j-1)%2] + d[i, j] + #up + pattern_cost[2] = dist_matrix[i-1, j%2] + d[i, j] + + step = np.argmin(pattern_cost) + dist_matrix[i, j%2] = pattern_cost[step] + step_matrix[i, j] = step + tdi = 0.0 + y = 0.0 + dx = 0 + dy = 0 + step = -1 + i = n-1 + j = n-1 + while i != 0 or j != 0: + step = int(step_matrix[i, j]) + if i < 0 or j < 0:break + dx = int((step == 0) + 1) + dy = int((step == 2) - (step == 1)) + tdi += abs(y + float(dy) / 2) * float(dx) + y = y + dy + i -= int((dx + dy) / 2) + j -= int((dx - dy) / 2) + tdis[tidx] = tdi + return tdis + + + @staticmethod + def __call__(pred, label, weights): + if weights.size: + print('Weights are not supported for TDI metric', file=sys.stderr) + normalizer = (pred.shape[1]-1)**2 + if not pred.flags['C_CONTIGUOUS']: + pred = np.ascontiguousarray(pred) + tdi = np.mean(TemporalDistortionIndex._calculate_tdi(pred, label)) / normalizer + return tdi + + class SMAPE(AbstractMetric): name = "SMAPE" @@ -31,8 +113,10 @@ class SMAPE(AbstractMetric): def __call__(preds, labels, weights): if not weights.size: weights = None - return 100 * np.average(2 * np.abs(preds - labels) / (np.abs(labels) + np.abs(preds)), weights=weights) - + a = 2 * np.abs(preds - labels) + b = np.abs(labels) + np.abs(preds) + b[b == 0] = 1 # numerator for this values is also 0 anyway + return 100 * np.average(a / b, weights=weights) def normalised_quantile_loss(y_pred, y, quantile, weights=None): @@ -66,6 +150,7 @@ class P90_loss(AbstractMetric): def __call__(labels, preds, weights): return normalised_quantile_loss(labels, preds, 0.9,weights) + # Normalized Deviation class ND(AbstractMetric): name = "ND" @@ -163,4 +248,5 @@ def __call__(preds, labels, weights, return_individual=False): "RMSE": RMSE, "R_Squared": R_Squared, "ND": ND, + "TDI": TemporalDistortionIndex } diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluator.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluator.py index 15425ddfa..410809d7f 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluator.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/evaluator.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,28 +12,53 @@ # See the License for the specific language governing permissions and # limitations under the License. +import sys import pickle from abc import ABC +import warnings import dgl import numpy as np +import pandas as pd import torch from data.datasets import get_collate_fn -from distributed_utils import get_mp_context +from models.interpretability import InterpretableModelBase from torch.utils.data import DataLoader from training.utils import to_device +from distributed_utils import get_mp_context +from data.data_utils import DTYPE_MAP from .evaluation_metrics import METRICS -import pandas as pd + +from typing import List, Callable + + +class Postprocessor: + """ + PoC class used for simple transformations like rounding or clipping + """ + def __init__(self, transformations: List[Callable[[torch.Tensor], torch.Tensor]]): + self._transformations = transformations + + def __call__(self, x): + return self.transform(x) + + def transform(self, x): + for t in self._transformations: + x = t(x) + return x class MetricEvaluator(ABC): - def __init__(self, config): + def __init__(self, config, postprocessor=None, scaler="scalers"): self.output_selector = config.get("output_selector", None) + self.per_step_metrics = config.get("per_step_metrics", False) + self.save_predictions = config.get("save_predictions", False) self.metrics = [] preprocessor_state = pickle.load(open(config.preprocessor_state_path, "rb")) - self.scalers = preprocessor_state["scalers"] - self.save_predictions = config.get("save_predictions", False) + self.postprocessor = postprocessor + self.scalers = preprocessor_state[scaler] + self.time_embed_dtype = preprocessor_state.get("timestamp_embed_type") self.example_history = [] for name in config.metrics: @@ -45,73 +70,113 @@ def __init__(self, config): def predict(self, *args, **kwargs): raise NotImplementedError - def save_preds(self, preds, ids): - all_examples = self.example_history - all_examples = all_examples.transpose(2,0,1).reshape(-1, all_examples.shape[1]) + def save_preds(self, preds, ids, timestamps): + all_examples = self.example_history # make this a separate function in each eval + if len(all_examples.shape) == 4: # MultiID case + all_examples = all_examples.transpose(2,0,1,3).reshape(-1, all_examples.shape[1]) + elif len(all_examples.shape) == 3: + all_examples = all_examples.transpose(2, 0, 1).reshape(-1, all_examples.shape[1]) if len(preds.shape) == 4: tgt_ords = np.arange(preds.shape[2]).repeat(preds.shape[0]) tgt_ords = pd.DataFrame(tgt_ords, columns=['#target']) - preds = preds.transpose(2,0,1,3).reshape(-1,preds.shape[1], preds.shape[3]) + preds = preds.transpose(2, 0, 1, 3).reshape(-1, preds.shape[1], preds.shape[3]) ids = ids.transpose().reshape(-1) else: tgt_ords = None + all_examples = self.scalers.inverse_transform_targets(all_examples, ids) - hist_df = pd.DataFrame(all_examples, columns=[f't{i+1}' for i in range(-self.config.encoder_length, 0)]) + hist_df = pd.DataFrame(all_examples, columns=[f't{i + 1}' for i in range(-self.config.encoder_length, 0)]) ids = pd.DataFrame(ids, columns=['id']) + timestamps = pd.DataFrame(timestamps, columns=['timestamp']) col_labels = [f'Estimator{j}_t{i:+}' for j in range(preds.shape[2]) for i in range(preds.shape[1])] - preds_df = pd.DataFrame(preds.reshape(preds.shape[0],-1, order='F'), columns=col_labels) - df = pd.concat([ids, tgt_ords, hist_df, preds_df], axis=1) + preds_df = pd.DataFrame(preds.reshape(preds.shape[0], -1, order='F'), columns=col_labels) + df = pd.concat([ids, timestamps, tgt_ords, hist_df, preds_df], axis=1) df.to_csv('predictions.csv') - def evaluate(self, preds, labels, ids, weights): - results = {} - - # In multi target case we treat each target as a separate example. - # Then we can reduce it to a single target case setting BS = prev_BS * num_targets - if len(preds.shape) == 4: - if self.scalers.scale_per_id: - ids = np.arange(preds.shape[-2]) - ids = np.repeat(ids, preds.shape[0]) - else: - ids = None - # TODO: this causes a memory movement. Rewrite this with views! - preds = np.concatenate([preds[:, :, i] for i in range(preds.shape[-2])], axis=0) - labels = np.concatenate([labels[:, :, i] for i in range(labels.shape[-1])], axis=0) - weights = np.concatenate([weights[:, :, i] for i in range(weights.shape[-1])], axis=0) - elif len(preds.shape) == 3: + def transpose_preds(self, preds, labels, ids, weights, timestamps): + """ + This fuction reshapes all legal shapes into num_examples x time x num_estimators + """ + if labels.shape[-1] == 1: labels = labels.squeeze(-1) + if weights.size and weights.shape[-1] == 1: + weights = weights.squeeze(-1) + + # preds: BS x T x ID x F x H + # labels: BS x T x ID x F + # ids: BS x ID + if len(preds.shape) == 5: + assert ids is not None + ids = ids.transpose(1,0).flatten().repeat(preds.shape[3]) + preds = preds.transpose(2,3,0,1,4) + labels = labels.transpose(2,3,0,1) if weights.size: - weights = weights.squeeze(-1) - else: - raise ValueError("Expected shape of predictions is either BSxTxFxH or BSxTxH") + weights = weights.transpose(2,3,0,1) + + # preds: BS x T x ID x H or BS x T x F x H, it should be processed in the same way + # labels: BS x T x ID + # ids: BS x ID + elif len(preds.shape) == 4: + ids = ids.transpose(1,0).flatten() if ids is not None else None + timestamps = timestamps.transpose(1,0).flatten() if timestamps is not None else None + preds = preds.transpose(2,0,1,3) + labels = labels.transpose(2,0,1) + if weights.size: + weights = weights.transpose(2,0,1) + + elif len(preds.shape) != 3: + raise ValueError("Predictions are expected to have 3, 4 or 5 dimensions") + + if len(preds.shape) > 3: + preds = preds.reshape(-1, *preds.shape[2:]) + labels = labels.reshape(-1, labels.shape[-1]) + if weights.size: + weights = weights.reshape(-1, *weights.shape[2:]) + + return preds, labels, ids, weights, timestamps + + def evaluate(self, preds, labels, ids, weights, timestamps, unscale=True): - upreds = np.stack([self.scalers.inverse_transform_targets(preds[..., i], ids) for i in range(preds.shape[-1])], - axis=-1) - labels = self.scalers.inverse_transform_targets(labels, ids) + if unscale: + print('Deprecation warning: Target unscaling will be moved from the evaluate function to the predict function', file=sys.stderr) + preds = self.scalers.inverse_transform_targets(preds, ids) + labels = self.scalers.inverse_transform_targets(labels, ids) + upreds, labels, ids, weights, timestamps = self.transpose_preds(preds, labels, ids, weights, timestamps) + if self.save_predictions: - self.save_preds(upreds, ids) + self.save_preds(upreds, ids, timestamps) + results = {} for metric in self.metrics: selector = getattr(metric, 'selector', self.output_selector) preds = upreds[..., selector] - results[metric.name] = metric(preds, labels, weights) if np.all(np.isfinite(preds)) else np.NaN - results = {k: float(v) for k, v in results.items()} + m = metric(preds, labels, weights) if np.all(np.isfinite(preds)) else np.NaN + results[metric.name] = float(m) + if self.per_step_metrics: + if metric.name == 'TDI': # The only metric that requires whole time series to be computed + continue + results[metric.name + '@step'] = [] + for i in range(preds.shape[-1]): + m = metric(preds[..., i:i+1], labels[..., i:i+1], weights[..., i:i+1]) if np.all(np.isfinite(preds[..., i:i+1])) else np.NaN + results[metric.name + '@step'].append(float(m)) return results class CTLMetricEvaluator(MetricEvaluator): - def __init__(self, test_data, config): - super().__init__(config) + def __init__(self, test_data, config, postprocessor=None): + super().__init__(config, postprocessor) self.device = config.device + self.visualisation_indices = config.get("visualisation_indices", None) + + mp_context = get_mp_context() if config.num_workers else None if test_data is not None: - mp_context = get_mp_context() self.dataloader = DataLoader( test_data, batch_size=self.config.batch_size, - num_workers=1, + num_workers=config.num_workers, pin_memory=True, collate_fn=get_collate_fn(config.model_type, config.encoder_length, test=True), multiprocessing_context=mp_context @@ -122,18 +187,30 @@ def __init__(self, test_data, config): def prep_data(self, batch): ids = batch.ndata['id'] if isinstance(batch, dgl.DGLGraph) else batch["id"] ids = ids[:, 0, ...] # Shape BS x T x F [x H] + + timestamp = batch.ndata['timestamp'] if isinstance(batch, dgl.DGLGraph) else batch["timestamp"] + timestamp = timestamp[:, 0, ...] + weights = batch.ndata['weight'] if isinstance(batch, dgl.DGLGraph) else batch['weight'] weights = weights[:, self.config.encoder_length:, :] if weights is not None and weights.numel() else torch.empty(0) + batch = to_device(batch, device=self.device) - return batch, weights, ids + return batch, weights, ids, timestamp def predict(self, model, dataloader=None): + self.device = next(model.parameters()).device + if not dataloader: dataloader = self.dataloader assert dataloader is not None, "Dataloader cannot be None, either pass in a valid dataloader or \ initialize evaluator with valid test_data" + + if self.visualisation_indices is not None: + assert isinstance(model, InterpretableModelBase), "Visualisation is only possible for interpretable models" + model.enable_activations_dump() + test_method_name = 'predict' if hasattr(model, "predict") else '__call__' test_method = getattr(model, test_method_name) @@ -145,32 +222,74 @@ def predict(self, model, dataloader=None): labels_full = [] weights_full = [] ids_full = [] + timestamps_full = [] + figures_full = [] for i, (batch, labels, _) in enumerate(dataloader): if self.save_predictions: - self.example_history.append(batch['target'][:,:self.config.encoder_length].detach().cpu()) - batch, weights, ids = self.prep_data(batch) + batch_data = batch.ndata if isinstance(batch, dgl.DGLGraph) else batch + self.example_history.append(batch_data['target'][:, :self.config.encoder_length].detach().cpu()) + batch, weights, ids, timestamp = self.prep_data(batch) labels_full.append(labels) weights_full.append(weights) preds = test_method(batch) ids_full.append(ids) preds_full.append(preds) + timestamps_full.append(timestamp) + + if self.visualisation_indices is not None: + current_indices = [sample_number for sample_number in self.visualisation_indices if + i * self.config.batch_size <= sample_number < (i + 1) * self.config.batch_size] + for sample_number in current_indices: + activations = model.get_activations(sample_number % self.config.batch_size, + dataloader.dataset.features) + for name, fig in activations.items(): + figures_full.append((fig, name, sample_number)) preds_full = torch.cat(preds_full, dim=0).cpu().numpy() labels_full = torch.cat(labels_full, dim=0).cpu().numpy() weights_full = torch.cat(weights_full).cpu().numpy() ids_full = torch.cat(ids_full).cpu().numpy() + + timestamps_full = torch.cat(timestamps_full).cpu().numpy() + if self.save_predictions: self.example_history = torch.cat(self.example_history, dim=0).cpu().numpy() - return preds_full, labels_full, ids_full, weights_full + + preds_full = self.scalers.inverse_transform_targets(preds_full, ids_full) + if self.postprocessor is not None: + preds_full = self.postprocessor(preds_full) + labels_full = self.scalers.inverse_transform_targets(labels_full, ids_full) + + timestamps_full = timestamps_full.astype(DTYPE_MAP[self.time_embed_dtype]) + + predictions_dict = { + 'preds_full': preds_full, + 'labels_full': labels_full, + 'ids_full': ids_full, + 'weights_full': weights_full, + 'timestamps_full': timestamps_full + } + + if figures_full: + predictions_dict['figures_full'] = figures_full + + return predictions_dict + + def evaluate(self, preds, labels, ids, weights, timestamps): + # This function is part of a rework aimed to move unscaling to the predict function + # It should be removed in the future + return super().evaluate(preds, labels, ids, weights, timestamps, unscale=False) class StatMetricEvaluator(MetricEvaluator): - def __init__(self, test_data, config): - super().__init__(config) + def __init__(self, test_data, config, postprocessor=None): + super().__init__(config, postprocessor, scaler="alt_scalers") self.dataloader = test_data + self.dataloader.test = True + def predict(self, model, dataloader=None): dataloader = dataloader or self.dataloader @@ -181,13 +300,16 @@ def predict(self, model, dataloader=None): weights_full = [] ids_full = [] - for i, test_batch in enumerate(dataloader): - labels = test_batch["endog"] - ids = test_batch["id"].iloc[0] - preds = np.array(model.predict(test_batch["exog"], i)) + for test_example in dataloader: + labels = test_example["endog"] + id = test_example['id'] + preds = np.array(model.predict(test_example)) labels_full.append(labels) - weights_full.append(test_batch.get('weight', [])) - ids_full.append(ids) + weights_full.append( + weights + if (weights := test_example['weight']).shape[-1] else [] + ) + ids_full.append(id) preds_full.append(preds) preds_full = np.stack(preds_full) @@ -196,13 +318,39 @@ def predict(self, model, dataloader=None): ids_full = np.stack(ids_full) if len(preds_full.shape) == 2: preds_full = preds_full[:, :, np.newaxis] - return preds_full, labels_full, ids_full, weights_full + + preds_full = self.scalers.inverse_transform_targets(preds_full, ids_full) + if self.postprocessor is not None: + preds_full = self.postprocessor(preds_full) + labels_full = self.scalers.inverse_transform_targets(labels_full, ids_full) + + + predictions_dict = { + 'preds_full': preds_full, + 'labels_full': labels_full, + 'ids_full': ids_full, + 'weights_full': weights_full + } + + return predictions_dict + + def evaluate(self, preds, labels, ids, weights, timestamps): + return super().evaluate(preds, labels, ids, weights, timestamps, unscale=False) + + def save_preds(self, preds, ids, timestamps): + ids = pd.DataFrame(ids, columns=['id']) + timestamps = pd.DataFrame(timestamps, columns=['timestamp']) + col_labels = [f'Estimator{j}_t{i:+}' for j in range(preds.shape[2]) for i in range(preds.shape[1])] + preds_df = pd.DataFrame(preds.reshape(preds.shape[0], -1, order='F'), columns=col_labels) + df = pd.concat([ids, timestamps, preds_df], axis=1) + df.to_csv('predictions.csv') class XGBMetricEvaluator(MetricEvaluator): - def __init__(self, test_data, config): - super().__init__(config) + def __init__(self, test_data, config , postprocessor=None): + super().__init__(config, postprocessor) self.dataloader = test_data + self.dataloader.test = True def predict(self, model, dataloader=None): dataloader = dataloader or self.dataloader @@ -231,4 +379,31 @@ def predict(self, model, dataloader=None): windows_labels = np.lib.stride_tricks.sliding_window_view(labels_all, self.dataloader.example_length) self.example_history.append(windows_labels.copy()[:, :self.dataloader.encoder_length]) self.example_history = np.concatenate(self.example_history, axis=0)[:, :, np.newaxis] - return outtemp, labels_temp, ids_temp, np.stack(weights) + + preds_full = self.scalers.inverse_transform_targets(outtemp, ids_temp) + if self.postprocessor is not None: + preds_full = self.postprocessor(preds_full) + labels_full = self.scalers.inverse_transform_targets(labels_temp, ids_temp) + + predictions_dict = { + 'preds_full': preds_full, + 'labels_full': labels_full, + 'ids_full': ids_temp, + 'weights_full': np.stack(weights) + } + + return predictions_dict + + def evaluate(self, preds, labels, ids, weights, timestamps): + return super().evaluate(preds, labels, ids, weights, timestamps, unscale=False) + + +def unpack_predictions(predictions_dict): + preds = predictions_dict.get('preds_full', None) + labels = predictions_dict.get('labels_full', None) + ids = predictions_dict.get('ids_full', None) + weights = predictions_dict.get('weights_full', None) + timestamps = predictions_dict.get('timestamps_full', None) + figures = predictions_dict.get('figures_full', None) + + return preds, labels, ids, weights, timestamps, figures diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/triton_evaluator.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/triton_evaluator.py index 2eb9f8d84..26a700080 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/triton_evaluator.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/evaluators/triton_evaluator.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -79,7 +79,14 @@ def predict(self, dataloader, model_name, server_url="localhost:8001"): if self.save_predictions: self.example_history = np.concatenate(self.example_history, axis=0) - return preds_full, labels_full, ids_full, weights_full + predictions_dict = { + 'preds_full': preds_full, + 'labels_full': labels_full, + 'ids_full': ids_full, + 'weights_full': weights_full + } + + return predictions_dict def predict_xgboost(self, dataloader, max_batch_size, server_url="localhost:8001"): grpc_client = triton_grpc.InferenceServerClient( @@ -132,4 +139,12 @@ def predict_xgboost(self, dataloader, max_batch_size, server_url="localhost:8001 windows_labels = np.lib.stride_tricks.sliding_window_view(labels_all, dataloader.example_length) self.example_history.append(windows_labels.copy()[:, :dataloader.encoder_length]) self.example_history = np.concatenate(self.example_history, axis=0)[:, :, np.newaxis] - return outtemp, labels_temp, ids_temp[:,0], np.stack(weights) + + predictions_dict = { + 'preds_full': outtemp, + 'labels_full': labels_temp, + 'ids_full': ids_temp[:,0], + 'weights_full': np.stack(weights) + } + + return predictions_dict diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/ensembling.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/ensembling.sh new file mode 100644 index 000000000..85d77df42 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/ensembling.sh @@ -0,0 +1,62 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -x +set -e +: ${MODEL:=nbeats} +: ${DATASET:=electricity} +: ${ORDER:=3} +: ${SUFFIX:=best_0} +: ${RESULTS:='/results'} + + +RESULTS=${RESULTS}/${MODEL}_${DATASET}_${SUFFIX}_checkpoints + +python launch_training.py \ + -m \ + seed="range(1,$(( 2 ** ${ORDER} + 1)))" \ + model=${MODEL} \ + dataset=${DATASET} \ + overrides=${DATASET}/${MODEL}/${SUFFIX} \ + trainer.config.log_interval=-1 \ + ~trainer.callbacks.early_stopping \ + +trainer.config.force_rerun=True \ + evaluator.config.metrics=[MAE,RMSE,SMAPE,TDI] \ + hydra.sweep.dir=${RESULTS} \ + hydra/launcher=joblib \ + hydra.launcher.n_jobs=8 \ + hydra.sweeper.max_batch_size=8 + +rm ${RESULTS}/*/last_checkpoint.zip + +# Iterate over orders of magnitude +for J in $( seq 1 ${ORDER} ) +do + export WANDB_RUN_GROUP="${MODEL}_${DATASET}_ensembling_$(( 2 ** $J ))_${SUFFIX}" + # For each order of magnitude split available checkpoint into 2^(order-J) disjoint sets and compute results on these to reduce variance + for SHIFT in $( seq 0 $(( 2 ** $J )) $(( 2 ** ${ORDER} - 1))) + do + + MODEL_LIST="[" + for I in $( seq 0 $(( 2 ** $J - 1)) ) + do + MODEL_LIST+="{dir: ${RESULTS}/$(( $I + $SHIFT )), checkpoint: best_checkpoint.zip, weight:1.0}," + done + MODEL_LIST=${MODEL_LIST::-1} + MODEL_LIST+="]" + + python launch_ensembling.py \ + model.config.model_list="${MODEL_LIST}" + done +done diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/example_multiprocessing_launcher.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/example_multiprocessing_launcher.sh new file mode 100644 index 000000000..04bead063 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/example_multiprocessing_launcher.sh @@ -0,0 +1,45 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# More info here: https://hydra.cc/docs/plugins/optuna_sweeper/ +: ${DATASET:=electricity} +RESULTS=/ws/tft_${DATASET}_hp_search +mkdir -p ${RESULTS} + +python launch_training.py \ + -m \ + 'model.config.n_head=choice(1,2)' \ + 'model.config.hidden_size=choice(96,128)' \ + 'model.config.dropout=interval(0,0.5)' \ + 'trainer.optimizer.lr=tag(log, interval(1e-5, 1e-2))' \ + 'trainer.config.ema=choice(true, false)' \ + '+trainer.config.ema_decay=interval(0.9, 0.9999)' \ + model=tft \ + dataset=${DATASET} \ + trainer/criterion=quantile \ + trainer.config.batch_size=1024 \ + trainer.config.num_epochs=10 \ + trainer.config.log_interval=-1 \ + trainer.config.mlflow_store="file://${RESULTS}/mlruns" \ + evaluator.config.metrics=[MAE,RMSE,SMAPE,TDI] \ + hydra/sweeper=optuna \ + +optuna_objectives=[MAE,RMSE,SMAPE,TDI] \ + hydra.sweeper.direction=[minimize,minimize,minimize,minimize] \ + hydra.sweeper.n_trials=8 \ + hydra.sweeper.experiment_sequence=hydra_utils.TSPPOptunaExperimentSequence \ + hydra.launcher.n_jobs=4 \ + hydra.sweeper.storage="sqlite:///${RESULTS}/hp_search_multiobjective.db" \ + hydra.sweeper.study_name="tft_${DATASET}_1GPU" \ + hydra/launcher=multiprocessing \ + hydra.sweep.dir='/results/${now:%Y-%m-%d}/${now:%H-%M-%S}' diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search.sh index 3ec2c4b3e..54dd099df 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search.sh @@ -1,4 +1,4 @@ -/# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,20 +12,39 @@ # See the License for the specific language governing permissions and # limitations under the License. -# More info here: https://hydra.cc/docs/plugins/optuna_sweeper/ +set -x +set -e + +: ${MODEL:=nbeats} +: ${DATASET:=electricity} +: ${SUFFIX:=} +: ${DISTRIBUTED:=0} + +RESULTS=/results/${MODEL}_${DATASET}_hp_search${SUFFIX} +mkdir -p ${RESULTS} + +if [[ ${DISTRIBUTED} == 0 ]] +then + LAUNCHER='hydra.sweeper.experiment_sequence=hydra_utils.TSPPOptunaExperimentSequence ' + LAUNCHER+='hydra/launcher=multiprocessing ' + LAUNCHER+='hydra.launcher.n_jobs=8' +else + LAUNCHER='hydra/launcher=torchrun ' +fi + python launch_training.py \ - -m \ - 'model.config.n_head=choice(1,2,4)' \ - 'trainer.optimizer.lr=tag(log, interval(1e-5, 1e-2))' \ - model=tft \ - dataset=electricity \ - trainer/criterion=quantile \ - trainer.config.batch_size=1024 \ - trainer.config.num_epochs=2 \ + -m \ + model=${MODEL} \ + dataset=${DATASET} \ + overrides=${DATASET}/${MODEL}/hp_search${SUFFIX} \ trainer.config.log_interval=-1 \ - "evaluator.config.metrics=[P50, P90, MAE, MSE]" \ - +optuna_objectives=[P50] \ - hydra/sweeper=optuna \ - hydra.sweeper.n_trials=3 \ - hydra.sweeper.n_jobs=1 \ - hydra.sweeper.storage=sqlite:////workspace/hp_search_multiobjective.db + +trainer.config.force_rerun=True \ + ~trainer.callbacks.save_checkpoint \ + evaluator.config.metrics=[MAE,RMSE] \ + hydra/sweeper=optuna \ + +optuna_objectives=[MAE,RMSE] \ + hydra.sweeper.direction=[minimize,minimize] \ + hydra.sweeper.n_trials=16 \ + hydra.sweeper.storage="sqlite:///${RESULTS}/hp_search_multiobjective.db" \ + hydra.sweeper.study_name="${MODEL}_${DATASET}_DIST_${DISTRIBUTED}" \ + ${LAUNCHER} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_distributed.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_distributed.sh index f9efb5c04..cc703008b 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_distributed.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_distributed.sh @@ -1,4 +1,4 @@ -/# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,18 +13,19 @@ # limitations under the License. # More info here: https://hydra.cc/docs/plugins/optuna_sweeper/ + python launch_training.py \ -m \ 'model.config.n_head=choice(1,2,4)' \ 'trainer.optimizer.lr=tag(log, interval(1e-5, 1e-2))' \ model=tft \ - dataset=electricity \ - trainer/criterion=quantile \ - trainer.config.batch_size=1024 \ - trainer.config.num_epochs=2 \ + dataset=${DATASET} \ + trainer/criterion=quantile \ + trainer.config.batch_size=1024 \ + trainer.config.num_epochs=2 \ trainer.config.log_interval=100 \ - +optuna_objectives=[P50] \ - hydra/sweeper=optuna \ - hydra.sweeper.n_trials=4 \ - hydra.sweeper.n_jobs=1 \ - hydra/launcher=torchrun + +optuna_objectives=[P50] \ + hydra/sweeper=optuna \ + hydra.sweeper.n_trials=4 \ + hydra/launcher=torchrun \ + hydra.launcher.nproc_per_node=8 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_multiobjective.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_multiobjective.sh index 17d0f8687..0c10ceb8b 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_multiobjective.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_multiobjective.sh @@ -1,4 +1,4 @@ -/# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,4 +27,5 @@ python launch_training.py \ hydra/sweeper=optuna \ hydra.sweeper.direction=[minimize,minimize] \ hydra.sweeper.n_trials=3 \ - hydra.sweeper.n_jobs=1 \ + hydra/launcher=joblib \ + hydra.launcher.n_jobs=1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_parallel.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_parallel.sh index 4ad1f3611..1af7e5534 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_parallel.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/hp_search_parallel.sh @@ -1,4 +1,4 @@ -/# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,5 +27,5 @@ python launch_training.py \ +optuna_objectives=[P50] \ hydra/sweeper=optuna \ hydra.sweeper.n_trials=16 \ - hydra.sweeper.n_jobs=8 \ + hydra.launcher.n_jobs=8 \ hydra/launcher=joblib diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/scheduler/plateau.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/interpretability.sh similarity index 60% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/conf/scheduler/plateau.yaml rename to Tools/PyTorch/TimeSeriesPredictionPlatform/examples/interpretability.sh index fe71d748e..30b33c0c3 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/conf/scheduler/plateau.yaml +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/interpretability.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -config: - scheduler: - _target_: torch.optim.lr_scheduler.ReduceLROnPlateau +: ${DATASET:=electricity} + +TFT_SCRIPTING=1 python launch_training.py \ + dataset=${DATASET} \ + model=tft \ + trainer/criterion=quantile \ + trainer.config.batch_size=1024 \ + +evaluator.config.visualisation_indices='[1, 1025, 1026, 2048]' diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/seed_sweep.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/seed_sweep.sh index b8d7af88b..c9cc4d05c 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/seed_sweep.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/seed_sweep.sh @@ -1,4 +1,4 @@ -/# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/tft_electricity_inference.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/tft_electricity_inference.sh deleted file mode 100644 index bc9b6157d..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/examples/tft_electricity_inference.sh +++ /dev/null @@ -1,23 +0,0 @@ -/# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -echo "Ensure the docker container has been started the correct way following the instructions in the README, in addition the mount to the outputs directory needs to be passed in." -PATH_TSPP=${1:-"$WORKDIR"} #Path to tspp directory outside of Docker so /home/usr/time-series-benchmark/ instead of /workspace/ -python launch_training.py model=tft dataset=electricity trainer/criterion=quantile trainer.config.num_epochs=1 +trainer.config.force_rerun=True hydra.run.dir=/workspace/outputs/0000-00-00/00-00-00/ -python launch_inference.py checkpoint=/workspace/outputs/0000-00-00/00-00-00/ -cd ${PATH_TSPP} -python launch_triton_configure.py deployment/convert=trt checkpoint=${PATH_TSPP}/outputs/0000-00-00/00-00-00/ -python launch_inference_server.py checkpoint=${PATH_TSPP}/outputs/0000-00-00/00-00-00/ -python launch_inference.py inference=triton checkpoint=${PATH_TSPP}/outputs/0000-00-00/00-00-00/ -docker stop trt_server_cont diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/LICENSE b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/LICENSE similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/LICENSE rename to Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/LICENSE diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/MIT_LICENSE b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/MIT_LICENSE similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/MIT_LICENSE rename to Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/MIT_LICENSE diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/hydra_plugins/_core.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/hydra_plugins/hydra_torchrun_launcher/_core.py similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/hydra_plugins/_core.py rename to Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/hydra_plugins/hydra_torchrun_launcher/_core.py diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/hydra_plugins/config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/hydra_plugins/hydra_torchrun_launcher/config.py similarity index 88% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/hydra_plugins/config.py rename to Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/hydra_plugins/hydra_torchrun_launcher/config.py index 67670daac..8d62ba1b1 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/hydra_plugins/config.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/hydra_plugins/hydra_torchrun_launcher/config.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ @dataclass class LauncherConfig: _target_: str = ( - "hydra_plugins.distributed_launcher.TorchDistributedLauncher" + "hydra_plugins.hydra_torchrun_launcher.distributed_launcher.TorchDistributedLauncher" ) min_nodes: int = 1 max_nodes: int = 1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/hydra_plugins/distributed_launcher.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/hydra_plugins/hydra_torchrun_launcher/distributed_launcher.py similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/hydra_plugins/distributed_launcher.py rename to Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/hydra_plugins/hydra_torchrun_launcher/distributed_launcher.py diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/setup.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/setup.py similarity index 100% rename from Tools/PyTorch/TimeSeriesPredictionPlatform/distributed_launcher/setup.py rename to Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/distributed_launcher/setup.py diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/MANIFEST.in b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/MANIFEST.in new file mode 100644 index 000000000..580709b13 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/MANIFEST.in @@ -0,0 +1,3 @@ +global-exclude *.pyc +global-exclude __pycache__ +recursive-include hydra_plugins/* *.yaml py.typed diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/NEWS.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/NEWS.md new file mode 100644 index 000000000..ea7925479 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/NEWS.md @@ -0,0 +1,18 @@ +1.2.0 (2022-05-17) +====================== + +### Features + +- Support for Python 3.10 ([#1856](https://github.com/facebookresearch/hydra/issues/1856)) + + +1.1.2 (2021-03-30) +================== + +### Features + +- Support Python 3.9 . ([#1062](https://github.com/facebookresearch/hydra/issues/1062)) + +### Maintenance Changes + +- Pin Hydra 1.0 plugins to hydra-core==1.0.* to discourage usage with Hydra 1.1 ([#1501](https://github.com/facebookresearch/hydra/issues/1501)) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/README.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/README.md new file mode 100644 index 000000000..23ae138c8 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/README.md @@ -0,0 +1,4 @@ +# Hydra Joblib Launcher +Provides a [`Joblib.Parallel`](https://joblib.readthedocs.io/en/latest/parallel.html) based Hydra Launcher supporting parallel execution. + +See [website](https://hydra.cc/docs/plugins/joblib_launcher) for more information diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/example/config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/example/config.yaml new file mode 100644 index 000000000..60bacddbb --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/example/config.yaml @@ -0,0 +1,9 @@ +defaults: + - override hydra/launcher: joblib + +task: 1 + +hydra: + launcher: + # override the number of jobs for joblib + n_jobs: 10 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/example/my_app.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/example/my_app.py new file mode 100644 index 000000000..b39236a19 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/example/my_app.py @@ -0,0 +1,20 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import logging +import os +import time + +import hydra +from omegaconf import DictConfig + +log = logging.getLogger(__name__) + + +@hydra.main(config_name="config") +def my_app(cfg: DictConfig) -> None: + log.info(f"Process ID {os.getpid()} executing task {cfg.task} ...") + + time.sleep(1) + + +if __name__ == "__main__": + my_app() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/__init__.py new file mode 100644 index 000000000..678b5f3c1 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved + +__version__ = "1.2.0" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/_core.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/_core.py new file mode 100644 index 000000000..88dd632cc --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/_core.py @@ -0,0 +1,155 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import logging +from pathlib import Path +from typing import Any, Dict, Union, List, Sequence + +from hydra.core.hydra_config import HydraConfig +from hydra.core.singleton import Singleton +from hydra.core.utils import ( + JobReturn, + configure_log, + filter_overrides, + run_job, + setup_globals, +) +from hydra.plugins.sweeper import ExperimentSequence +from hydra.types import HydraContext, TaskFunction +from joblib import Parallel, delayed # type: ignore +from omegaconf import DictConfig, open_dict +import multiprocessing as mp + +from .joblib_launcher import JoblibLauncher + +log = logging.getLogger(__name__) + + +def execute_job( + idx: int, + overrides: Sequence[str], + hydra_context: HydraContext, + config: DictConfig, + task_function: TaskFunction, + singleton_state: Dict[Any, Any], +) -> JobReturn: + """Calls `run_job` in parallel""" + setup_globals() + Singleton.set_state(singleton_state) + + sweep_config = hydra_context.config_loader.load_sweep_config( + config, list(overrides) + ) + with open_dict(sweep_config): + sweep_config.hydra.job.id = "{}_{}".format(sweep_config.hydra.job.name, idx) + sweep_config.hydra.job.num = idx + HydraConfig.instance().set_config(sweep_config) + + ret = run_job( + hydra_context=hydra_context, + config=sweep_config, + task_function=task_function, + job_dir_key="hydra.sweep.dir", + job_subdir_key="hydra.sweep.subdir", + ) + + return ret + + +def process_joblib_cfg(joblib_cfg: Dict[str, Any]) -> None: + for k in ["pre_dispatch", "batch_size", "max_nbytes"]: + if k in joblib_cfg.keys(): + try: + val = joblib_cfg.get(k) + if val: + joblib_cfg[k] = int(val) + except ValueError: + pass + + +def _batch_sequence(sequence, batch_size=1): + while True: + overrides = [experiment_config for _, experiment_config in zip(range(batch_size), sequence)] + if overrides: + yield overrides + if len(overrides) != batch_size: + raise StopIteration + + +def launch( + launcher: JoblibLauncher, + job_overrides: Union[Sequence[Sequence[str]], ExperimentSequence], + initial_job_idx: int, +) -> Sequence[JobReturn]: + """ + :param job_overrides: an Iterable of List, where each inner list is the arguments for one job run. + :param initial_job_idx: Initial job idx in batch. + :return: an array of return values from run_job with indexes corresponding to the input list indexes. + """ + setup_globals() + assert launcher.config is not None + assert launcher.task_function is not None + assert launcher.hydra_context is not None + + configure_log(launcher.config.hydra.hydra_logging, launcher.config.hydra.verbose) + sweep_dir = Path(str(launcher.config.hydra.sweep.dir)) + sweep_dir.mkdir(parents=True, exist_ok=True) + + # Joblib's backend is hard-coded to loky since the threading + # backend is incompatible with Hydra + joblib_cfg = launcher.joblib + joblib_cfg["backend"] = "loky" + process_joblib_cfg(joblib_cfg) + singleton_state = Singleton.get_state() + + if isinstance(job_overrides, ExperimentSequence): + log.info( + "Joblib.Parallel({}) is launching {} jobs".format( + ",".join([f"{k}={v}" for k, v in joblib_cfg.items()]), + 'generator of', + ) + ) + batch_size = v if (v := joblib_cfg['n_jobs']) != -1 else mp.cpu_count() + runs = [] + overrides = [] + for idx, overrides in enumerate(_batch_sequence(job_overrides, batch_size)): + for i, override in enumerate(overrides): + log.info("\t#{} : {}".format(idx*batch_size+i, " ".join(filter_overrides(override)))) + results = Parallel(**joblib_cfg)( + delayed(execute_job)( + initial_job_idx + idx, + override, + launcher.hydra_context, + launcher.config, + launcher.task_function, + singleton_state, + ) + for override in overrides + ) + for experiment_result in zip(overrides, results): + job_overrides.update_sequence(experiment_result) + else: + log.info( + "Joblib.Parallel({}) is launching {} jobs".format( + ",".join([f"{k}={v}" for k, v in joblib_cfg.items()]), + len(job_overrides), + ) + ) + log.info("Launching jobs, sweep output dir : {}".format(sweep_dir)) + for idx, overrides in enumerate(job_overrides): + log.info("\t#{} : {}".format(idx, " ".join(filter_overrides(overrides)))) + + runs = Parallel(**joblib_cfg)( + delayed(execute_job)( + initial_job_idx + idx, + overrides, + launcher.hydra_context, + launcher.config, + launcher.task_function, + singleton_state, + ) + for idx, overrides in enumerate(job_overrides) + ) + + assert isinstance(runs, List) + for run in runs: + assert isinstance(run, JobReturn) + return runs diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/config.py new file mode 100644 index 000000000..6ae2827b6 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/config.py @@ -0,0 +1,51 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from dataclasses import dataclass +from typing import Optional + +from hydra.core.config_store import ConfigStore + + +@dataclass +class JobLibLauncherConf: + _target_: str = "hydra_plugins.hydra_joblib_launcher.joblib_launcher.JoblibLauncher" + + # maximum number of concurrently running jobs. if -1, all CPUs are used + n_jobs: int = -1 + + # allows to hard-code backend, otherwise inferred based on prefer and require + backend: Optional[str] = None + + # processes or threads, soft hint to choose backend + prefer: str = "processes" + + # null or sharedmem, sharedmem will select thread-based backend + require: Optional[str] = None + + # if greater than zero, prints progress messages + verbose: int = 0 + + # timeout limit for each task. Unit dependent on backend implementation; miliseconds for loky. + timeout: Optional[float] = None + + # number of batches to be pre-dispatched + pre_dispatch: str = "2*n_jobs" + + # number of atomic tasks to dispatch at once to each worker + batch_size: str = "auto" + + # path used for memmapping large arrays for sharing memory with workers + temp_folder: Optional[str] = None + + # thresholds size of arrays that triggers automated memmapping + max_nbytes: Optional[str] = None + + # memmapping mode for numpy arrays passed to workers + mmap_mode: str = "r" + + +ConfigStore.instance().store( + group="hydra/launcher", + name="joblib", + node=JobLibLauncherConf, + provider="joblib_launcher", +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/joblib_launcher.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/joblib_launcher.py new file mode 100644 index 000000000..66cb99d74 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/joblib_launcher.py @@ -0,0 +1,47 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import logging +from typing import Any, Optional, Sequence + +from hydra.core.utils import JobReturn +from hydra.plugins.launcher import Launcher +from hydra.types import HydraContext, TaskFunction +from omegaconf import DictConfig + +log = logging.getLogger(__name__) + + +class JoblibLauncher(Launcher): + def __init__(self, **kwargs: Any) -> None: + """Joblib Launcher + + Launches parallel jobs using Joblib.Parallel. For details, refer to: + https://joblib.readthedocs.io/en/latest/generated/joblib.Parallel.html + + This plugin is based on the idea and inital implementation of @emilemathieutmp: + https://github.com/facebookresearch/hydra/issues/357 + """ + self.config: Optional[DictConfig] = None + self.task_function: Optional[TaskFunction] = None + self.hydra_context: Optional[HydraContext] = None + + self.joblib = kwargs + + def setup( + self, + *, + hydra_context: HydraContext, + task_function: TaskFunction, + config: DictConfig, + ) -> None: + self.config = config + self.task_function = task_function + self.hydra_context = hydra_context + + def launch( + self, job_overrides: Sequence[Sequence[str]], initial_job_idx: int + ) -> Sequence[JobReturn]: + from . import _core + + return _core.launch( + launcher=self, job_overrides=job_overrides, initial_job_idx=initial_job_idx + ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/py.typed b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/hydra_plugins/hydra_joblib_launcher/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/news/.gitignore b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/news/.gitignore new file mode 100644 index 000000000..b722e9e13 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/news/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/pyproject.toml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/pyproject.toml new file mode 100644 index 000000000..fe7d2a3e9 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/pyproject.toml @@ -0,0 +1,43 @@ +[build-system] +requires = ["setuptools", "wheel", "read-version"] +build-backend = "setuptools.build_meta" + + +[tool.towncrier] + package = "hydra_plugins.hydra_joblib_launcher" + filename = "NEWS.md" + directory = "news/" + title_format = "{version} ({project_date})" + template = "../../news/_template.rst" + issue_format = "[#{issue}](https://github.com/facebookresearch/hydra/issues/{issue})" + start_string = "\n" + + [[tool.towncrier.type]] + directory = "feature" + name = "Features" + showcontent = true + + [[tool.towncrier.type]] + directory = "api_change" + name = "API Change (Renames, deprecations and removals)" + showcontent = true + + [[tool.towncrier.type]] + directory = "bugfix" + name = "Bug Fixes" + showcontent = true + + [[tool.towncrier.type]] + directory = "config" + name = "Configuration structure changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "docs" + name = "Improved Documentation" + showcontent = true + + [[tool.towncrier.type]] + directory = "maintenance" + name = "Maintenance Changes" + showcontent = true diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/setup.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/setup.py new file mode 100644 index 000000000..9a1d2b87d --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/setup.py @@ -0,0 +1,33 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +# type: ignore +from pathlib import Path + +from read_version import read_version +from setuptools import find_namespace_packages, setup + +setup( + name="hydra-joblib-launcher", + version=read_version("hydra_plugins/hydra_joblib_launcher", "__init__.py"), + author="Jan-Matthis Lueckmann, Omry Yadan", + author_email="mail@jan-matthis.de, omry@fb.com", + description="Joblib Launcher for Hydra apps", + long_description=(Path(__file__).parent / "README.md").read_text(), + long_description_content_type="text/markdown", + url="https://github.com/facebookresearch/hydra/", + packages=find_namespace_packages(include=["hydra_plugins.*"]), + classifiers=[ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + ], + install_requires=[ + "hydra-core>=1.1.0.dev7", + "joblib>=0.14.0", + ], + include_package_data=True, +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/tests/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/tests/__init__.py new file mode 100644 index 000000000..168f9979a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/tests/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/tests/test_joblib_launcher.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/tests/test_joblib_launcher.py new file mode 100644 index 000000000..96a01bd52 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_joblib_launcher/tests/test_joblib_launcher.py @@ -0,0 +1,95 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from typing import Any + +from hydra.core.plugins import Plugins +from hydra.plugins.launcher import Launcher +from hydra.test_utils.launcher_common_tests import ( + IntegrationTestSuite, + LauncherTestSuite, +) +from hydra.test_utils.test_utils import TSweepRunner, chdir_plugin_root +from pytest import mark + +from hydra_plugins.hydra_joblib_launcher.joblib_launcher import JoblibLauncher + +chdir_plugin_root() + + +def test_discovery() -> None: + # Tests that this plugin can be discovered via the plugins subsystem when looking for Launchers + assert JoblibLauncher.__name__ in [ + x.__name__ for x in Plugins.instance().discover(Launcher) + ] + + +@mark.parametrize("launcher_name, overrides", [("joblib", [])]) +class TestJoblibLauncher(LauncherTestSuite): + """ + Run the Launcher test suite on this launcher. + """ + + pass + + +@mark.parametrize( + "task_launcher_cfg, extra_flags", + [ + # joblib with process-based backend (default) + ( + {}, + [ + "-m", + "hydra/job_logging=hydra_debug", + "hydra/job_logging=disabled", + "hydra/launcher=joblib", + ], + ) + ], +) +class TestJoblibLauncherIntegration(IntegrationTestSuite): + """ + Run this launcher through the integration test suite. + """ + + pass + + +def test_example_app(hydra_sweep_runner: TSweepRunner, tmpdir: Any) -> None: + with hydra_sweep_runner( + calling_file="example/my_app.py", + calling_module=None, + task_function=None, + config_path=".", + config_name="config", + overrides=["task=1,2,3,4", f"hydra.sweep.dir={tmpdir}"], + ) as sweep: + overrides = {("task=1",), ("task=2",), ("task=3",), ("task=4",)} + + assert sweep.returns is not None and len(sweep.returns[0]) == 4 + for ret in sweep.returns[0]: + assert tuple(ret.overrides) in overrides + + +@mark.parametrize( + "overrides", + [ + "hydra.launcher.batch_size=1", + "hydra.launcher.max_nbytes=10000", + "hydra.launcher.max_nbytes=1M", + "hydra.launcher.pre_dispatch=all", + "hydra.launcher.pre_dispatch=10", + "hydra.launcher.pre_dispatch=3*n_jobs", + ], +) +def test_example_app_launcher_overrides( + hydra_sweep_runner: TSweepRunner, overrides: str +) -> None: + with hydra_sweep_runner( + calling_file="example/my_app.py", + calling_module=None, + task_function=None, + config_path=".", + config_name="config", + overrides=[overrides], + ) as sweep: + assert sweep.returns is not None and len(sweep.returns[0]) == 1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/MANIFEST.in b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/MANIFEST.in new file mode 100644 index 000000000..580709b13 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/MANIFEST.in @@ -0,0 +1,3 @@ +global-exclude *.pyc +global-exclude __pycache__ +recursive-include hydra_plugins/* *.yaml py.typed diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/NEWS.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/NEWS.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/NEWS.md @@ -0,0 +1 @@ + diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/README.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/README.md new file mode 100644 index 000000000..69c386ace --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/README.md @@ -0,0 +1,3 @@ +# Hydra loky Launcher +Provides a [loky](link) based Hydra Launcher supporting parallel worker pool execution. + diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/example/config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/example/config.yaml new file mode 100644 index 000000000..ba590cf44 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/example/config.yaml @@ -0,0 +1,9 @@ +defaults: + - override hydra/launcher: multiprocessing + +task: 1 + +hydra: + launcher: + # override the number of jobs for joblib + processes: 10 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/example/my_app.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/example/my_app.py new file mode 100644 index 000000000..b39236a19 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/example/my_app.py @@ -0,0 +1,20 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import logging +import os +import time + +import hydra +from omegaconf import DictConfig + +log = logging.getLogger(__name__) + + +@hydra.main(config_name="config") +def my_app(cfg: DictConfig) -> None: + log.info(f"Process ID {os.getpid()} executing task {cfg.task} ...") + + time.sleep(1) + + +if __name__ == "__main__": + my_app() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/__init__.py new file mode 100644 index 000000000..678b5f3c1 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved + +__version__ = "1.2.0" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/_core.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/_core.py new file mode 100644 index 000000000..b1cf364e9 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/_core.py @@ -0,0 +1,222 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import logging +from pathlib import Path +from typing import Any, Dict, Union, List, Sequence +from enum import Enum + +import cloudpickle + +from hydra.core.hydra_config import HydraConfig +from hydra.core.singleton import Singleton +from hydra.core.utils import ( + JobReturn, + JobStatus, + configure_log, + filter_overrides, + run_job, + setup_globals, +) +from hydra.plugins.sweeper import ExperimentSequence +from hydra.types import HydraContext, TaskFunction +from omegaconf import DictConfig, open_dict +import multiprocessing as mp +import multiprocessing.connection # needed to use mp.connection + +from .multiprocessing_launcher import MultiprocessingLauncher + +log = logging.getLogger(__name__) + + +class WaitingStrategy(Enum): + FIRST_COMPLETED = 'first_completed' + ALL_COMPLETED = 'all_completed' + + +def execute_job( + idx: int, + overrides: Sequence[str], + hydra_context: HydraContext, + config: DictConfig, + task_function: TaskFunction, + singleton_state: Dict[Any, Any], +) -> JobReturn: + """Calls `run_job` in parallel""" + setup_globals() + Singleton.set_state(singleton_state) + + sweep_config = hydra_context.config_loader.load_sweep_config( + config, list(overrides) + ) + with open_dict(sweep_config): + sweep_config.hydra.job.id = "{}_{}".format(sweep_config.hydra.job.name, idx) + sweep_config.hydra.job.num = idx + HydraConfig.instance().set_config(sweep_config) + + ret = run_job( + hydra_context=hydra_context, + config=sweep_config, + task_function=task_function, + job_dir_key="hydra.sweep.dir", + job_subdir_key="hydra.sweep.subdir", + ) + return ret + + +def _proxy_fn_call(results_queue, collection_lock, *args): + args = [cloudpickle.loads(obj) for obj in args] + result = execute_job(*args) + with collection_lock: + results_queue.put((int(mp.current_process().name), cloudpickle.dumps(result))) + + +def wait_for_results(running_tasks, + results_queue, + idx_to_process, + collection_lock, + return_when=WaitingStrategy.ALL_COMPLETED): + if not running_tasks: + return [], [] + # waiting_strategy = all if return_when is WaitingStrategy.ALL_COMPLETED else any + keep_waiting = True + finished = [] + results = [] + while keep_waiting: + mp.connection.wait([p.sentinel for p in running_tasks]) + with collection_lock: + while not results_queue.empty(): + idx, ret = results_queue.get() + finished.append(idx_to_process[idx]) + results.append(cloudpickle.loads(ret)) + + for p in running_tasks: + if not p.is_alive() and p.exitcode != 0: + e = mp.ProcessError('Worker process terminated unexpectedly!') + ret = JobReturn() + ret.return_value = e + ret.status = JobStatus.FAILED + finished.append(p) + results.append(ret) + if not p.is_alive(): + p.join() + + if return_when is WaitingStrategy.ALL_COMPLETED: + keep_waiting = len(results) != len(running_tasks) + else: + keep_waiting = len(results) == 0 + + return finished, results + + +def launch( + launcher: MultiprocessingLauncher, + job_overrides: Union[Sequence[Sequence[str]], ExperimentSequence], + initial_job_idx: int, +) -> Sequence[JobReturn]: + """ + :param job_overrides: an Iterable of List, where each inner list is the arguments for one job run. + :param initial_job_idx: Initial job idx in batch. + :return: an array of return values from run_job with indexes corresponding to the input list indexes. + """ + setup_globals() + assert launcher.config is not None + assert launcher.task_function is not None + assert launcher.hydra_context is not None + + configure_log(launcher.config.hydra.hydra_logging, launcher.config.hydra.verbose) + sweep_dir = Path(str(launcher.config.hydra.sweep.dir)) + sweep_dir.mkdir(parents=True, exist_ok=True) + + singleton_state = Singleton.get_state() + batch_size = v if (v := launcher.mp_config['n_jobs']) else mp.cpu_count() + + runs = [None for _ in range(len(job_overrides))] + log.info( + "Multiprocessing({}) is launching {} jobs".format( + ",".join([f"{k}={v}" for k, v in launcher.mp_config.items()]), + 'generator of' if isinstance(job_overrides, ExperimentSequence) else len(job_overrides), + ) + ) + + running_tasks = {} + collection_lock = launcher.mp_context.Lock() + results_queue = launcher.mp_context.Queue() + idx_to_process = {} + + for idx, override in enumerate(job_overrides): + log.info("\t#{} : {}".format(idx, " ".join(filter_overrides(override)))) + p = launcher.mp_context.Process( + target=_proxy_fn_call, + args=(results_queue, + collection_lock, + *[cloudpickle.dumps(obj) + for obj in ( + initial_job_idx + idx, + override, + launcher.hydra_context, + launcher.config, + launcher.task_function, + singleton_state)] + ), + name=str(idx) + ) + running_tasks[p] = (override, idx) + idx_to_process[idx] = p + p.start() + + if len(running_tasks) == batch_size: + finished, results = wait_for_results(running_tasks, + results_queue, + idx_to_process, + collection_lock, + return_when=WaitingStrategy.FIRST_COMPLETED) + + overrides = [running_tasks[f] for f in finished] + running_tasks = {task: running_tasks[task] for task in running_tasks if task not in finished} + + for (override, idx), res in zip(overrides, results): + runs[idx] = res + del idx_to_process[idx] + if isinstance(job_overrides, ExperimentSequence): + try: + job_overrides.update_sequence((override, res)) + except: + [p.terminate() for p in idx_to_process.values()] + raise + + finished, results = wait_for_results(running_tasks, + results_queue, + idx_to_process, + collection_lock, + return_when=WaitingStrategy.ALL_COMPLETED) + + overrides = [running_tasks[f] for f in finished] + + for (override, idx), res in zip(overrides, results): + runs[idx] = res + del idx_to_process[idx] + if isinstance(job_overrides, ExperimentSequence): + try: + job_overrides.update_sequence((override, res)) + except: + [p.terminate() for p in idx_to_process.values()] + raise + + #launcher.executor.close() + assert isinstance(runs, List) + for run in runs: + assert isinstance(run, JobReturn) + return runs diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/config.py new file mode 100644 index 000000000..0210cf2b8 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/config.py @@ -0,0 +1,21 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from dataclasses import dataclass +from typing import Optional + +from hydra.core.config_store import ConfigStore + + +@dataclass +class MultiprocessingLauncherConf: + _target_: str = "hydra_plugins.hydra_multiprocessing_launcher.multiprocessing_launcher.MultiprocessingLauncher" + + # maximum number of concurrently running jobs. if None, all CPUs are used + n_jobs: Optional[int] = None + + +ConfigStore.instance().store( + group="hydra/launcher", + name="multiprocessing", + node=MultiprocessingLauncherConf, + provider="multiprocessing_launcher", +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/multiprocessing_launcher.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/multiprocessing_launcher.py new file mode 100644 index 000000000..be1e5e9ea --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/multiprocessing_launcher.py @@ -0,0 +1,73 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import logging +from typing import Any, Optional, Sequence +import multiprocessing as mp + +from hydra.core.utils import JobReturn +from hydra.plugins.launcher import Launcher +from hydra.plugins.sweeper import ExperimentSequence +from hydra.types import HydraContext, TaskFunction +from omegaconf import DictConfig + +log = logging.getLogger(__name__) + + + +class MultiprocessingLauncher(Launcher): + def __init__(self, **kwargs: Any) -> None: + """Multiprocessing Launcher + + Launches parallel jobs using pure python multiprocessing. + Intended usecase is to start heavy long running jobs (e.g. ML model training). + + This plugin is based on the idea and inital implementation of joblib launcher. + """ + self.config: Optional[DictConfig] = None + self.task_function: Optional[TaskFunction] = None + self.hydra_context: Optional[HydraContext] = None + self.executor = None + self.mp_config = kwargs + + def setup( + self, + *, + hydra_context: HydraContext, + task_function: TaskFunction, + config: DictConfig, + ) -> None: + self.config = config + self.task_function = task_function + self.hydra_context = hydra_context + self.mp_context = mp.get_context('spawn') + + def launch( + self, job_overrides: Sequence[Sequence[str]], initial_job_idx: int + ) -> Sequence[JobReturn]: + from . import _core + + return _core.launch( + launcher=self, job_overrides=job_overrides, initial_job_idx=initial_job_idx + ) + + def launch_experiment_sequence( + self, job_overrides: ExperimentSequence, initial_job_idx: int + ) -> Sequence[JobReturn]: + from . import _core + + return _core.launch( + launcher=self, job_overrides=job_overrides, initial_job_idx=initial_job_idx + ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/py.typed b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/hydra_plugins/hydra_multiprocessing_launcher/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/news/.gitignore b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/news/.gitignore new file mode 100644 index 000000000..b722e9e13 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/news/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/pyproject.toml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/pyproject.toml new file mode 100644 index 000000000..fe7d2a3e9 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/pyproject.toml @@ -0,0 +1,43 @@ +[build-system] +requires = ["setuptools", "wheel", "read-version"] +build-backend = "setuptools.build_meta" + + +[tool.towncrier] + package = "hydra_plugins.hydra_joblib_launcher" + filename = "NEWS.md" + directory = "news/" + title_format = "{version} ({project_date})" + template = "../../news/_template.rst" + issue_format = "[#{issue}](https://github.com/facebookresearch/hydra/issues/{issue})" + start_string = "\n" + + [[tool.towncrier.type]] + directory = "feature" + name = "Features" + showcontent = true + + [[tool.towncrier.type]] + directory = "api_change" + name = "API Change (Renames, deprecations and removals)" + showcontent = true + + [[tool.towncrier.type]] + directory = "bugfix" + name = "Bug Fixes" + showcontent = true + + [[tool.towncrier.type]] + directory = "config" + name = "Configuration structure changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "docs" + name = "Improved Documentation" + showcontent = true + + [[tool.towncrier.type]] + directory = "maintenance" + name = "Maintenance Changes" + showcontent = true diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/setup.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/setup.py new file mode 100644 index 000000000..51c73c491 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/setup.py @@ -0,0 +1,33 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +# type: ignore +from pathlib import Path + +from read_version import read_version +from setuptools import find_namespace_packages, setup + +setup( + name="hydra-multiprocessing-launcher", + version=read_version("hydra_plugins/hydra_multiprocessing_launcher", "__init__.py"), + author="Dima Zhylko, Jan Bączek", + author_email="dzhylko@nvidia.com, jbaczek@nvidia.com", + description="Multiprocessing Launcher for Hydra apps", + long_description=(Path(__file__).parent / "README.md").read_text(), + long_description_content_type="text/markdown", + url="https://github.com/facebookresearch/hydra/", + packages=find_namespace_packages(include=["hydra_plugins.*"]), + classifiers=[ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + ], + install_requires=[ + "hydra-core>=1.1.0.dev7", + "cloudpickle>=2.0.0", + ], + include_package_data=True, +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/tests/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/tests/__init__.py new file mode 100644 index 000000000..168f9979a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/tests/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/tests/test_multiprocessing_launcher.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/tests/test_multiprocessing_launcher.py new file mode 100644 index 000000000..d4cb2c142 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_multiprocessing_launcher/tests/test_multiprocessing_launcher.py @@ -0,0 +1,105 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from typing import Any + +from hydra.core.plugins import Plugins +from hydra.plugins.launcher import Launcher +from hydra.test_utils.launcher_common_tests import ( + IntegrationTestSuite, + LauncherTestSuite, +) +from hydra.test_utils.test_utils import TSweepRunner, chdir_plugin_root +from pytest import mark + +from hydra_plugins.hydra_multiprocessing_launcher.multiprocessing_launcher import MultiprocessingLauncher + +chdir_plugin_root() + + +def test_discovery() -> None: + # Tests that this plugin can be discovered via the plugins subsystem when looking for Launchers + assert MultiprocessingLauncher.__name__ in [ + x.__name__ for x in Plugins.instance().discover(Launcher) + ] + + +@mark.parametrize("launcher_name, overrides", [("multiprocessing", [])]) +class TestMultiprocessingLauncher(LauncherTestSuite): + """ + Run the Launcher test suite on this launcher. + """ + + pass + + +@mark.parametrize( + "task_launcher_cfg, extra_flags", + [ + # multiprocessing with process-based backend (default) + ( + {}, + [ + "-m", + "hydra/job_logging=hydra_debug", + "hydra/job_logging=disabled", + "hydra/launcher=multiprocessing", + ], + ) + ], +) +class TestMultiprocessingLauncherIntegration(IntegrationTestSuite): + """ + Run this launcher through the integration test suite. + """ + + pass + + +def test_example_app(hydra_sweep_runner: TSweepRunner, tmpdir: Any) -> None: + with hydra_sweep_runner( + calling_file="example/my_app.py", + calling_module=None, + task_function=None, + config_path=".", + config_name="config", + overrides=["task=1,2,3,4", f"hydra.sweep.dir={tmpdir}"], + ) as sweep: + overrides = {("task=1",), ("task=2",), ("task=3",), ("task=4",)} + + assert sweep.returns is not None and len(sweep.returns[0]) == 4 + for ret in sweep.returns[0]: + assert tuple(ret.overrides) in overrides + + +@mark.parametrize( + "overrides", + [ + "hydra.launcher.processes=1", + "hydra.launcher.maxtasksperchild=1" + ], +) +def test_example_app_launcher_overrides( + hydra_sweep_runner: TSweepRunner, overrides: str +) -> None: + with hydra_sweep_runner( + calling_file="example/my_app.py", + calling_module=None, + task_function=None, + config_path=".", + config_name="config", + overrides=[overrides], + ) as sweep: + assert sweep.returns is not None and len(sweep.returns[0]) == 1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/MANIFEST.in b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/MANIFEST.in new file mode 100644 index 000000000..580709b13 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/MANIFEST.in @@ -0,0 +1,3 @@ +global-exclude *.pyc +global-exclude __pycache__ +recursive-include hydra_plugins/* *.yaml py.typed diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/NEWS.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/NEWS.md new file mode 100644 index 000000000..77a2beabf --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/NEWS.md @@ -0,0 +1,40 @@ +1.2.0 (2022-05-17) +====================== + +### Features + +- Add support for GridSampler ([#1815](https://github.com/facebookresearch/hydra/issues/1815)) +- Support for Python 3.10 ([#1856](https://github.com/facebookresearch/hydra/issues/1856)) +- Add experimental 'custom_search_space' configuration node to allow extending trial objects programmatically. ([#1906](https://github.com/facebookresearch/hydra/issues/1906)) + +### Configuration structure changes + +- Add hydra.sweeper.params and deprecate hydra.sweeper.search_space ([#1890](https://github.com/facebookresearch/hydra/issues/1890)) + + +1.1.2 (2022-01-23) +======================= + +### Bug Fixes + +- Fix a bug where Optuna Sweeper parses the override value incorrectly ([#1811](https://github.com/facebookresearch/hydra/issues/1811)) + + +1.1.1 (2021-09-01) +======================= + +### Maintenance Changes + +- Update optuna dependency ([#1746](https://github.com/facebookresearch/hydra/issues/1634)) + + +1.1.0.dev2 (2021-06-10) +======================= + +### Features + +- Add support for changing settings of Optuna samplers ([#1472](https://github.com/facebookresearch/hydra/issues/1472)) + +### API Change (Renames, deprecations and removals) + +- Config structure changes, please refer to the [docs](https://hydra.cc/docs/plugins/optuna_sweeper/) ([#1472](https://github.com/facebookresearch/hydra/issues/1472)) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/README.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/README.md new file mode 100644 index 000000000..16b8b0629 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/README.md @@ -0,0 +1,5 @@ +# Hydra Optuna Sweeper + +Provides an [Optuna](https://optuna.org) based Hydra Sweeper. + +See [website](https://hydra.cc/docs/plugins/optuna_sweeper/) for more information. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/conf/config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/conf/config.yaml new file mode 100644 index 000000000..e3b86c710 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/conf/config.yaml @@ -0,0 +1,24 @@ +defaults: + - override hydra/sweeper: optuna + - override hydra/sweeper/sampler: tpe + +hydra: + sweeper: + sampler: + seed: 123 + direction: minimize + study_name: sphere + storage: null + n_trials: 20 + n_jobs: 1 + max_failure_rate: 0.0 + params: + x: range(-5.5, 5.5, step=0.5) + y: choice(-5 ,0 ,5) + +x: 1 +y: 1 +z: 1 + +# if true, simulate a failure by raising an exception +error: false diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/custom-search-space-objective.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/custom-search-space-objective.py new file mode 100644 index 000000000..a389a63ed --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/custom-search-space-objective.py @@ -0,0 +1,27 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import hydra +from omegaconf import DictConfig +from optuna.trial import Trial + + +@hydra.main(version_base=None, config_path="custom-search-space", config_name="config") +def multi_dimensional_sphere(cfg: DictConfig) -> float: + w: float = cfg.w + x: float = cfg.x + y: float = cfg.y + z: float = cfg.z + return w**2 + x**2 + y**2 + z**2 + + +def configure(cfg: DictConfig, trial: Trial) -> None: + x_value = trial.params["x"] + trial.suggest_float( + "z", + x_value - cfg.max_z_difference_from_x, + x_value + cfg.max_z_difference_from_x, + ) + trial.suggest_float("+w", 0.0, 1.0) # note +w here, not w as w is a new parameter + + +if __name__ == "__main__": + multi_dimensional_sphere() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/custom-search-space/config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/custom-search-space/config.yaml new file mode 100644 index 000000000..f11a2aaed --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/custom-search-space/config.yaml @@ -0,0 +1,24 @@ +defaults: + - override hydra/sweeper: optuna + +hydra: + sweeper: + sampler: + seed: 123 + direction: minimize + study_name: custom-search-space + storage: null + n_trials: 20 + n_jobs: 1 + + params: + x: range(-5.5, 5.5, 0.5) + y: choice(-5, 0, 5) + # `custom_search_space` should be a dotpath pointing to a + # callable that provides search-space configuration logic: + custom_search_space: custom-search-space-objective.configure + +x: 1 +y: 1 +z: 100 +max_z_difference_from_x: 0.5 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/multi-objective-conf/config.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/multi-objective-conf/config.yaml new file mode 100644 index 000000000..d4cc4f2d7 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/multi-objective-conf/config.yaml @@ -0,0 +1,19 @@ +defaults: + - override hydra/sweeper: optuna + - override hydra/sweeper/sampler: nsgaii + +hydra: + sweeper: + sampler: + seed: 123 + direction: [minimize, minimize] + study_name: multi-objective + storage: null + n_trials: 20 + n_jobs: 1 + params: + x: range(0, 5, step=0.5) + y: range(0, 3, step=0.5) + +x: 1 +y: 1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/multi-objective.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/multi-objective.py new file mode 100644 index 000000000..80d2666c4 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/multi-objective.py @@ -0,0 +1,19 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from typing import Tuple + +import hydra +from omegaconf import DictConfig + + +@hydra.main(version_base=None, config_path="multi-objective-conf", config_name="config") +def binh_and_korn(cfg: DictConfig) -> Tuple[float, float]: + x: float = cfg.x + y: float = cfg.y + + v0 = 4 * x**2 + 4 * y**2 + v1 = (x - 5) ** 2 + (y - 5) ** 2 + return v0, v1 + + +if __name__ == "__main__": + binh_and_korn() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/sphere.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/sphere.py new file mode 100644 index 000000000..d6cf8ef9d --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/example/sphere.py @@ -0,0 +1,18 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import hydra +from omegaconf import DictConfig + + +@hydra.main(version_base=None, config_path="conf", config_name="config") +def sphere(cfg: DictConfig) -> float: + x: float = cfg.x + y: float = cfg.y + + if cfg.get("error", False): + raise RuntimeError("cfg.error is True") + + return x**2 + y**2 + + +if __name__ == "__main__": + sphere() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/__init__.py new file mode 100644 index 000000000..e42a13578 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/__init__.py @@ -0,0 +1,3 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved + +__version__ = "1.3.0.dev0" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/_impl.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/_impl.py new file mode 100644 index 000000000..992416124 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/_impl.py @@ -0,0 +1,469 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import functools +import logging +import sys +import warnings +from textwrap import dedent +from typing import ( + Any, + Callable, + Dict, + List, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, +) + +import optuna +from hydra._internal.deprecation_warning import deprecation_warning +from hydra.core.override_parser.overrides_parser import OverridesParser +from hydra.core.override_parser.types import ( + ChoiceSweep, + IntervalSweep, + Override, + RangeSweep, + Transformer, +) +from hydra.core.plugins import Plugins +from hydra.plugins.sweeper import ( + Sweeper, + ExperimentSequence +) +from hydra.types import HydraContext, TaskFunction +from hydra.utils import get_method, instantiate +from omegaconf import DictConfig, OmegaConf +from optuna.distributions import ( + BaseDistribution, + CategoricalChoiceType, + CategoricalDistribution, + DiscreteUniformDistribution, + IntLogUniformDistribution, + IntUniformDistribution, + LogUniformDistribution, + UniformDistribution, +) +from optuna.trial import Trial + +from .config import Direction, DistributionConfig, DistributionType + +log = logging.getLogger(__name__) + + +def create_optuna_distribution_from_config( + config: MutableMapping[str, Any] +) -> BaseDistribution: + kwargs = dict(config) + if isinstance(config["type"], str): + kwargs["type"] = DistributionType[config["type"]] + param = DistributionConfig(**kwargs) + if param.type == DistributionType.categorical: + assert param.choices is not None + return CategoricalDistribution(param.choices) + if param.type == DistributionType.int: + assert param.low is not None + assert param.high is not None + if param.log: + return IntLogUniformDistribution(int(param.low), int(param.high)) + step = int(param.step) if param.step is not None else 1 + return IntUniformDistribution(int(param.low), int(param.high), step=step) + if param.type == DistributionType.float: + assert param.low is not None + assert param.high is not None + if param.log: + return LogUniformDistribution(param.low, param.high) + if param.step is not None: + return DiscreteUniformDistribution(param.low, param.high, param.step) + return UniformDistribution(param.low, param.high) + raise NotImplementedError(f"{param.type} is not supported by Optuna sweeper.") + + +def create_optuna_distribution_from_override(override: Override) -> Any: + if not override.is_sweep_override(): + return override.get_value_element_as_str() + + value = override.value() + choices: List[CategoricalChoiceType] = [] + if override.is_choice_sweep(): + assert isinstance(value, ChoiceSweep) + for x in override.sweep_iterator(transformer=Transformer.encode): + assert isinstance( + x, (str, int, float, bool, type(None)) + ), f"A choice sweep expects str, int, float, bool, or None type. Got {type(x)}." + choices.append(x) + return CategoricalDistribution(choices) + + if override.is_range_sweep(): + assert isinstance(value, RangeSweep) + assert value.start is not None + assert value.stop is not None + if value.shuffle: + for x in override.sweep_iterator(transformer=Transformer.encode): + assert isinstance( + x, (str, int, float, bool, type(None)) + ), f"A choice sweep expects str, int, float, bool, or None type. Got {type(x)}." + choices.append(x) + return CategoricalDistribution(choices) + if ( + isinstance(value.start, float) + or isinstance(value.stop, float) + or isinstance(value.step, float) + ): + return DiscreteUniformDistribution(value.start, value.stop, value.step) + return IntUniformDistribution( + int(value.start), int(value.stop), step=int(value.step) + ) + + if override.is_interval_sweep(): + assert isinstance(value, IntervalSweep) + assert value.start is not None + assert value.end is not None + if "log" in value.tags: + if isinstance(value.start, int) and isinstance(value.end, int): + return IntLogUniformDistribution(int(value.start), int(value.end)) + return LogUniformDistribution(value.start, value.end) + else: + if isinstance(value.start, int) and isinstance(value.end, int): + return IntUniformDistribution(value.start, value.end) + return UniformDistribution(value.start, value.end) + + raise NotImplementedError(f"{override} is not supported by Optuna sweeper.") + + +def create_params_from_overrides( + arguments: List[str], +) -> Tuple[Dict[str, BaseDistribution], Dict[str, Any]]: + parser = OverridesParser.create() + parsed = parser.parse_overrides(arguments) + search_space_distributions = dict() + fixed_params = dict() + + for override in parsed: + param_name = override.get_key_element() + value = create_optuna_distribution_from_override(override) + if isinstance(value, BaseDistribution): + search_space_distributions[param_name] = value + else: + fixed_params[param_name] = value + return search_space_distributions, fixed_params + + +class OptunaExperimentSequence(ExperimentSequence): + def __init__(self, + study, + num_experiments, + search_space_distributions, + fixed_params, + directions, + custom_search_space_extender, + max_failure_rate=0.0, + is_grid_sampler=False) -> None: + self.study = study + self.num_experiments = num_experiments + self.search_space_distributions = search_space_distributions + self.fixed_params = fixed_params + self.directions = directions + self.custom_search_space_extender = custom_search_space_extender + self.max_failure_rate = max_failure_rate + self.fault_tolerance = int(num_experiments * max_failure_rate) + self.is_grid_sampler = is_grid_sampler + self.idx = -1 + self.override_trial_mapping = {} + + def _configure_trial( + self, + trial: Trial, + search_space_distributions: Dict[str, BaseDistribution], + fixed_params: Dict[str, Any], + ) -> Sequence[str]: + for param_name, distribution in search_space_distributions.items(): + assert type(param_name) is str + trial._suggest(param_name, distribution) + for param_name, value in fixed_params.items(): + trial.set_user_attr(param_name, value) + + if self.custom_search_space_extender: + assert self.config is not None + self.custom_search_space_extender(self.config, trial) + + overlap = trial.params.keys() & trial.user_attrs + if len(overlap): + raise ValueError( + "Overlapping fixed parameters and search space parameters found!" + f"Overlapping parameters: {list(overlap)}" + ) + params = dict(trial.params) + params.update(fixed_params) + + return tuple(f"{name}={val}" for name, val in params.items()) + + def update_sequence(self, experiment_result: Tuple[Sequence[str], Any]): + override, ret = experiment_result + trial = self.override_trial_mapping[override] + values: Optional[List[float]] = None + state: optuna.trial.TrialState = optuna.trial.TrialState.COMPLETE + try: + if len(self.directions) == 1: + try: + values = [float(ret.return_value)] + except (ValueError, TypeError): + raise ValueError( + f"Return value must be float-castable. Got '{ret.return_value}'." + ).with_traceback(sys.exc_info()[2]) + else: + try: + values = [float(v) for v in ret.return_value] + except (ValueError, TypeError): + raise ValueError( + "Return value must be a list or tuple of float-castable values." + f" Got '{ret.return_value}'." + ).with_traceback(sys.exc_info()[2]) + if len(values) != len(self.directions): + raise ValueError( + "The number of the values and the number of the objectives are" + f" mismatched. Expect {len(self.directions)}, but actually {len(values)}." + ) + + try: + self.study.tell(trial=trial, state=state, values=values) + except RuntimeError as e: + if ( + self.is_grid_sampler + and "`Study.stop` is supposed to be invoked inside an objective function or a callback." + in str(e) + ): + pass + else: + raise e + + except Exception as e: + state = optuna.trial.TrialState.FAIL + self.study.tell(trial=trial, state=state, values=values) + log.warning(f"Failed experiment: {e}") + self.fault_tolerance -= 1 + + # raise if too many failures + if self.fault_tolerance < 0: + log.error( + f"Failed {int(self.num_experiments * self.max_failure_rate)} times out of {self.num_experiments} " + f"with max_failure_rate={self.max_failure_rate}." + ) + ret.return_value # delegate raising to JobReturn, with actual traceback + + def __next__(self) -> Sequence[str]: + self.idx += 1 + if self.idx < self.num_experiments: + trial = self.study.ask() + override = self._configure_trial(trial, self.search_space_distributions, self.fixed_params) + self.override_trial_mapping[override] = trial + return override + else: + raise StopIteration + + def __len__(self): + return self.num_experiments + + +class OptunaSweeperImpl(Sweeper): + def __init__( + self, + sampler: Any, + direction: Any, + storage: Optional[Any], + study_name: Optional[str], + n_trials: int, + max_failure_rate: float, + search_space: Optional[DictConfig], + custom_search_space: Optional[str], + params: Optional[DictConfig], + experiment_sequence: str, + ) -> None: + self.sampler = sampler + self.direction = direction + self.storage = storage + self.study_name = study_name + self.n_trials = n_trials + self.max_failure_rate = max_failure_rate + assert self.max_failure_rate >= 0.0 + assert self.max_failure_rate <= 1.0 + self.custom_search_space_extender: Optional[ + Callable[[DictConfig, Trial], None] + ] = None + if custom_search_space: + self.custom_search_space_extender = get_method(custom_search_space) + self.search_space = search_space + self.params = params + self.job_idx: int = 0 + self.search_space_distributions: Optional[Dict[str, BaseDistribution]] = None + self.experiment_sequence_inst = experiment_sequence + + def _process_searchspace_config(self) -> None: + url = "https://hydra.cc/docs/upgrades/1.1_to_1.2/changes_to_sweeper_config/" + if self.params is None and self.search_space is None: + self.params = OmegaConf.create({}) + elif self.search_space is not None: + if self.params is not None: + warnings.warn( + "Both hydra.sweeper.params and hydra.sweeper.search_space are configured." + "\nHydra will use hydra.sweeper.params for defining search space." + f"\n{url}" + ) + else: + deprecation_warning( + message=dedent( + f"""\ + `hydra.sweeper.search_space` is deprecated and will be removed in the next major release. + Please configure with `hydra.sweeper.params`. + {url} + """ + ), + ) + self.search_space_distributions = { + str(x): create_optuna_distribution_from_config(y) + for x, y in self.search_space.items() + } + + def setup( + self, + *, + hydra_context: HydraContext, + task_function: TaskFunction, + config: DictConfig, + ) -> None: + self.job_idx = 0 + self.config = config + self.hydra_context = hydra_context + self.launcher = Plugins.instance().instantiate_launcher( + config=config, hydra_context=hydra_context, task_function=task_function + ) + self.sweep_dir = config.hydra.sweep.dir + + def _get_directions(self) -> List[str]: + if isinstance(self.direction, MutableSequence): + return [d.name if isinstance(d, Direction) else d for d in self.direction] + elif isinstance(self.direction, str): + return [self.direction] + return [self.direction.name] + + def _parse_sweeper_params_config(self) -> List[str]: + if not self.params: + return [] + + return [f"{k!s}={v}" for k, v in self.params.items()] + + def _to_grid_sampler_choices(self, distribution: BaseDistribution) -> Any: + if isinstance(distribution, CategoricalDistribution): + return distribution.choices + elif isinstance(distribution, IntUniformDistribution): + assert ( + distribution.step is not None + ), "`step` of IntUniformDistribution must be a positive integer." + n_items = (distribution.high - distribution.low) // distribution.step + return [distribution.low + i * distribution.step for i in range(n_items)] + elif isinstance(distribution, DiscreteUniformDistribution): + n_items = int((distribution.high - distribution.low) // distribution.q) + return [distribution.low + i * distribution.q for i in range(n_items)] + else: + raise ValueError("GridSampler only supports discrete distributions.") + + def sweep(self, arguments: List[str]) -> None: + assert self.config is not None + assert self.launcher is not None + assert self.hydra_context is not None + assert self.job_idx is not None + + self._process_searchspace_config() + params_conf = self._parse_sweeper_params_config() + params_conf.extend(arguments) + + is_grid_sampler = ( + isinstance(self.sampler, functools.partial) + and self.sampler.func == optuna.samplers.GridSampler # type: ignore + ) + + ( + override_search_space_distributions, + fixed_params, + ) = create_params_from_overrides(params_conf) + + search_space_distributions = dict() + if self.search_space_distributions: + search_space_distributions = self.search_space_distributions.copy() + search_space_distributions.update(override_search_space_distributions) + + if is_grid_sampler: + search_space_for_grid_sampler = { + name: self._to_grid_sampler_choices(distribution) + for name, distribution in search_space_distributions.items() + } + + self.sampler = self.sampler(search_space_for_grid_sampler) + n_trial = 1 + for v in search_space_for_grid_sampler.values(): + n_trial *= len(v) + self.n_trials = min(self.n_trials, n_trial) + log.info( + f"Updating num of trials to {self.n_trials} due to using GridSampler." + ) + + # Remove fixed parameters from Optuna search space. + for param_name in fixed_params: + if param_name in search_space_distributions: + del search_space_distributions[param_name] + + directions = self._get_directions() + + study = optuna.create_study( + study_name=self.study_name, + storage=self.storage, + sampler=self.sampler, + directions=directions, + load_if_exists=True, + ) + log.info(f"Study name: {study.study_name}") + log.info(f"Storage: {self.storage}") + log.info(f"Sampler: {type(self.sampler).__name__}") + log.info(f"Directions: {directions}") + + n_trials_to_go = self.n_trials + + experiment_sequence = instantiate( + {"_target_": self.experiment_sequence_inst}, + study, + n_trials_to_go, + search_space_distributions, + fixed_params, + directions, + self.custom_search_space_extender, + max_failure_rate=self.max_failure_rate, + is_grid_sampler=is_grid_sampler, + ) + self.launcher.launch(experiment_sequence, 0) + + results_to_serialize: Dict[str, Any] + if len(directions) < 2: + best_trial = study.best_trial + results_to_serialize = { + "name": "optuna", + "best_params": best_trial.params, + "best_value": best_trial.value, + } + log.info(f"Best parameters: {best_trial.params}") + log.info(f"Best value: {best_trial.value}") + else: + best_trials = study.best_trials + pareto_front = [ + {"params": t.params, "values": t.values} for t in best_trials + ] + results_to_serialize = { + "name": "optuna", + "solutions": pareto_front, + } + log.info(f"Number of Pareto solutions: {len(best_trials)}") + for t in best_trials: + log.info(f" Values: {t.values}, Params: {t.params}") + OmegaConf.save( + OmegaConf.create(results_to_serialize), + f"{self.config.hydra.sweep.dir}/optimization_results.yaml", + ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/config.py new file mode 100644 index 000000000..b7d767900 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/config.py @@ -0,0 +1,236 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from dataclasses import dataclass, field +from enum import Enum +from typing import Any, Dict, List, Optional + +from hydra.core.config_store import ConfigStore +from omegaconf import MISSING + + +class DistributionType(Enum): + int = 1 + float = 2 + categorical = 3 + + +class Direction(Enum): + minimize = 1 + maximize = 2 + + +@dataclass +class SamplerConfig: + _target_: str = MISSING + + +@dataclass +class GridSamplerConfig(SamplerConfig): + """ + https://optuna.readthedocs.io/en/stable/reference/generated/optuna.samplers.GridSampler.html + """ + + _target_: str = "optuna.samplers.GridSampler" + # search_space will be populated at run time based on hydra.sweeper.params + _partial_: bool = True + + +@dataclass +class TPESamplerConfig(SamplerConfig): + """ + https://optuna.readthedocs.io/en/stable/reference/generated/optuna.samplers.TPESampler.html + """ + + _target_: str = "optuna.samplers.TPESampler" + seed: Optional[int] = None + + consider_prior: bool = True + prior_weight: float = 1.0 + consider_magic_clip: bool = True + consider_endpoints: bool = False + n_startup_trials: int = 10 + n_ei_candidates: int = 24 + multivariate: bool = False + warn_independent_sampling: bool = True + + +@dataclass +class RandomSamplerConfig(SamplerConfig): + """ + https://optuna.readthedocs.io/en/stable/reference/generated/optuna.samplers.RandomSampler.html + """ + + _target_: str = "optuna.samplers.RandomSampler" + seed: Optional[int] = None + + +@dataclass +class CmaEsSamplerConfig(SamplerConfig): + """ + https://optuna.readthedocs.io/en/stable/reference/generated/optuna.samplers.CmaEsSampler.html + """ + + _target_: str = "optuna.samplers.CmaEsSampler" + seed: Optional[int] = None + + x0: Optional[Dict[str, Any]] = None + sigma0: Optional[float] = None + independent_sampler: Optional[Any] = None + warn_independent_sampling: bool = True + consider_pruned_trials: bool = False + restart_strategy: Optional[Any] = None + inc_popsize: int = 2 + use_separable_cma: bool = False + source_trials: Optional[Any] = None + + +@dataclass +class NSGAIISamplerConfig(SamplerConfig): + """ + https://optuna.readthedocs.io/en/stable/reference/generated/optuna.samplers.NSGAIISampler.html + """ + + _target_: str = "optuna.samplers.NSGAIISampler" + seed: Optional[int] = None + + population_size: int = 50 + mutation_prob: Optional[float] = None + crossover_prob: float = 0.9 + swapping_prob: float = 0.5 + constraints_func: Optional[Any] = None + + +@dataclass +class MOTPESamplerConfig(SamplerConfig): + """ + https://optuna.readthedocs.io/en/stable/reference/generated/optuna.samplers.MOTPESampler.html + """ + + _target_: str = "optuna.samplers.MOTPESampler" + seed: Optional[int] = None + + consider_prior: bool = True + prior_weight: float = 1.0 + consider_magic_clip: bool = True + consider_endpoints: bool = False + n_startup_trials: int = 10 + n_ehvi_candidates: int = 24 + + +@dataclass +class DistributionConfig: + + # Type of distribution. "int", "float" or "categorical" + type: DistributionType + + # Choices of categorical distribution + # List element type should be Union[str, int, float, bool] + choices: Optional[List[Any]] = None + + # Lower bound of int or float distribution + low: Optional[float] = None + + # Upper bound of int or float distribution + high: Optional[float] = None + + # If True, space is converted to the log domain + # Valid for int or float distribution + log: bool = False + + # Discritization step + # Valid for int or float distribution + step: Optional[float] = None + + +defaults = [{"sampler": "tpe"}] + + +@dataclass +class OptunaSweeperConf: + _target_: str = "hydra_plugins.hydra_optuna_sweeper.optuna_sweeper.OptunaSweeper" + defaults: List[Any] = field(default_factory=lambda: defaults) + + # Sampling algorithm + # Please refer to the reference for further details + # https://optuna.readthedocs.io/en/stable/reference/samplers.html + sampler: SamplerConfig = MISSING + + # Direction of optimization + # Union[Direction, List[Direction]] + direction: Any = Direction.minimize + + # Storage URL to persist optimization results + # For example, you can use SQLite if you set 'sqlite:///example.db' + # Please refer to the reference for further details + # https://optuna.readthedocs.io/en/stable/reference/storages.html + storage: Optional[Any] = None + + # Name of study to persist optimization results + study_name: Optional[str] = None + + # Total number of function evaluations + n_trials: int = 20 + + # Maximum authorized failure rate for a batch of parameters + max_failure_rate: float = 0.0 + + search_space: Optional[Dict[str, Any]] = None + + params: Optional[Dict[str, str]] = None + + # Allow custom trial configuration via Python methods. + # If given, `custom_search_space` should be a an instantiate-style dotpath targeting + # a callable with signature Callable[[DictConfig, optuna.trial.Trial], None]. + # https://optuna.readthedocs.io/en/stable/tutorial/10_key_features/002_configurations.html + custom_search_space: Optional[str] = None + + experiment_sequence: str = "hydra_plugins.hydra_optuna_sweeper._impl.OptunaExperimentSequence" + + +ConfigStore.instance().store( + group="hydra/sweeper", + name="optuna", + node=OptunaSweeperConf, + provider="optuna_sweeper", +) + +ConfigStore.instance().store( + group="hydra/sweeper/sampler", + name="tpe", + node=TPESamplerConfig, + provider="optuna_sweeper", +) + +ConfigStore.instance().store( + group="hydra/sweeper/sampler", + name="random", + node=RandomSamplerConfig, + provider="optuna_sweeper", +) + +ConfigStore.instance().store( + group="hydra/sweeper/sampler", + name="cmaes", + node=CmaEsSamplerConfig, + provider="optuna_sweeper", +) + +ConfigStore.instance().store( + group="hydra/sweeper/sampler", + name="nsgaii", + node=NSGAIISamplerConfig, + provider="optuna_sweeper", +) + +ConfigStore.instance().store( + group="hydra/sweeper/sampler", + name="motpe", + node=MOTPESamplerConfig, + provider="optuna_sweeper", +) + +ConfigStore.instance().store( + group="hydra/sweeper/sampler", + name="grid", + node=GridSamplerConfig, + provider="optuna_sweeper", +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/optuna_sweeper.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/optuna_sweeper.py new file mode 100644 index 000000000..112e8e44a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/optuna_sweeper.py @@ -0,0 +1,54 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from typing import Any, List, Optional + +from hydra.plugins.sweeper import Sweeper +from hydra.types import HydraContext, TaskFunction +from omegaconf import DictConfig + +from .config import SamplerConfig + + +class OptunaSweeper(Sweeper): + """Class to interface with Optuna""" + + def __init__( + self, + sampler: SamplerConfig, + direction: Any, + storage: Optional[Any], + study_name: Optional[str], + n_trials: int, + max_failure_rate: float, + search_space: Optional[DictConfig], + custom_search_space: Optional[str], + params: Optional[DictConfig], + experiment_sequence: str + ) -> None: + from ._impl import OptunaSweeperImpl + + self.sweeper = OptunaSweeperImpl( + sampler, + direction, + storage, + study_name, + n_trials, + max_failure_rate, + search_space, + custom_search_space, + params, + experiment_sequence, + ) + + def setup( + self, + *, + hydra_context: HydraContext, + task_function: TaskFunction, + config: DictConfig, + ) -> None: + self.sweeper.setup( + hydra_context=hydra_context, task_function=task_function, config=config + ) + + def sweep(self, arguments: List[str]) -> None: + return self.sweeper.sweep(arguments) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/py.typed b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/hydra_plugins/hydra_optuna_sweeper/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/news/.gitignore b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/news/.gitignore new file mode 100644 index 000000000..b722e9e13 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/news/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/news/1513.feature b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/news/1513.feature new file mode 100644 index 000000000..edf1774ca --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/news/1513.feature @@ -0,0 +1 @@ +Add fault tolerance via `max_failure_rate` parameter diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/pyproject.toml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/pyproject.toml new file mode 100644 index 000000000..fd2b51105 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/pyproject.toml @@ -0,0 +1,43 @@ +[build-system] +requires = ["setuptools", "wheel", "read-version"] +build-backend = "setuptools.build_meta" + + +[tool.towncrier] + package = "hydra_plugins.hydra_optuna_sweeper" + filename = "NEWS.md" + directory = "news/" + title_format = "{version} ({project_date})" + template = "../../news/_template.rst" + issue_format = "[#{issue}](https://github.com/facebookresearch/hydra/issues/{issue})" + start_string = "\n" + + [[tool.towncrier.type]] + directory = "feature" + name = "Features" + showcontent = true + + [[tool.towncrier.type]] + directory = "api_change" + name = "API Change (Renames, deprecations and removals)" + showcontent = true + + [[tool.towncrier.type]] + directory = "bugfix" + name = "Bug Fixes" + showcontent = true + + [[tool.towncrier.type]] + directory = "config" + name = "Configuration structure changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "docs" + name = "Improved Documentation" + showcontent = true + + [[tool.towncrier.type]] + directory = "maintenance" + name = "Maintenance Changes" + showcontent = true diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/setup.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/setup.py new file mode 100644 index 000000000..491ecc41b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/setup.py @@ -0,0 +1,34 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +# type: ignore +from pathlib import Path + +from read_version import read_version +from setuptools import find_namespace_packages, setup + +setup( + name="hydra-optuna-sweeper", + version=read_version("hydra_plugins/hydra_optuna_sweeper", "__init__.py"), + author="Toshihiko Yanase, Hiroyuki Vincent Yamazaki", + author_email="toshihiko.yanase@gmail.com, hiroyuki.vincent.yamazaki@gmail.com", + description="Hydra Optuna Sweeper plugin", + long_description=(Path(__file__).parent / "README.md").read_text(), + long_description_content_type="text/markdown", + url="https://github.com/facebookresearch/hydra/", + packages=find_namespace_packages(include=["hydra_plugins.*"]), + classifiers=[ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS", + "Development Status :: 4 - Beta", + ], + install_requires=[ + "hydra-core>=1.1.0.dev7", + "optuna>=3.0.0", + ], + include_package_data=True, +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/__init__.py new file mode 100644 index 000000000..168f9979a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/conf/test_deprecated_search_space.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/conf/test_deprecated_search_space.yaml new file mode 100644 index 000000000..f3d11ed8c --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/conf/test_deprecated_search_space.yaml @@ -0,0 +1,20 @@ +defaults: + - override hydra/sweeper: optuna + +hydra: + sweeper: + direction: minimize + study_name: sphere + storage: null + n_trials: 20 + n_jobs: 1 + search_space: + x: + type: float + low: -5.5 + high: 5.5 + step: 0.5 + +x: 1 +y: 1 +z: foo diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/conf/test_grid.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/conf/test_grid.yaml new file mode 100644 index 000000000..bcf1527a9 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/conf/test_grid.yaml @@ -0,0 +1,19 @@ +defaults: + - override hydra/sweeper: optuna + - override hydra/sweeper/sampler: grid + +hydra: + sweeper: + direction: minimize + study_name: sphere + storage: null + n_trials: 20 + n_jobs: 1 + params: + x: choice(-1, 1) + y: range(-1.0, 1.0, step=1) + z: choice("foo", "bar") + +x: 1 +y: 1 +z: foo diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/test_optuna_sweeper_plugin.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/test_optuna_sweeper_plugin.py new file mode 100644 index 000000000..f042937a8 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_optuna_sweeper/tests/test_optuna_sweeper_plugin.py @@ -0,0 +1,393 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import os +import sys +from functools import partial +from pathlib import Path +from typing import Any, List, Optional + +import optuna +from hydra.core.override_parser.overrides_parser import OverridesParser +from hydra.core.plugins import Plugins +from hydra.plugins.sweeper import Sweeper +from hydra.test_utils.test_utils import ( + TSweepRunner, + chdir_plugin_root, + run_process, + run_python_script, +) +from omegaconf import DictConfig, OmegaConf +from optuna.distributions import ( + BaseDistribution, + CategoricalDistribution, + DiscreteUniformDistribution, + IntLogUniformDistribution, + IntUniformDistribution, + LogUniformDistribution, + UniformDistribution, +) +from optuna.samplers import RandomSampler +from pytest import mark, warns + +from hydra_plugins.hydra_optuna_sweeper import _impl +from hydra_plugins.hydra_optuna_sweeper._impl import OptunaSweeperImpl +from hydra_plugins.hydra_optuna_sweeper.config import Direction +from hydra_plugins.hydra_optuna_sweeper.optuna_sweeper import OptunaSweeper + +chdir_plugin_root() + + +def test_discovery() -> None: + assert OptunaSweeper.__name__ in [ + x.__name__ for x in Plugins.instance().discover(Sweeper) + ] + + +def check_distribution(expected: BaseDistribution, actual: BaseDistribution) -> None: + if not isinstance(expected, CategoricalDistribution): + assert expected == actual + return + + assert isinstance(actual, CategoricalDistribution) + # shuffle() will randomize the order of items in choices. + assert set(expected.choices) == set(actual.choices) + + +@mark.parametrize( + "input, expected", + [ + ( + {"type": "categorical", "choices": [1, 2, 3]}, + CategoricalDistribution([1, 2, 3]), + ), + ({"type": "int", "low": 0, "high": 10}, IntUniformDistribution(0, 10)), + ( + {"type": "int", "low": 0, "high": 10, "step": 2}, + IntUniformDistribution(0, 10, step=2), + ), + ({"type": "int", "low": 0, "high": 5}, IntUniformDistribution(0, 5)), + ( + {"type": "int", "low": 1, "high": 100, "log": True}, + IntLogUniformDistribution(1, 100), + ), + ({"type": "float", "low": 0, "high": 1}, UniformDistribution(0, 1)), + ( + {"type": "float", "low": 0, "high": 10, "step": 2}, + DiscreteUniformDistribution(0, 10, 2), + ), + ( + {"type": "float", "low": 1, "high": 100, "log": True}, + LogUniformDistribution(1, 100), + ), + ], +) +def test_create_optuna_distribution_from_config(input: Any, expected: Any) -> None: + actual = _impl.create_optuna_distribution_from_config(input) + check_distribution(expected, actual) + + +@mark.parametrize( + "input, expected", + [ + ("key=choice(1,2)", CategoricalDistribution([1, 2])), + ("key=choice(true, false)", CategoricalDistribution([True, False])), + ("key=choice('hello', 'world')", CategoricalDistribution(["hello", "world"])), + ("key=shuffle(range(1,3))", CategoricalDistribution((1, 2))), + ("key=range(1,3)", IntUniformDistribution(1, 3)), + ("key=interval(1, 5)", UniformDistribution(1, 5)), + ("key=int(interval(1, 5))", IntUniformDistribution(1, 5)), + ("key=tag(log, interval(1, 5))", LogUniformDistribution(1, 5)), + ("key=tag(log, int(interval(1, 5)))", IntLogUniformDistribution(1, 5)), + ("key=range(0.5, 5.5, step=1)", DiscreteUniformDistribution(0.5, 5.5, 1)), + ], +) +def test_create_optuna_distribution_from_override(input: Any, expected: Any) -> None: + parser = OverridesParser.create() + parsed = parser.parse_overrides([input])[0] + actual = _impl.create_optuna_distribution_from_override(parsed) + check_distribution(expected, actual) + + +@mark.parametrize( + "input, expected", + [ + (["key=choice(1,2)"], ({"key": CategoricalDistribution([1, 2])}, {})), + (["key=5"], ({}, {"key": "5"})), + ( + ["key1=choice(1,2)", "key2=5"], + ({"key1": CategoricalDistribution([1, 2])}, {"key2": "5"}), + ), + ( + ["key1=choice(1,2)", "key2=5", "key3=range(1,3)"], + ( + { + "key1": CategoricalDistribution([1, 2]), + "key3": IntUniformDistribution(1, 3), + }, + {"key2": "5"}, + ), + ), + ], +) +def test_create_params_from_overrides(input: Any, expected: Any) -> None: + actual = _impl.create_params_from_overrides(input) + assert actual == expected + + +def test_launch_jobs(hydra_sweep_runner: TSweepRunner) -> None: + sweep = hydra_sweep_runner( + calling_file=None, + calling_module="hydra.test_utils.a_module", + config_path="configs", + config_name="compose.yaml", + task_function=None, + overrides=[ + "hydra/sweeper=optuna", + "hydra/launcher=basic", + "hydra.sweeper.n_trials=8", + "hydra.sweeper.n_jobs=3", + ], + ) + with sweep: + assert sweep.returns is None + + +@mark.parametrize("with_commandline", (True, False)) +def test_optuna_example(with_commandline: bool, tmpdir: Path) -> None: + storage = "sqlite:///" + os.path.join(str(tmpdir), "test.db") + study_name = "test-optuna-example" + cmd = [ + "example/sphere.py", + "--multirun", + "hydra.sweep.dir=" + str(tmpdir), + "hydra.job.chdir=True", + "hydra.sweeper.n_trials=20", + "hydra.sweeper.n_jobs=1", + f"hydra.sweeper.storage={storage}", + f"hydra.sweeper.study_name={study_name}", + "hydra/sweeper/sampler=tpe", + "hydra.sweeper.sampler.seed=123", + "~z", + ] + if with_commandline: + cmd += [ + "x=choice(0, 1, 2)", + "y=0", # Fixed parameter + ] + run_python_script(cmd) + returns = OmegaConf.load(f"{tmpdir}/optimization_results.yaml") + study = optuna.load_study(storage=storage, study_name=study_name) + best_trial = study.best_trial + assert isinstance(returns, DictConfig) + assert returns.name == "optuna" + assert returns["best_params"]["x"] == best_trial.params["x"] + if with_commandline: + assert "y" not in returns["best_params"] + assert "y" not in best_trial.params + else: + assert returns["best_params"]["y"] == best_trial.params["y"] + assert returns["best_value"] == best_trial.value + # Check the search performance of the TPE sampler. + # The threshold is the 95th percentile calculated with 1000 different seed values + # to make the test robust against the detailed implementation of the sampler. + # See https://github.com/facebookresearch/hydra/pull/1746#discussion_r681549830. + assert returns["best_value"] <= 2.27 + + +@mark.parametrize("num_trials", (10, 1)) +def test_example_with_grid_sampler( + tmpdir: Path, + num_trials: int, +) -> None: + storage = "sqlite:///" + os.path.join(str(tmpdir), "test.db") + study_name = "test-grid-sampler" + cmd = [ + "example/sphere.py", + "--multirun", + "--config-dir=tests/conf", + "--config-name=test_grid", + "hydra.sweep.dir=" + str(tmpdir), + "hydra.job.chdir=False", + f"hydra.sweeper.n_trials={num_trials}", + "hydra.sweeper.n_jobs=1", + f"hydra.sweeper.storage={storage}", + f"hydra.sweeper.study_name={study_name}", + ] + run_python_script(cmd) + returns = OmegaConf.load(f"{tmpdir}/optimization_results.yaml") + assert isinstance(returns, DictConfig) + bv, bx, by, bz = ( + returns["best_value"], + returns["best_params"]["x"], + returns["best_params"]["y"], + returns["best_params"]["z"], + ) + if num_trials >= 12: + assert bv == 1 and abs(bx) == 1 and by == 0 + else: + assert bx in [-1, 1] and by in [-1, 0] + assert bz in ["foo", "bar"] + + +@mark.parametrize("with_commandline", (True, False)) +def test_optuna_multi_objective_example(with_commandline: bool, tmpdir: Path) -> None: + cmd = [ + "example/multi-objective.py", + "--multirun", + "hydra.sweep.dir=" + str(tmpdir), + "hydra.job.chdir=True", + "hydra.sweeper.n_trials=20", + "hydra.sweeper.n_jobs=1", + "hydra/sweeper/sampler=random", + "hydra.sweeper.sampler.seed=123", + ] + if with_commandline: + cmd += [ + "x=range(0, 5)", + "y=range(0, 3)", + ] + run_python_script(cmd) + returns = OmegaConf.load(f"{tmpdir}/optimization_results.yaml") + assert isinstance(returns, DictConfig) + assert returns.name == "optuna" + if with_commandline: + for trial_x in returns["solutions"]: + assert trial_x["params"]["x"] % 1 == 0 + assert trial_x["params"]["y"] % 1 == 0 + # The trials must not dominate each other. + for trial_y in returns["solutions"]: + assert not _dominates(trial_x, trial_y) + else: + for trial_x in returns["solutions"]: + assert trial_x["params"]["x"] % 1 in {0, 0.5} + assert trial_x["params"]["y"] % 1 in {0, 0.5} + # The trials must not dominate each other. + for trial_y in returns["solutions"]: + assert not _dominates(trial_x, trial_y) + + +def _dominates(values_x: List[float], values_y: List[float]) -> bool: + return all(x <= y for x, y in zip(values_x, values_y)) and any( + x < y for x, y in zip(values_x, values_y) + ) + + +def test_optuna_custom_search_space_example(tmpdir: Path) -> None: + max_z_difference_from_x = 0.3 + cmd = [ + "example/custom-search-space-objective.py", + "--multirun", + "hydra.sweep.dir=" + str(tmpdir), + "hydra.job.chdir=True", + "hydra.sweeper.n_trials=20", + "hydra.sweeper.n_jobs=1", + "hydra/sweeper/sampler=random", + "hydra.sweeper.sampler.seed=123", + f"max_z_difference_from_x={max_z_difference_from_x}", + ] + run_python_script(cmd) + returns = OmegaConf.load(f"{tmpdir}/optimization_results.yaml") + assert isinstance(returns, DictConfig) + assert returns.name == "optuna" + assert ( + abs(returns["best_params"]["x"] - returns["best_params"]["z"]) + <= max_z_difference_from_x + ) + w = returns["best_params"]["+w"] + assert 0 <= w <= 1 + + +@mark.parametrize( + "search_space,params,raise_warning,msg", + [ + (None, None, False, None), + ( + {}, + {}, + True, + r"Both hydra.sweeper.params and hydra.sweeper.search_space are configured.*", + ), + ( + {}, + None, + True, + r"`hydra.sweeper.search_space` is deprecated and will be removed in the next major release.*", + ), + (None, {}, False, None), + ], +) +def test_warnings( + tmpdir: Path, + search_space: Optional[DictConfig], + params: Optional[DictConfig], + raise_warning: bool, + msg: Optional[str], +) -> None: + partial_sweeper = partial( + OptunaSweeperImpl, + sampler=RandomSampler(), + direction=Direction.minimize, + storage=None, + study_name="test", + n_trials=1, + n_jobs=1, + max_failure_rate=0.0, + custom_search_space=None, + ) + if search_space is not None: + search_space = OmegaConf.create(search_space) + if params is not None: + params = OmegaConf.create(params) + sweeper = partial_sweeper(search_space=search_space, params=params) + if raise_warning: + with warns( + UserWarning, + match=msg, + ): + sweeper._process_searchspace_config() + else: + sweeper._process_searchspace_config() + + +@mark.parametrize("max_failure_rate", (0.5, 1.0)) +def test_failure_rate(max_failure_rate: float, tmpdir: Path) -> None: + cmd = [ + sys.executable, + "example/sphere.py", + "--multirun", + "hydra.sweep.dir=" + str(tmpdir), + "hydra.job.chdir=True", + "hydra.sweeper.n_trials=20", + "hydra.sweeper.n_jobs=2", + "hydra/sweeper/sampler=random", + "hydra.sweeper.sampler.seed=123", + f"hydra.sweeper.max_failure_rate={max_failure_rate}", + "error=true", + ] + out, err = run_process(cmd, print_error=False, raise_exception=False) + error_string = "RuntimeError: cfg.error is True" + if max_failure_rate < 1.0: + assert error_string in err + else: + assert error_string not in err + + +def test_example_with_deprecated_search_space( + tmpdir: Path, +) -> None: + cmd = [ + "-W ignore::UserWarning", + "example/sphere.py", + "--multirun", + "--config-dir=tests/conf", + "--config-name=test_deprecated_search_space", + "hydra.sweep.dir=" + str(tmpdir), + "hydra.job.chdir=True", + "hydra.sweeper.n_trials=20", + "hydra.sweeper.n_jobs=1", + ] + + run_python_script(cmd) + returns = OmegaConf.load(f"{tmpdir}/optimization_results.yaml") + assert isinstance(returns, DictConfig) + assert returns.name == "optuna" + assert abs(returns["best_params"]["x"]) <= 5.5 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/LICENSE b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/LICENSE new file mode 100644 index 000000000..31de3a24c --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 NVIDIA Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/MIT_LICENSE b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/MIT_LICENSE new file mode 100644 index 000000000..b96dcb048 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/MIT_LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/README.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/README.md new file mode 100644 index 000000000..69b304c5b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/README.md @@ -0,0 +1,8 @@ +# Hydra torchrun Launcher +This launcher aims to make it easier to launch a run multi GPU PyTorch training with hydra. It works by creating an Elastic Agent (torchrun launcher class) and forking the main process after hydra is initialized. \ +You can read more on the internals of torchrun [here.](https://pytorch.org/docs/stable/elastic/run.html) + +# Example usage +```bash +python my_app.py -m hydra/launcher=torchrun hydra.launcher.nproc_per_node=8 +``` diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/_core.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/_core.py new file mode 100644 index 000000000..f2140b9bc --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/_core.py @@ -0,0 +1,147 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved + +import logging + +from functools import partial +from pathlib import Path +from typing import Sequence + +from omegaconf import DictConfig, open_dict +from hydra.types import HydraContext +from hydra.core.singleton import Singleton +from hydra.core.hydra_config import HydraConfig +from hydra.types import TaskFunction +from hydra.core.utils import ( + JobReturn, + configure_log, + filter_overrides, + run_job, + setup_globals, + env_override, +) + +from torch.distributed.launcher.api import LaunchConfig, launch_agent +from torch.distributed.elastic.multiprocessing import Std + +from .distributed_launcher import TorchDistributedLauncher + +log = logging.getLogger(__name__) + + +def setup( + launcher: TorchDistributedLauncher, + *, + hydra_context: HydraContext, + task_function: TaskFunction, + config: DictConfig, +) -> None: + launcher.config = config + launcher.hydra_context = hydra_context + launcher.task_function = task_function + + c = config.hydra.launcher + launcher.launch_config = LaunchConfig( + min_nodes=c.min_nodes, + max_nodes=c.max_nodes, + nproc_per_node=c.nproc_per_node, + run_id=c.rdzv_id, + role=c.role, + rdzv_endpoint=c.rdzv_endpoint, + rdzv_backend=c.rdzv_backend, + rdzv_configs={"rank": 0}, + max_restarts=c.max_restarts, + monitor_interval=c.monitor_interval, + # start_method: Works only with fork. + # Spawn and forkserver require pickling which does't work inside wrapped function + start_method="fork", + redirects=Std.from_str(c.redirects), + tee=Std.from_str(c.tee), + log_dir=c.get("log_dir"), + ) + + +def launch( + launcher: TorchDistributedLauncher, + job_overrides: Sequence[Sequence[str]], + initial_job_idx: int, +) -> Sequence[JobReturn]: + """ + :param job_overrides: a List of List, where each inner list is the arguments for one job run. + :param initial_job_idx: Initial job idx in batch. + :return: an array of return values from run_job with indexes corresponding to the input list indexes. + """ + setup_globals() + assert launcher.config is not None + assert launcher.hydra_context is not None + assert launcher.task_function is not None + + configure_log(launcher.config.hydra.hydra_logging, launcher.config.hydra.verbose) + sweep_dir = Path(str(launcher.config.hydra.sweep.dir)) + sweep_dir.mkdir(parents=True, exist_ok=True) + runs = [] + + for idx, overrides in enumerate(job_overrides): + idx = initial_job_idx + idx + lst = " ".join(filter_overrides(overrides)) + log.info(f"\t#{idx} : {lst}") + sweep_config = launcher.hydra_context.config_loader.load_sweep_config( + launcher.config, list(overrides) + ) + with open_dict(sweep_config): + # This typically coming from the underlying scheduler (SLURM_JOB_ID for instance) + # In that case, it will not be available here because we are still in the main process. + # but instead should be populated remotely before calling the task_function. + sweep_config.hydra.job.id = f"job_id_for_{idx}" + sweep_config.hydra.job.num = idx + + HydraConfig.instance().set_config(sweep_config) + launcher.singleton_state = Singleton.get_state() + + def _task_function(task_function, singleton_state, task_cfg): + return launch_agent( + launcher.launch_config, + wrapped_task_function, + [task_function, launcher.singleton_state, task_cfg], + ) + + _task_function = partial( + _task_function, launcher.task_function, launcher.singleton_state + ) + + ret = run_job( + hydra_context=launcher.hydra_context, + task_function=_task_function, + config=sweep_config, + job_dir_key="hydra.sweep.dir", + job_subdir_key="hydra.sweep.subdir", + ) + + # We assume that main process has rank 0 + ret.return_value = ret.return_value[0] + runs.append(ret) + configure_log( + launcher.config.hydra.hydra_logging, launcher.config.hydra.verbose + ) + return runs + + +def wrapped_task_function(task_function, singleton_state, task_cfg): + Singleton.set_state(singleton_state) + env_set = HydraConfig.instance().cfg.hydra.job.env_set + with env_override(env_set): + ret = task_function(task_cfg) + return ret diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/config.py new file mode 100644 index 000000000..194402771 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/config.py @@ -0,0 +1,41 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved + +from dataclasses import dataclass +from hydra.core.config_store import ConfigStore + + +@dataclass +class LauncherConfig: + _target_: str = "hydra_plugins.hydra_torchrun_launcher.distributed_launcher.TorchDistributedLauncher" + min_nodes: int = 1 + max_nodes: int = 1 + nproc_per_node: int = 8 + rdzv_id: str = "none" + role: str = "default" + rdzv_endpoint: str = "127.0.0.1:29500" + rdzv_backend: str = "static" + rdzv_timeout: int = -1 + max_restarts: int = 0 + monitor_interval: int = 5 + log_dir = None + redirects: str = "0" + tee: str = "0" + + +ConfigStore.instance().store( + group="hydra/launcher", name="torchrun", node=LauncherConfig +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/distributed_launcher.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/distributed_launcher.py new file mode 100644 index 000000000..99752a104 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/hydra_plugins/hydra_torchrun_launcher/distributed_launcher.py @@ -0,0 +1,56 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved + + +from typing import Optional, Sequence + +from hydra.types import HydraContext +from hydra.core.utils import JobReturn +from hydra.plugins.launcher import Launcher +from hydra.types import TaskFunction +from omegaconf import DictConfig + + +class TorchDistributedLauncher(Launcher): + def __init__(self, **kwargs) -> None: + self.config: Optional[DictConfig] = None + self.task_function: Optional[TaskFunction] = None + self.hydra_context: Optional[HydraContext] = None + + def setup( + self, + *, + hydra_context: HydraContext, + task_function: TaskFunction, + config: DictConfig, + ) -> None: + from . import _core + + return _core.setup( + launcher=self, + hydra_context=hydra_context, + task_function=task_function, + config=config, + ) + + def launch( + self, job_overrides: Sequence[Sequence[str]], initial_job_idx: int + ) -> Sequence[JobReturn]: + from . import _core + + return _core.launch( + launcher=self, job_overrides=job_overrides, initial_job_idx=initial_job_idx + ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/setup.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/setup.py new file mode 100644 index 000000000..b77920b24 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/setup.py @@ -0,0 +1,35 @@ +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved + +from setuptools import find_namespace_packages, setup + +setup( + name="hydra-torchrun-launcher", + version="0.1", + author="Jan Baczek", + author_email="jbaczek@nvidia.com", + description="Torch distributed launcher plugin", + packages=find_namespace_packages(include=["hydra_plugins.*"]), + classifiers=[ + "License :: OSI Approved :: MIT Apache License, Version 2.0", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + ], + install_requires=["torch>=1.11.0", "hydra-core>=1.1.1"], + include_package_data=True, +) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/tests/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/tests/__init__.py new file mode 100644 index 000000000..168f9979a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/tests/__init__.py @@ -0,0 +1 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/tests/test_torchrun_launcher.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/tests/test_torchrun_launcher.py new file mode 100644 index 000000000..4e4bb156b --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/hydra_torchrun_launcher/tests/test_torchrun_launcher.py @@ -0,0 +1,67 @@ +# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +from hydra.core.plugins import Plugins +from hydra.plugins.launcher import Launcher +from hydra.test_utils.launcher_common_tests import ( + IntegrationTestSuite, + LauncherTestSuite, +) +from hydra.test_utils.test_utils import chdir_plugin_root +from pytest import mark + +from hydra_plugins.hydra_torchrun_launcher.distributed_launcher import ( + TorchDistributedLauncher, +) + +chdir_plugin_root() + + +def test_discovery() -> None: + # Tests that this plugin can be discovered via the plugins subsystem when looking for Launchers + assert TorchDistributedLauncher.__name__ in [ + x.__name__ for x in Plugins.instance().discover(Launcher) + ] + + +@mark.parametrize("launcher_name, overrides", [("torchrun", [])]) +class TestTorechDistributedLauncher(LauncherTestSuite): + """ + Run the Launcher test suite on this launcher. + """ + + pass + + +@mark.parametrize( + "task_launcher_cfg, extra_flags", + [ + ( + {}, + [ + "-m", + "hydra/job_logging=hydra_debug", + "hydra/job_logging=disabled", + "hydra/launcher=torchrun", + ], + ) + ], +) +class TestTorechDistributedLauncherIntegration(IntegrationTestSuite): + """ + Run this launcher through the integration test suite. + """ + + pass diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/optuna_sweeper.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/optuna_sweeper.py new file mode 100644 index 000000000..4cf11d3c4 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_plugins/optuna_sweeper.py @@ -0,0 +1,82 @@ +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +""" +Sweeper plugin interface +""" +from abc import abstractmethod +from collections.abc import Iterator +import typing +from typing import Any, List, Sequence, Optional, Dict, Tuple + +from hydra.types import TaskFunction +from omegaconf import DictConfig +from .launcher import Launcher + +from .plugin import Plugin +from hydra.types import HydraContext + + +class ExperimentSequence(Iterator): + @abstractmethod + def __next__(self): + """Return tuple of experiment id, optional trial object and experiment overrides.""" + raise NotImplementedError() + + def __iter__(self) -> typing.Iterator[Sequence[str]]: + return self + + @abstractmethod + def update_sequence(self, experiment_result: Tuple[Sequence[str], Any]): + """Update experiment generator(study) with experiment results""" + raise NotImplementedError() + + +class Sweeper(Plugin): + """ + An abstract sweeper interface + Sweeper takes the command line arguments, generates a and launches jobs + (where each job typically takes a different command line arguments) + """ + + hydra_context: Optional[HydraContext] + config: Optional[DictConfig] + launcher: Optional[Launcher] + + @abstractmethod + def setup( + self, + *, + hydra_context: HydraContext, + task_function: TaskFunction, + config: DictConfig, + ) -> None: + raise NotImplementedError() + + @abstractmethod + def sweep(self, arguments: List[str]) -> Any: + """ + Execute a sweep + :param arguments: list of strings describing what this sweeper should do. + exact structure is determine by the concrete Sweeper class. + :return: the return objects of all thy launched jobs. structure depends on the Sweeper + implementation. + """ + ... + + def validate_batch_is_legal(self, batch: Sequence[Sequence[str]]) -> None: + """ + Ensures that the given batch can be composed. + This repeat work the launcher will do, but as the launcher may be performing this in a different + process/machine it's important to do it here as well to detect failures early. + """ + config_loader = ( + self.hydra_context.config_loader + if hasattr(self, "hydra_context") and self.hydra_context is not None + else self.config_loader # type: ignore + ) + assert config_loader is not None + + assert self.config is not None + for overrides in batch: + config_loader.load_sweep_config( + master_config=self.config, sweep_overrides=list(overrides) + ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_utils.py index d9aa8640c..ccb0b069f 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/hydra_utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,10 +12,29 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging +import sys +from typing import ( + Any, + Dict, + List, + Optional, + Sequence, + Tuple +) + +import optuna from hydra import compose, initialize from hydra.core.global_hydra import GlobalHydra from hydra.core.hydra_config import HydraConfig from omegaconf import OmegaConf +from optuna.trial import Trial +from hydra.plugins.sweeper import ExperimentSequence +from optuna.distributions import BaseDistribution +import torch + +log = logging.getLogger(__name__) + def get_config(config_name, config_path, override_list=None, return_hydra_config=False): GlobalHydra.instance().clear() @@ -25,3 +44,127 @@ def get_config(config_name, config_path, override_list=None, return_hydra_config HydraConfig().cfg = cfg OmegaConf.resolve(cfg) return cfg + + +class TSPPOptunaExperimentSequence(ExperimentSequence): + def __init__(self, + study, + num_experiments, + search_space_distributions, + fixed_params, + directions, + custom_search_space_extender, + max_failure_rate=0.0, + is_grid_sampler=False) -> None: + self.study = study + self.num_experiments = num_experiments + self.search_space_distributions = search_space_distributions + self.fixed_params = fixed_params + self.directions = directions + self.custom_search_space_extender = custom_search_space_extender + self.max_failure_rate = max_failure_rate + self.fault_tolerance = int(num_experiments * max_failure_rate) + self.is_grid_sampler = is_grid_sampler + self.idx = -1 + self.override_trial_mapping = {} + self.idle_devices = set(range(torch.cuda.device_count())) + self.trial_device = {} + + def _configure_trial( + self, + trial: Trial, + search_space_distributions: Dict[str, BaseDistribution], + fixed_params: Dict[str, Any], + gpu_id: int + ) -> Sequence[str]: + for param_name, distribution in search_space_distributions.items(): + assert type(param_name) is str + trial._suggest(param_name, distribution) + for param_name, value in fixed_params.items(): + trial.set_user_attr(param_name, value) + + if self.custom_search_space_extender: + assert self.config is not None + self.custom_search_space_extender(self.config, trial) + + overlap = trial.params.keys() & trial.user_attrs + if len(overlap): + raise ValueError( + "Overlapping fixed parameters and search space parameters found!" + f"Overlapping parameters: {list(overlap)}" + ) + params = dict(trial.params) + params.update(fixed_params) + params['+hydra.device_id'] = gpu_id + + return tuple(f"{name}={val}" for name, val in params.items()) + + def update_sequence(self, experiment_result: Tuple[Sequence[str], Any]): + override, ret = experiment_result + trial = self.override_trial_mapping[override] + self.idle_devices.add(self.trial_device[trial]) + values: Optional[List[float]] = None + state: optuna.trial.TrialState = optuna.trial.TrialState.COMPLETE + try: + if len(self.directions) == 1: + try: + values = [float(ret.return_value)] + except (ValueError, TypeError): + raise ValueError( + f"Return value must be float-castable. Got '{ret.return_value}'." + ).with_traceback(sys.exc_info()[2]) + else: + try: + values = [float(v) for v in ret.return_value] + except (ValueError, TypeError): + raise ValueError( + "Return value must be a list or tuple of float-castable values." + f" Got '{ret.return_value}'." + ).with_traceback(sys.exc_info()[2]) + if len(values) != len(self.directions): + raise ValueError( + "The number of the values and the number of the objectives are" + f" mismatched. Expect {len(self.directions)}, but actually {len(values)}." + ) + + try: + self.study.tell(trial=trial, state=state, values=values) + except RuntimeError as e: + if ( + self.is_grid_sampler + and "`Study.stop` is supposed to be invoked inside an objective function or a callback." + in str(e) + ): + pass + else: + raise e + + except Exception as e: + state = optuna.trial.TrialState.FAIL + self.study.tell(trial=trial, state=state, values=values) + log.warning(f"Failed experiment: {e}") + self.fault_tolerance -= 1 + + # raise if too many failures + if self.fault_tolerance < 0: + log.error( + f"Failed {int(self.num_experiments * self.max_failure_rate) + 1} times out of {self.num_experiments} " + f"with max_failure_rate={self.max_failure_rate}." + ) + ret.return_value # delegate raising to JobReturn, with actual traceback + + def __next__(self) -> Sequence[str]: + self.idx += 1 + if self.idx < self.num_experiments: + trial = self.study.ask() + assert len(self.idle_devices) > 0, 'Number of simultaneous experiments is greater than number of gpus' + device_id = self.idle_devices.pop() + self.trial_device[trial] = device_id + override = self._configure_trial(trial, self.search_space_distributions, self.fixed_params, device_id) + self.override_trial_mapping[override] = trial + return override + else: + raise StopIteration + + def __len__(self): + return self.num_experiments diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/converter.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/converter.py index be318641e..d46648159 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/converter.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/converter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 import os import shutil @@ -233,4 +234,4 @@ def run_converter(config, export, convert): ], cwd=tspp_main_dir, check=True, - ) \ No newline at end of file + ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/deploy.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/deploy.sh index 4e0ca182e..ac09ae792 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/deploy.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/deploy.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024 NVIDIA CORPORATION. All rights reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -13,30 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -# export TRITON_MODEL_OVERWRITE=True NAV_DIR=$1 NV_VISIBLE_DEVICES=$2 echo "Start" -# Create common bridge for client and server BRIDGE_NAME="bridge" -# docker network create ${BRIDGE_NAME} - -# Clean up -# cleanup() { -# docker kill trt_server_cont -# docker network rm ${BRIDGE_NAME} -# } -# trap cleanup EXIT -# trap cleanup SIGTERM # Start Server echo Starting server... SERVER_ID=$(bash inference/launch_triton_server.sh ${BRIDGE_NAME} ${NAV_DIR} $NV_VISIBLE_DEVICES ) echo $SERVER_ID -# SERVER_IP=$( docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${SERVER_ID} ) - - SERVER_URI="localhost" @@ -62,5 +48,3 @@ while [[ ${current_status} != "200" ]] || [[ $($ready_command) != "200" ]]; do done echo "TRITON Server is ready!" - - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference.py index 0f437b5a6..629893634 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,12 +20,17 @@ import hydra import numpy as np import torch -from apex import amp +import importlib +try: + from apex import amp +except ImportError: + print("Nvidia apex not available. Can't use apex Automatic Mixed Precision (AMP) for training.\ + Please check: https://github.com/NVIDIA/apex for installation") from omegaconf import OmegaConf import conf.conf_utils -from loggers.log_helper import setup_logger from data.data_utils import Preprocessor +from evaluators.evaluator import unpack_predictions def run_inference(config): @@ -62,13 +67,15 @@ def run_inference(config): model.to(device=device) precision = cfg.precision assert precision in ["fp16", "fp32"], "Precision needs to be either fp32 or fp16" - if precision == "fp16": + if precision == "fp16" and importlib.util.find_spec("apex"): model = amp.initialize(model, opt_level="O2") else: model.load(cfg.checkpoint) - preds_full, labels_full, ids_full, weights_full = evaluator.predict(model) - eval_metrics = evaluator.evaluate(preds_full, labels_full, ids_full, weights_full) - logger = setup_logger(cfg) + + predictions_dict = evaluator.predict(model) + preds, labels, ids, weights, timestamps, _ = unpack_predictions(predictions_dict) + eval_metrics = evaluator.evaluate(preds, labels, ids, weights, timestamps) + logger = hydra.utils.call(config.logger) logger.log(step=[], data={k: float(v) for k, v in eval_metrics.items()}, verbosity=dllogger.Verbosity.VERBOSE) logger.log(step='event', data={"String": "Evaluation Metrics: {}".format(eval_metrics)}, verbosity=dllogger.Verbosity.DEFAULT) return eval_metrics diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference_triton.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference_triton.py index 67c42562c..fd0fecdbb 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference_triton.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/inference_triton.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,9 +20,9 @@ from omegaconf import OmegaConf from triton.dataloader import get_dataloader_fn -from loggers.log_helper import setup_logger import dllogger from data.data_utils import Preprocessor +from evaluators.evaluator import unpack_predictions def run_inference_triton(config): cfg = config @@ -70,18 +70,19 @@ def run_inference_triton(config): else: train, valid, test = hydra.utils.call(config.dataset) del train, valid - preds_full, labels_full, ids_full, weights_full = evaluator.predict_xgboost(test, max_batch_size=cfg.batch_size) + predictions_dict = evaluator.predict_xgboost(test, max_batch_size=cfg.batch_size) + preds_full, labels_full, ids_full, weights_full, _ = unpack_predictions(predictions_dict) + elif config.dataset.config.get('stat', False): raise ValueError("Stat models not supported on triton") else: model_name = cfg.get("model_name") if cfg.get("model_name", None) else files_in_store[0] dataloader = get_dataloader_fn(cfg.checkpoint, cfg.batch_size) - preds_full, labels_full, ids_full, weights_full = evaluator.predict(dataloader, model_name) + predictions_dict = evaluator.predict(dataloader, model_name) + preds_full, labels_full, ids_full, weights_full, _ = unpack_predictions(predictions_dict) - #Need to merge the eval configs here - metrics = evaluator.evaluate(preds_full, labels_full, ids_full, weights_full) - logger = setup_logger(cfg) + logger = hydra.utils.call(config.logger) logger.log(step=[], data={k: float(v) for k, v in metrics.items()}, verbosity=dllogger.Verbosity.VERBOSE) logger.log(step='event', data={"String": "Evaluation Metrics: {}".format(metrics)}, verbosity=dllogger.Verbosity.DEFAULT) - print(metrics) \ No newline at end of file + print(metrics) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_inference_server.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_inference_server.py index 6550348e2..998c3c190 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_inference_server.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_inference_server.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 import os import shutil import subprocess @@ -21,7 +21,6 @@ import shutil import hydra from triton.dataloader import get_dataloader_fn -from loggers.log_helper import setup_logger def run_server_launch(config): cfg = config # export model diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_triton_server.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_triton_server.sh index cf462f15a..d88455c1a 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_triton_server.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/launch_triton_server.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024 NVIDIA CORPORATION. All rights reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/stop_docker.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/stop_docker.sh index 35be17f30..ce05ce4b1 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/stop_docker.sh +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/inference/stop_docker.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024 NVIDIA CORPORATION. All rights reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -docker stop trt_server_cont \ No newline at end of file +docker stop trt_server_cont diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_ensembling.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_ensembling.py new file mode 100644 index 000000000..0b4c1114e --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_ensembling.py @@ -0,0 +1,56 @@ +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Script assumes that ensembled models have the same output size (same data and model type). +Aimed to ensemble models from seed/hp sweeps +""" + +import warnings +import os +import hydra +from omegaconf import OmegaConf + +import conf.conf_utils # loads resolvers for OmegaConf +from evaluators.evaluator import unpack_predictions +from training.utils import set_seed +warnings.filterwarnings("ignore") + + +@hydra.main(config_path="conf", config_name="ensemble_conf") +def main(config): + set_seed(config.get("seed", None)) + model_info = config.model.config.model_list[0] + model_dir = model_info.dir + with open(os.path.join(model_dir, '.hydra/config.yaml'), 'rb') as f: + cfg = OmegaConf.load(f) + + if cfg.model._target_ == 'models.tspp_xgboost.TSPPXGBoost': + config.model._target_ = 'models.ensembling.XGBEnsemble' + + model = hydra.utils.instantiate(config.model) + + train, valid, test = hydra.utils.call(cfg.dataset) + del train, valid + + cfg.evaluator.config = {**cfg.evaluator.config, **config.evaluator.config} + evaluator = hydra.utils.instantiate(cfg.evaluator, test_data=test) + predictions_dict = evaluator.predict(model) + preds, labels, ids, weights, timestamps, _ = unpack_predictions(predictions_dict) + eval_metrics = evaluator.evaluate(preds, labels, ids, weights, timestamps) + logger = hydra.utils.call(config.logger) + logger.log(step=[], data=eval_metrics, verbosity=0) + logger.flush() + +if __name__ == '__main__': + main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference.py index eb4422502..d8b5066c4 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + import warnings import hydra diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference_server.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference_server.py index 2e41f6079..e384cb74d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference_server.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_inference_server.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + import warnings import hydra diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_preproc.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_preproc.py index d8133070c..8ce3aa672 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_preproc.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_preproc.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + import warnings import hydra @@ -23,16 +25,27 @@ def main(cfg): print(cfg) preprocessor = hydra.utils.instantiate(cfg, _recursive_=False) - train, valid, test = preprocessor.preprocess() + train, valid, test, train_stat, test_stat = preprocessor.preprocess() + preprocessor.fit_scalers(train) + preprocessor.fit_scalers(train_stat, alt_scaler=True) + train = preprocessor.apply_scalers(train) valid = preprocessor.apply_scalers(valid) test = preprocessor.apply_scalers(test) + + train_stat = preprocessor.apply_scalers(train_stat, alt_scaler=True) + test_stat = preprocessor.apply_scalers(test_stat, alt_scaler=True) + train = preprocessor.impute(train) valid = preprocessor.impute(valid) test = preprocessor.impute(test) + + train_stat = preprocessor.impute(train_stat) + test_stat = preprocessor.impute(test_stat) + preprocessor.save_state() - preprocessor.save_datasets(train, valid, test) + preprocessor.save_datasets(train, valid, test, train_stat, test_stat) if __name__ == "__main__": main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_training.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_training.py index aa9bd285e..dae0bea76 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_training.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_training.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,16 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 +import sys +import gc import warnings -import os + +from hydra.core.hydra_config import HydraConfig +import conf.conf_utils # loads resolvers import hydra -from omegaconf import OmegaConf import torch - -import conf.conf_utils from distributed_utils import is_main_process, init_distributed, init_parallel -from training.utils import set_seed, get_optimization_objectives +from evaluators.evaluator import unpack_predictions from loggers.log_helper import log_parameters +from training.utils import set_seed, get_optimization_objectives + warnings.filterwarnings("ignore") @@ -34,35 +38,62 @@ def main(config): train, valid, test = hydra.utils.call(config.dataset) evaluator = hydra.utils.instantiate(config.evaluator, test_data=test) + logger = hydra.utils.call(config.logger) + log_parameters(logger, config) if 'CTLTrainer' in trainer_type: - init_parallel() init_distributed() - model = model.to(device=config.model.config.device) + model = model.to(device=config.model.config.device) # This has to be done before recursive trainer instantiation trainer = hydra.utils.instantiate( config.trainer, optimizer={'params': model.parameters()}, model=model, train_dataset=train, valid_dataset=valid, + logger=logger, ) - log_parameters(trainer.logger, config) - trainer.train() + try: + trainer.train() + except RuntimeError as e: + if 'CUDNN_STATUS_NOT_INITIALIZED' in str(e): + print(str(e), file=sys.stderr) + print('This happens sometimes. IDK why. Sorry... Exiting gracefully...', file=sys.stderr) + logger.log(step=[], data={}, verbosity=0) # close loggers + return + elif 'CUDA out of memory' in str(e): + print('Job {} caused OOM'.format(HydraConfig.get().job.num), file=sys.stderr) + print(str(e), file=sys.stderr) + print('Exiting gracefully...', file=sys.stderr) + logger.log(step=[], data={}, verbosity=0) # close loggers + return + raise e + if is_main_process(): checkpoint = torch.load("best_checkpoint.zip", map_location=evaluator.device) model.load_state_dict(checkpoint["model_state_dict"]) - preds, labels, ids, weights = evaluator.predict(model) - eval_metrics = evaluator.evaluate(preds, labels, ids, weights) - trainer.logger.log(step=[], data=eval_metrics, verbosity=0) - trainer.logger.flush() + predictions_dict = evaluator.predict(model) + preds, labels, ids, weights, timestamps, figures = unpack_predictions(predictions_dict) + eval_metrics = evaluator.evaluate(preds, labels, ids, weights, timestamps) + logger.log_figures(figures=figures) + logger.log(step=[], data=eval_metrics, verbosity=0) + logger.flush() - del train, valid, test, model, trainer + # This frees memory when using parallel trainings with joblib. We should stress test it + # It leaves some memory though which is hard to tell what allocated it. + # gc.get_objects() indicate that no tensors are left to collect. + # joblib's loky backend reuses processes for efficiency reason and prevents PyTorch to cleanup after itself. + del train, valid, test, model, trainer, evaluator, preds, labels, ids, weights + torch.cuda.synchronize() + gc.collect() torch.cuda.empty_cache() + torch.cuda.ipc_collect() + torch.cuda.synchronize() + objectives = get_optimization_objectives(config, eval_metrics) return objectives - elif 'XGBTrainer' in trainer_type or "StatTrainer" in trainer_type: + elif 'XGBTrainer' in trainer_type: del config.trainer.criterion trainer = hydra.utils.instantiate( @@ -70,13 +101,34 @@ def main(config): model=model, train_dataset=train, valid_dataset=valid, + logger=logger, ) trainer.train() - preds, labels, ids, weights = evaluator.predict(model) - eval_metrics = evaluator.evaluate(preds, labels, ids, weights) - trainer.logger.log(step=[], data=eval_metrics, verbosity=0) + predictions_dict = evaluator.predict(model) + preds, labels, ids, weights, timestamps, _ = unpack_predictions(predictions_dict) + eval_metrics = evaluator.evaluate(preds, labels, ids, weights, timestamps) + logger.log(step=[], data=eval_metrics, verbosity=0) + objectives = get_optimization_objectives(config, eval_metrics) + return objectives + elif "StatTrainer" in trainer_type: + del config.trainer.criterion + + test.test = True + trainer = hydra.utils.instantiate( + config.trainer, + model=model, + train_dataset=train, + valid_dataset=test, + logger=logger, + evaluator=evaluator + ) + + predictions_dict = trainer.train() + preds, labels, ids, weights, timestamps, _ = unpack_predictions(predictions_dict) + eval_metrics = evaluator.evaluate(preds, labels, ids, weights, timestamps) + logger.log(step=[], data=eval_metrics, verbosity=0) objectives = get_optimization_objectives(config, eval_metrics) return objectives else: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_triton_configure.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_triton_configure.py index edf48fcbb..a4dc21a2b 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_triton_configure.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/launch_triton_configure.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + import warnings import hydra diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/backends.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/backends.py index 37b561899..d732f0f8f 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/backends.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/backends.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,20 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os import atexit +import os import time - from collections import OrderedDict -from threading import Thread -from queue import Queue from functools import partial +from queue import Queue +from threading import Thread from typing import Callable -from torch.utils.tensorboard import SummaryWriter +import wandb +import mlflow +from distributed_utils import is_parallel from dllogger import Backend +from mlflow.entities import Metric, Param +from torch.utils.tensorboard import SummaryWriter -from distributed_utils import is_parallel class AverageMeter: def __init__(self): @@ -79,7 +81,7 @@ def elapsed_time(self): class AggregatorBackend(Backend): def __init__(self, verbosity, agg_dict): super().__init__(verbosity=verbosity) - self.metrics = OrderedDict({k: v() for k, v in agg_dict.items()}) + self.metrics = OrderedDict(agg_dict) self.metrics.flushed = True self.step = 0 self.epoch = 0 @@ -154,5 +156,149 @@ def log(self, timestamp, elapsedtime, step, data): for k, v in data.items(): self.summary_writer.add_scalar(k, v, step) + def log_figure(self, fig, name, step): + if not isinstance(step, int): + return + self.summary_writer.add_figure(name, fig, global_step=step) + + def flush(self): + self.summary_writer.flush() + +class AsyncCaller: + STOP_MARK = "__STOP" + + def __init__(self) -> None: + self._q = Queue() + self._stop = False + self._t = Thread(target=self.run, daemon=True) + self._t.start() + + def close(self): + self._q.put(self.STOP_MARK) + + def run(self): + while True: + data = self._q.get() + if data == self.STOP_MARK: + break + data() + + def __call__(self, func, *args, **kwargs): + self._q.put(partial(func, *args, **kwargs)) + + def wait(self, close=True): + if close: + self.close() + self._t.join() + + @staticmethod + def async_dec(ac_attr): + def decorator_func(func): + def wrapper(self, *args, **kwargs): + if isinstance(getattr(self, ac_attr, None), Callable): + return getattr(self, ac_attr)(func, self, *args, **kwargs) + else: + return func(self, *args, **kwargs) + + return wrapper + + return decorator_func + + +class WandBBackend(Backend): + def __init__(self, verbosity): + super().__init__(verbosity=verbosity) + wandb.init() + + @property + def log_level(self): + return self._log_level + + def metadata(self, timestamp, elapsedtime, metric, metadata): + pass + + def log(self, timestamp, elapsedtime, step, data): + close = step == [] or step == () + if step == 'PARAMETER': + wandb.config.update(data) + if not isinstance(step, int): + step = None + wandb.log(data={k: v for k,v in data.items() if isinstance(v, (float, int))}, step=step) + if close: + exit_code = 1 if not data else 0 + wandb.finish(exit_code=exit_code, quiet=True) + + def log_figure(self, fig, name, step): + if not isinstance(step, int): + return + wandb.log({name: fig}, step=step) + def flush(self): pass + + +class MLflowBackend(Backend): + def __init__(self, uri, experiment_name, verbosity): + super().__init__(verbosity=verbosity) + assert not uri.startswith( + "http") or experiment_name, "When specifying remote tracking server, experiment name is mandatory" + + self.client = mlflow.tracking.MlflowClient(tracking_uri=uri) + if experiment_name: + exp = self.client.get_experiment_by_name(experiment_name) + if exp is None: + if is_parallel(): + raise NotImplementedError("For parallel jobs create experiment beforehand") + exp_id = self.client.create_experiment(experiment_name) + else: + exp_id = exp.experiment_id + else: + exp_id = '0' + + self.run = self.client.create_run(exp_id) + + self.async_caller = AsyncCaller() + self.buffer = {'metrics': [], 'params': [], 'tags': []} + + def close(self): + self.async_caller.close() + + @property + def log_level(self): + return self._log_level + + def metadata(self, timestamp, elapsedtime, metric, metadata): + pass + + def log(self, timestamp, elapsedtime, step, data): + timestamp = int(timestamp.timestamp() * 1000) + if step == 'PARAMETER': + for k, v in data.items(): + self.buffer['params'].append(Param(k, str(v))) + elif isinstance(step, int): + for k, v in data.items(): + self.buffer['metrics'].append(Metric(k, v, timestamp, step)) + elif step == []: + for k, v in data.items(): + self.buffer['metrics'].append(Metric(k, v, timestamp, 0)) + self.client.set_terminated(self.run.info.run_id) + self.flush() + self.async_caller.wait(close=True) + + @AsyncCaller.async_dec(ac_attr="async_caller") + def flush(self): + for b in self._batched_buffer(): + self.client.log_batch(self.run.info.run_id, **b) + for k in self.buffer.keys(): + self.buffer[k] = [] + + def _batched_buffer(self): + while sum(len(v) for v in self.buffer.values()) > 0: + batch = {} + capacity = 1000 + for k, v in self.buffer.items(): + _v = v[:capacity] + batch[k] = _v + self.buffer[k] = v[capacity:] + capacity -= len(_v) + yield batch diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/log_helper.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/log_helper.py index 41e34ee1c..7e3d7cc92 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/log_helper.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/loggers/log_helper.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,23 +12,47 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 import os import json import pandas as pd import dllogger -from dllogger import JSONStreamBackend, Logger, StdOutBackend -from .backends import AggregatorBackend, TensorBoardBackend, AverageMeter +from dllogger import Logger +from .backends import TensorBoardBackend, WandBBackend from omegaconf import OmegaConf from distributed_utils import is_main_process + +FIGURE_LOGGERS = (TensorBoardBackend, WandBBackend) + + +class ExtendedLogger(Logger): + def __init__(self, *args, **kwargs): + super(ExtendedLogger, self).__init__(*args, **kwargs) + self._init_figure_loggers() + + def _init_figure_loggers(self): + figure_loggers = [logger for logger in self.backends if isinstance(logger, FIGURE_LOGGERS)] + if not figure_loggers: + figure_loggers = None + self.figure_loggers = figure_loggers + + def log_figures(self, figures=None): + if self.figure_loggers is None or not figures: + return + for fig, name, step in figures: + for logger in self.figure_loggers: + logger.log_figure(fig=fig, name=name, step=step) + + def jsonlog_2_df(path, keys): with open(path, 'r') as f: log = [json.loads(l[4:]) for l in f.readlines()] log = [l for l in log if l['type'] == 'LOG' and isinstance(l['step'], (int, list))] assert log[-1]['step'] == [], "Logfile is corrupted" - log[-1]['step']=log[-2]['step'] # Every log ends with step == [] + log[-1]['step'] = log[-2]['step'] # Every log ends with step == [] log = [ { **{k:v for k,v in l.items() if not isinstance(v, dict)}, @@ -42,6 +66,7 @@ def jsonlog_2_df(path, keys): df = df.groupby('step').mean() return df + def empty_step_format(step): return "" @@ -58,45 +83,29 @@ def no_string_metric_format(metric, metadata, value): return "{} : {} {}".format(metric, format.format(value) if value is not None else value, unit) -def setup_logger(config, resume_training=False): - log_filename = config.get("log_filename", "log.json") +def setup_logger(backends=[]):#, resume_training=False): if is_main_process(): - backends = [ - TensorBoardBackend(verbosity=dllogger.Verbosity.VERBOSE), - JSONStreamBackend(verbosity=dllogger.Verbosity.VERBOSE, filename=log_filename, append=True), - AggregatorBackend(verbosity=dllogger.Verbosity.VERBOSE, agg_dict={"loss": AverageMeter}), - StdOutBackend( - verbosity=dllogger.Verbosity.DEFAULT, - step_format=empty_step_format, - metric_format=no_string_metric_format, - prefix_format=empty_prefix_format, - ), - ] - - logger = Logger(backends=backends) + logger = ExtendedLogger(backends=backends) else: - logger = Logger(backends=[]) + logger = ExtendedLogger(backends=[]) container_setup_info = get_framework_env_vars() logger.log(step="PARAMETER", data=container_setup_info, verbosity=dllogger.Verbosity.VERBOSE) + logger.metadata("loss", {"unit": "nat", "GOAL": "MINIMIZE", "STAGE": "TRAIN"}) + logger.metadata("val_loss", {"unit": "nat", "GOAL": "MINIMIZE", "STAGE": "VAL"}) - if not resume_training: - logger.metadata("loss", {"unit": "nat", "GOAL": "MINIMIZE", "STAGE": "TRAIN"}) - logger.metadata("val_loss", {"unit": "nat", "GOAL": "MINIMIZE", "STAGE": "VAL"}) return logger -def restart_logger(config, logger): - """An utility function to nealty close every backend holding resources""" - for b in logger.backends: - if hasattr(b, 'close'): - b.close() - return setup_logger(config, resume_training=True) def log_parameters(logger, config): model_config = flatten_config(config.model) trainer_config = flatten_config(config.trainer) additional_fields = {'seed': config.seed} - logger.log(step="PARAMETER", data={**model_config, **trainer_config, **additional_fields}, verbosity=dllogger.Verbosity.VERBOSE) + logger.log(step="PARAMETER", + data={**model_config, **trainer_config, **additional_fields}, + verbosity=dllogger.Verbosity.VERBOSE + ) + def flatten_config(config): config = OmegaConf.to_container(config, resolve=True) @@ -110,6 +119,7 @@ def flatten_config(config): config = config.to_dict(orient='records')[0] return config + def get_framework_env_vars(): return { "NVIDIA_PYTORCH_VERSION": os.environ.get("NVIDIA_PYTORCH_VERSION"), diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/dcrnn.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/dcrnn.py new file mode 100644 index 000000000..66433025a --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/dcrnn.py @@ -0,0 +1,283 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import torch +import torch.nn as nn +import scipy.sparse as sp +from scipy.sparse import linalg +import dgl +import dgl.function as fn +import dgl.ops as ops + +from .tft_pyt.modeling import LazyEmbedding + +def calculate_normalized_laplacian(adj): + """ + # L = D^-1/2 (D-A) D^-1/2 = I - D^-1/2 A D^-1/2 + # D = diag(A 1) + :param adj: + :return: + """ + adj = sp.coo_matrix(adj) + d = np.array(adj.sum(1)) + d_inv_sqrt = np.power(d, -0.5).flatten() + d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0. + d_mat_inv_sqrt = sp.diags(d_inv_sqrt) + normalized_laplacian = sp.eye(adj.shape[0]) - adj.dot(d_mat_inv_sqrt).transpose().dot(d_mat_inv_sqrt).tocoo() + return normalized_laplacian + + +def calculate_random_walk_matrix(adj_mx): + d = np.array(adj_mx.sum(1)) + d_inv = np.power(d, -1).flatten() + d_inv[np.isinf(d_inv)] = 0. + d_mat_inv = np.diag(d_inv) + random_walk_mx = d_mat_inv.dot(adj_mx) + random_walk_mx = torch.from_numpy(random_walk_mx) + return random_walk_mx + + +def calculate_dual_random_walk_matrix(adj_mx): + L0 = calculate_random_walk_matrix(adj_mx).T + L1 = calculate_random_walk_matrix(adj_mx.T).T + return L0, L1 + + +def calculate_scaled_laplacian(adj_mx, lambda_max=2, undirected=True): + if undirected: + adj_mx = np.maximum.reduce([adj_mx, adj_mx.T]) + L = calculate_normalized_laplacian(adj_mx) + if lambda_max is None: + lambda_max, _ = linalg.eigsh(L, 1, which='LM') + lambda_max = lambda_max[0] + L = sp.csr_matrix(L) + M, _ = L.shape + I = sp.identity(M, format='csr', dtype=L.dtype) + L = (2 / lambda_max * L) - I + L = L.astype(np.float32).todense() + return torch.from_numpy(L) + + +class DCGRUCell(torch.nn.Module): + def __init__(self, num_units, max_diffusion_step, nonlinearity='tanh'): + super().__init__() + self._activation = torch.tanh if nonlinearity == 'tanh' else torch.relu + self._num_units = num_units + self.gconv1 = Gconv(self._num_units*2, self._num_units, max_diffusion_step, 0.0) + self.gconv2 = Gconv(self._num_units, self._num_units, max_diffusion_step, 0.0) + + def forward(self, graph, inputs, hx): + """Gated recurrent unit (GRU) with Graph Convolution. + """ + _inputs = torch.cat([inputs, hx], dim=-1) + x = self.gconv1(graph, _inputs) + + value = torch.sigmoid(x) + r, u = value.chunk(2, dim=-1) + + _inputs = torch.cat([inputs, r * hx], dim=-1) + c = self.gconv2(graph, _inputs) + + if self._activation is not None: + c = self._activation(c) + + new_state = u * hx + (1.0 - u) * c + return new_state + + +class Gconv(torch.nn.Module): + def __init__(self, output_size, hidden_size, max_diffusion_step, bias_start=0.0): + assert max_diffusion_step > 0 + super().__init__() + self.output_size = output_size + self.hidden_size = hidden_size + self._max_diffusion_step = max_diffusion_step + + self.num_matrices = 2 * self._max_diffusion_step + 1 + self.lin = torch.nn.LazyLinear(self.output_size) + def _reset_parameters(self): + torch.nn.init.xavier_normal_(self.weight) + torch.nn.init.constant_(self.bias, bias_start) + bound_method = _reset_parameters.__get__(self.lin, self.lin.__class__) + self.lin.reset_parameters = bound_method + + @staticmethod + def calculate_random_walk_matrix(adj_mx): + d = adj_mx.sum(1) + d_inv = d.pow(-1) + d_inv[torch.isinf(d_inv)] = 0. + random_walk_mx = d_inv.unsqueeze(1).mul(adj_mx) + return random_walk_mx + + + def rwLaplacian(self,feat, graph): + rev = graph.reverse() + + # L0 + out_degree = ops.copy_e_sum(rev, graph.edata['w']) #adj_mx.sum(1) + graph.ndata['_h'] = feat[...,0] * out_degree.pow(-1).unsqueeze(-1) + graph.update_all(fn.u_mul_e('_h', 'w', 'm') , fn.sum('m', '_h')) + + # L1 + in_degree = ops.copy_e_sum(graph, graph.edata['w']) #adj_mx.sum(0) + rev.edata['w'] = graph.edata['w'] + rev.ndata['_h'] = feat[...,1] * in_degree.pow(-1).unsqueeze(-1) + rev.update_all(fn.u_mul_e('_h', 'w', 'm') , fn.sum('m', '_h')) + + return torch.stack((graph.ndata.pop('_h'), rev.ndata.pop('_h')), dim=-1) + + def forward(self, graph, inputs): + batch_size = graph.batch_size + + # Caching + # We assume that all graphs are the same in sructure! + if not hasattr(self, 'adj_mx'): + with torch.no_grad(): + samples = dgl.unbatch(graph) + adj_mx = torch.sparse_coo_tensor(indices=samples[0].adjacency_matrix().coalesce().indices().to(inputs.device), + values=samples[0].edata['w'].to(inputs.device)).to_dense() + L0 = Gconv.calculate_random_walk_matrix(adj_mx).T + L1 = Gconv.calculate_random_walk_matrix(adj_mx.T).T + self.register_buffer('adj_mx', adj_mx, persistent=False) + self.register_buffer('L0', L0, persistent=False) + self.register_buffer('L1', L1, persistent=False) + if hasattr(self, f'L_{batch_size}'): + L = getattr(self, f'L_{batch_size}') + else: + L = torch.block_diag(*[l for l in (self.L0,self.L1) for _ in range(batch_size)]).to_sparse() + setattr(self, f'L_{batch_size}', L) + + x0 = torch.cat((inputs,inputs), dim=0) + x1 = torch.sparse.mm(L, x0) + dif_outs = [inputs, *x1.chunk(2, dim=0)] + + for k in range(2, self._max_diffusion_step + 1): + x2 = 2 * torch.sparse.mm(L, x1) - x0 + dif_outs += x2.chunk(2, dim=0) + x1, x0 = x2, x1 + + x = torch.stack(dif_outs, dim=-1) + x = x.reshape(graph.num_nodes(), -1) + x = self.lin(x) + return x + + + +class RNNStack(nn.Module): + def __init__(self, num_rnn_layers, max_diffusion_step, rnn_units, nonlinearity='tanh'): + super().__init__() + self.num_rnn_layers = num_rnn_layers + self.rnn_units = rnn_units + self.dcgru_layers = nn.ModuleList([DCGRUCell(rnn_units, max_diffusion_step, nonlinearity=nonlinearity) for _ in range(self.num_rnn_layers)]) + + def forward(self, graph, inputs, hidden_state=None): + if hidden_state is None: + hidden_state = inputs.new_zeros((self.num_rnn_layers, graph.num_nodes(), self.rnn_units)) + + hidden_states = [] + output = inputs + for layer_num, dcgru_layer in enumerate(self.dcgru_layers): + next_hidden_state = dcgru_layer(graph, output, hidden_state[layer_num]) + hidden_states.append(next_hidden_state) + output = next_hidden_state + + return output, torch.stack(hidden_states) # runs in O(num_layers) so not too slow + +class DCRNN(nn.Module): + def __init__(self, config): + super().__init__() + self.config = config + self.max_diffusion_step = int(config.get('max_diffusion_step', 2)) + self.num_nodes = int(config.get('num_nodes', 1)) + self.num_rnn_layers = int(config.get('num_rnn_layers', 1)) + self.rnn_units = int(config.get('rnn_units')) + self.activation = config.get('activation') + self.output_dim = int(config.get('output_dim', 1)) + self.horizon = int(config.get('horizon', 1)) # for the decoder + self.encoder_model = RNNStack(self.num_rnn_layers, self.max_diffusion_step, self.rnn_units, self.activation) + self.projection_layer = nn.Linear(self.rnn_units, self.output_dim) + self.decoder_model = RNNStack(self.num_rnn_layers, self.max_diffusion_step, self.rnn_units, self.activation) + self.cl_decay_steps = int(config.get('cl_decay_steps', 1000)) + self.use_curriculum_learning = bool(config.get('use_curriculum_learning', False)) + self.seq_len = int(config.get('encoder_length')) # for the encoder + self.batches_seen = 0 + + self.use_embedding = config.use_embedding + ### New embedding + if self.use_embedding: + self.config.hidden_size = self.config.input_dim + self.embedding = LazyEmbedding(self.config) + self.include_static_data = config.get('include_static_data', False) + #### + + def _compute_sampling_threshold(self, batches_seen): + return self.cl_decay_steps / ( + self.cl_decay_steps + np.exp(batches_seen / self.cl_decay_steps)) + + def encoder(self, graph): + encoder_hidden_state = None + h = graph.ndata['h'] + for t in range(self.seq_len): + _, encoder_hidden_state = self.encoder_model(graph, h[:,t], encoder_hidden_state) + + return encoder_hidden_state + + def decoder(self, graph, encoder_hidden_state, labels=None): + decoder_hidden_state = encoder_hidden_state + decoder_input = encoder_hidden_state.new_zeros((graph.num_nodes(), 1)) + + outputs = [] + + for t in range(self.horizon): + decoder_output, decoder_hidden_state = self.decoder_model(graph, decoder_input, decoder_hidden_state) + decoder_output = self.projection_layer(decoder_output) + decoder_input = decoder_output + outputs.append(decoder_output) + if self.training and self.use_curriculum_learning: + c = np.random.uniform(0, 1) + if c < self._compute_sampling_threshold(self.batches_seen): + decoder_input = labels[:,t].view(-1,1) + outputs = torch.stack(outputs, dim=1) + return outputs + + def forward(self, batch): + if self.use_embedding: + # New embedding + _batch = { + k:v[:, :self.seq_len] + if v is not None and v.numel() else None + for k,v in batch.ndata.items() + if 'ID' not in k and 'id' not in k + } + emb = self.embedding(_batch) + emb = [e.view(*e.shape[:-2], -1) for e in emb if e is not None] + emb[0] = emb[0].unsqueeze(1).expand(emb[0].shape[0], self.seq_len, *emb[0].shape[1:]) + if not self.include_static_data: + emb = emb[1:] + batch.ndata['h'] = torch.cat(emb, dim=-1) + #### + else: + t = batch.ndata['k_cont'][:, :self.seq_len, 2:] + t = torch.einsum('btk,k->bt', t, t.new([1, 0.16])) + batch.ndata['h'] = torch.cat([batch.ndata['target'][:, :self.seq_len], t.unsqueeze(-1)], dim=-1) + + if self.training: + labels = batch.ndata['target'][:, self.seq_len:].view(-1, self.num_nodes, self.horizon).transpose(1,2) + else: + labels = None + + encoder_hidden_state = self.encoder(batch) + outputs = self.decoder(batch, encoder_hidden_state, labels) + self.batches_seen += 1 + return outputs diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/deepar.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/deepar.py new file mode 100644 index 000000000..d46846b97 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/deepar.py @@ -0,0 +1,147 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn +from .tft_pyt.modeling import LazyEmbedding + +class DeepAR(nn.Module): + def __init__(self, config): + super().__init__() + + self.config = config + self.encoder_length = config.encoder_length + self.register_buffer('quantiles', torch.FloatTensor(config.quantiles), persistent=False) + self.use_embedding = self.config.use_embedding + + if self.config.use_embedding: + ### New Embedding + # DeepAR can't currenty work with observed data + config.num_historic_vars -= len(config.temporal_observed_categorical_inp_lens) + config.num_historic_vars -= config.temporal_observed_continuous_inp_size + config.temporal_observed_categorical_inp_lens = [] + config.temporal_observed_continuous_inp_size = 0 + _config = config.copy() + _config.hidden_size = self.config.embedding_dim + self.embedding_v2 = LazyEmbedding(_config) + inp_size = (config.num_static_vars + config.num_historic_vars) * config.embedding_dim + else: + self.embedding = nn.ModuleList([ + nn.Embedding(n, config.embedding_dim) + for n in config.static_categorical_inp_lens + config.temporal_known_categorical_inp_lens + ]) + + inp_size = config.temporal_known_continuous_inp_size + len(self.embedding) * config.embedding_dim + 1 # +1 for target + + self.lstm = nn.LSTM(input_size=inp_size, + hidden_size=config.hidden_size, + num_layers=config.num_layers, + bias=True, + batch_first=True, + dropout=config.dropout) + for names in self.lstm._all_weights: + for name in filter(lambda n: "bias" in n, names): + bias = getattr(self.lstm, name) + n = bias.size(0) + start, end = n // 4, n // 2 + bias.data[start:end].fill_(1.) + + self.relu = nn.ReLU() + self.distribution_mu = nn.Linear(config.hidden_size * config.num_layers, 1) + self.distribution_presigma = nn.Linear(config.hidden_size * config.num_layers, 1) + self.distribution_sigma = nn.Softplus() + + def _roll_data(x): + if x is None: + return None + x = torch.roll(x, 1, 1) + x[:,0] = 0 + return x + def forward(self, batch): + if self.use_embedding: + return self._forward_v2(batch) + else: + return self._forward_v1(batch) + + + def _forward_v2(self, batch): + batch = batch.copy() # shallow copy to replace observables in this scope + batch['target'] = DeepAR._roll_data(batch['target']) + batch['weight'] = DeepAR._roll_data(batch['weight']) + batch['o_cat'] = None + batch['o_cont'] = None + + emb = self.embedding_v2(batch) + emb = [x for x in emb if x is not None] + emb[0] = emb[0].unsqueeze(1).expand(emb[0].shape[0], emb[1].shape[1], *emb[0].shape[1:]) + emb = torch.cat(emb, axis=-2) + emb = emb.view(*emb.shape[:-2], -1) + + state = None + mus = [] + sigs = [] + for t in range(emb.shape[1]): + zero_index = (batch['target'][:, t, 0] == 0) + if t > 0 and torch.sum(zero_index) > 0: + _x = torch.matmul(mu[zero_index].unsqueeze(-1), self.embedding_v2.t_tgt_embedding_vectors) + _x = _x + self.embedding_v2.t_tgt_embedding_bias + emb[zero_index, t, -self.config.embedding_dim:] = _x # target embedding is the last to be concatenated + mu, sigma, state = self._forward_ar(emb[:,t].unsqueeze(1), state) + + mus.append(mu) + sigs.append(sigma) + + mus = torch.stack(mus, dim=1) + sigs = torch.stack(sigs, dim=1) + + return torch.stack((mus, sigs), dim=-1) + + def _forward_v1(self, batch): + cat = torch.cat([batch['s_cat'], batch['k_cat']], dim=-1).permute(2,0,1) + emb = torch.cat([e(t) for e, t in zip(self.embedding, cat)], dim=-1) + target = torch.roll(batch['target'], 1, 1) + target[:, 0] = 0 + x = torch.cat((target, batch['k_cont'], emb), dim=-1) + + state = None + mus = [] + sigs = [] + for t in range(x.shape[1]): + zero_index = (x[:, t, 0] == 0) + if t > 0 and torch.sum(zero_index) > 0: + x[zero_index, t, 0] = mu[zero_index] + + mu, sigma, state = self._forward_ar(x[:, t].unsqueeze(1), state) + + mus.append(mu) + sigs.append(sigma) + + mus = torch.stack(mus, dim=1) + sigs = torch.stack(sigs, dim=1) + + return torch.stack((mus, sigs), dim=-1) + + def _forward_ar(self, x, state): + output, state = self.lstm(x, state) + hidden = state[0] + hidden_permute = hidden.permute(1, 2, 0).contiguous().view(hidden.shape[1], -1) + pre_sigma = self.distribution_presigma(hidden_permute) + mu = self.distribution_mu(hidden_permute) + sigma = self.distribution_sigma(pre_sigma) # softplus to make sure standard deviation is positive + return torch.squeeze(mu), torch.squeeze(sigma), state + + def predict(self, batch): + preds = self.forward(batch) + preds = preds[:, self.encoder_length:, :] + preds = torch.stack([preds[..., 0] + preds[..., 1] * torch.erfinv(2 * q - 1) * 1.4142135623730951 for q in self.quantiles], dim=-1) + return preds diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/deepar_v2.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/deepar_v2.py new file mode 100644 index 000000000..0ef0ed4e4 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/deepar_v2.py @@ -0,0 +1,147 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +'''Defines the neural network, loss function and metrics''' + +import math +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch.autograd import Variable +from .tft_pyt.modeling import LazyEmbedding +import torch +from torch import nn + +class AutoregressiveLSTM(nn.Module): + def __init__(self, input_size, hidden_size, embed_size, num_layers, dropout, tgt_embed): + super(AutoregressiveLSTM, self).__init__() + self.hidden_size = hidden_size + self.embed_size = embed_size + self.num_layers = num_layers + self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, dropout=dropout) + self.tgt_embed = tgt_embed + + # This is a modification to the more general algorithm implemented here that uses all the layer's hidden states to make a final prediction + # This is not what is described in the paper but is what reference implementation did + # In this particular case it is used for expected value (mu) estimation + self.mu_proj = nn.Linear(hidden_size * num_layers, 1) + self.sig_proj = nn.Sequential( + nn.Linear(hidden_size * num_layers, 1), + nn.Softplus() + ) + + + def forward(self, inputs, embedded_labels, hidden=None, mask=None): + # Inputs should be all covariate embeddings and embedded labels should be target emdeddings + + mus = [] + sigs = [] + for i in range(inputs.shape[1]): + input = inputs[:,i] + if embedded_labels is None or mask is None: + mu_embed = self.tgt_embed(mu) + input = torch.cat((input, mu_embed), dim=-1) + elif i and mask[:,i].any(): + mu_embed = self.tgt_embed(mu) + input = torch.cat((input, torch.where(mask[:, i], mu_embed, embedded_labels[:, i])), dim=-1) + else: + input = torch.cat((input, embedded_labels[:, i]), dim=-1) + + _, hidden = self.lstm(input.unsqueeze(1), hidden) + hidden_permute = hidden[0].permute(1, 2, 0).contiguous().view(hidden[0].shape[1], -1) + mu = self.mu_proj(hidden_permute) + + sig = self.sig_proj(hidden_permute) + + mus.append(mu) + sigs.append(sig) + + mus = torch.cat(mus, dim=1) + sigs = torch.cat(sigs, dim=1) + return mus, sigs, hidden + + +class DeepAR(nn.Module): + def __init__(self, config): + super().__init__() + + self.config = config + self.encoder_length = config.encoder_length + self.example_length = config.example_length + self.register_buffer('quantiles', torch.FloatTensor(config.quantiles), persistent=False) + self.use_embedding = self.config.use_embedding + self.drop_variance = self.config.get('drop_variance', False) + + _config = config.copy() + _config.hidden_size = self.config.embedding_dim + _config.num_historic_vars -= len(config.temporal_observed_categorical_inp_lens) + _config.num_historic_vars -= config.temporal_observed_continuous_inp_size + _config.temporal_observed_categorical_inp_lens = [] + _config.temporal_observed_continuous_inp_size = 0 + + self.embedding_v2 = LazyEmbedding(_config) + tgt_embed = lambda x: torch.matmul(x, self.embedding_v2.t_tgt_embedding_vectors) + self.embedding_v2.t_tgt_embedding_bias + + inp_size = (config.num_static_vars + config.num_future_vars + config.temporal_target_size) * config.embedding_dim + + self.encoder = AutoregressiveLSTM(input_size=inp_size, + hidden_size=config.hidden_size, + embed_size=config.embedding_dim, + num_layers=config.num_layers, + dropout=config.dropout, + tgt_embed=tgt_embed) + + def _roll_data(x): + if x is None: + return None + x = torch.roll(x, 1, 1) + x[:,0] = 0 + return x + + + def forward(self, batch, predict=False): + batch = batch.copy() # shallow copy to replace observables in this scope + batch['target'] = DeepAR._roll_data(batch['target']) + batch['weight'] = DeepAR._roll_data(batch['weight']) + batch['o_cat'] = None + batch['o_cont'] = None + + s_emb, k_emb, _, tgt_emb = self.embedding_v2(batch) + s_emb = s_emb.unsqueeze(1).expand(s_emb.shape[0], tgt_emb.shape[1], *s_emb.shape[1:]) + + feat = torch.cat((s_emb, k_emb) , axis=-2) + feat = feat.view(*feat.shape[:-2], -1) + tgt_emb = tgt_emb.view(*tgt_emb.shape[:-2], -1) + + if batch['weight'] is not None: + mask = batch['weight'] == 0 + else: + mask = batch['target'] == 0 + + if predict: + mask[:, self.encoder_length:] = True + + mus, sigs, _ = self.encoder(feat, embedded_labels=tgt_emb, mask=mask) + + if self.drop_variance: + return mus.unsqueeze(-1) + return torch.stack((mus, sigs), dim=-1) + + def predict(self, batch): + preds = self.forward(batch, predict=True) + preds = preds[:,self.encoder_length:, :] + if self.drop_variance: + return preds + preds = torch.stack([preds[...,0] + preds[...,1] * torch.erfinv(2 * q - 1) * 1.4142135623730951 for q in self.quantiles], dim=-1) + return preds diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/ensembling.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/ensembling.py new file mode 100644 index 000000000..227368245 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/ensembling.py @@ -0,0 +1,123 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +import hydra +from omegaconf import OmegaConf +import torch +from torch import nn, Tensor +from typing import Dict +from training.utils import to_device + + +class ModelEnsemble(nn.Module): + def __init__(self, config): + super().__init__() + self.config = config + self.reduction_stategy = config.get('reduction_strategy', 'mean') + self.model_weights = [] + self.model_list = [] + for model_info in self.config.model_list: + self.model_weights.append(model_info.get('weight', 1.0)) + + model_dir = model_info.dir + with open(os.path.join(model_dir, '.hydra/config.yaml'), 'rb') as f: + cfg = OmegaConf.load(f) + model: nn.Module = hydra.utils.instantiate(cfg.model) + if not(cfg.dataset.config.get('xgb', False) or cfg.dataset.config.get('stat', False)): + # reduce gpu memory usage + state_dict = torch.load(os.path.join(model_dir, model_info.get('checkpoint', 'best_checkpoint.zip')), map_location='cpu')['model_state_dict'] + model.load_state_dict(state_dict) + else: + raise ValueError('XGB and stat models are currently not supported by ensembling.') + self.model_list.append(model) + + self.num_devices = min(torch.cuda.device_count(), len(self.model_list)) + model_splits = [self.model_list[i::self.num_devices] for i in range(self.num_devices)] + model_splits = [nn.ModuleList(x).to(f'cuda:{i}') for i, x in enumerate(model_splits)] + self.model_splits = nn.ModuleList(model_splits) + + self.model_weights = [x for y in [self.model_weights[i::self.num_devices] for i in range(self.num_devices)] for x in y] + + @staticmethod + def _reduce_preds(preds, weights, reduction_stategy): + if reduction_stategy not in ['mean', 'sum']: + raise ValueError(f'Unknown reduction strategy: {reduction_stategy}') + + result = sum(p * w for p, w in zip(preds, weights)) + if reduction_stategy == 'mean': + result /= sum(weights) + + return result + + @staticmethod + def _replicate(batch, n): + return [to_device(batch, i) for i in range(n)] + + @torch.no_grad() + def forward(self, x: Dict[str, Tensor]) -> Tensor: + _x = self._replicate(x, self.num_devices) + preds = [[] for _ in range(self.num_devices)] + + for i, (data, split) in enumerate(zip(_x, self.model_splits)): + for model in split: + test_method_name = 'predict' if hasattr(model, 'predict') else '__call__' + test_method = getattr(model, test_method_name) + pred = test_method(data) + # Move all preds to cpu. Probably it will have a terrible performance, but we have tons of memory there + preds[i].append(pred.cpu()) + + preds = [x for y in preds for x in y] + preds = self._reduce_preds(preds, self.model_weights, self.reduction_stategy) + + return preds + +class XGBEnsemble: + def __init__(self, config): + super().__init__() + self.config = config + self.reduction_stategy = config.get('reduction_strategy', 'mean') + self.model_weights = [] + self.model_list = [] + for model_info in self.config.model_list: + self.model_weights.append(model_info.get('weight', 1.0)) + + model_dir = model_info.dir + with open(os.path.join(model_dir, '.hydra/config.yaml'), 'rb') as f: + cfg = OmegaConf.load(f) + model: nn.Module = hydra.utils.instantiate(cfg.model) + model.load(model_dir) + self.model_list.append(model) + + @staticmethod + def _reduce_preds(preds, weights, reduction_stategy): + if reduction_stategy not in ['mean', 'sum']: + raise ValueError(f'Unknown reduction strategy: {reduction_stategy}') + + result = sum(p * w for p, w in zip(preds, weights)) + if reduction_stategy == 'mean': + result /= sum(weights) + + return result + + def predict(self, x, i): + preds = [] + + for model in self.model_list: + pred = model.predict(x, i) + preds.append(pred) + + preds = self._reduce_preds(preds, self.model_weights, self.reduction_stategy) + + return preds diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/gnn.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/gnn.py new file mode 100644 index 000000000..a8ee7aaf5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/gnn.py @@ -0,0 +1,296 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn +from typing import Optional, Tuple, Dict +from torch import Tensor +import dgl +from dgl.nn.pytorch.conv import GraphConv + +import networkx as nx +import numpy as np +from copy import copy + +def list_contract_nodes_(graph, l_nodes): + """ + l_nodes: List[List[Int]]: nodes to merge + Returns node mapping + """ + pooled_feat = [] + _nodes_flat = [x for y in l_nodes for x in y] + + _unmerged_nodes = list(range(graph.num_nodes())) + for n in _nodes_flat: + _unmerged_nodes.remove(n) + + node_mapping = {i:[n] for i,n in enumerate(_unmerged_nodes)} + num_nodes = graph.num_nodes() + i = 0 + while l_nodes: + nodes = l_nodes.pop() + # Add features + ndata = {k:v[nodes].mean() for k, v in graph.ndata.items()} + pooled_feat.append({k: v[nodes].mean(dim=0) for k,v in graph.ndata.items()}) + # Add edges + predecessors = torch.cat([graph.predecessors(n) for n in nodes]) + successors = torch.cat([graph.successors(n) for n in nodes]) + nidx = graph.num_nodes() + graph.add_edges(torch.full_like(predecessors, nidx), predecessors) + graph.add_edges(torch.full_like(successors, nidx), successors) + # Add key to super node mapping + node_mapping[num_nodes - len(_nodes_flat) + i] = nodes + i += 1 + + graph.remove_nodes(_nodes_flat) + + # Insert pooled features + pooled_feat = {k: torch.stack([d[k] for d in pooled_feat], dim=0) for k in graph.ndata.keys()} + for k, v in pooled_feat.items(): + graph.ndata[k][-v.shape[0]:] = v + + return graph, node_mapping + +def coarsen(graph): + g_nx = graph.cpu().to_networkx().to_undirected() + g_nx = nx.Graph(g_nx) + matching = nx.algorithms.matching.max_weight_matching(g_nx) + matching = [list(x) for x in matching] + g, s_node_map = list_contract_nodes_(graph, matching) + return g, s_node_map + +class SpatialPooling(nn.Module): + def __init__(self): + super().__init__() + self.s_node_map = None + self.cached_graph = None + self.ukey = f'feat_{id(self)}' + + def forward(self, graph, feat): + self.cached_graph = graph + _graph = copy(graph) + _graph.ndata[self.ukey] = feat + g, s_node_map = coarsen(_graph) + self.s_node_map = s_node_map + return g, g.ndata[self.ukey] + + def unpool(self, feat): + """ Unpools by copying values""" + _feat = [] + for k,v in self.s_node_map.items(): + for node in v: + _feat.append((node, feat[k])) + u_feat = torch.stack([t[1] for t in sorted(_feat, key=lambda x: x[0])]) + return self.cached_graph, u_feat + +class TFTEmbedding(nn.Module): + def __init__(self, config): + super().__init__() + self.s_cat_inp_lens = config.static_categorical_inp_lens + self.t_cat_k_inp_lens = config.temporal_known_categorical_inp_lens + self.t_cat_o_inp_lens = config.temporal_observed_categorical_inp_lens + self.s_cont_inp_size = config.static_continuous_inp_size + self.t_cont_k_inp_size = config.temporal_known_continuous_inp_size + self.t_cont_o_inp_size = config.temporal_observed_continuous_inp_size + self.t_tgt_size = config.temporal_target_size + + self.hidden_size = config.hidden_size + + # There are 7 types of input: + # 1. Static categorical + # 2. Static continuous + # 3. Temporal known a priori categorical + # 4. Temporal known a priori continuous + # 5. Temporal observed categorical + # 6. Temporal observed continuous + # 7. Temporal observed targets (time series obseved so far) + + self.s_cat_embed = nn.ModuleList([ + nn.Embedding(n, self.hidden_size) for n in self.s_cat_inp_lens]) if self.s_cat_inp_lens else None + self.t_cat_k_embed = nn.ModuleList([ + nn.Embedding(n, self.hidden_size) for n in self.t_cat_k_inp_lens]) if self.t_cat_k_inp_lens else None + self.t_cat_o_embed = nn.ModuleList([ + nn.Embedding(n, self.hidden_size) for n in self.t_cat_o_inp_lens]) if self.t_cat_o_inp_lens else None + + self.s_cont_embedding_vectors = nn.Parameter(torch.Tensor(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None + self.t_cont_k_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None + self.t_cont_o_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None + self.t_tgt_embedding_vectors = nn.Parameter(torch.Tensor(self.t_tgt_size, self.hidden_size)) + + self.s_cont_embedding_bias = nn.Parameter(torch.zeros(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None + self.t_cont_k_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None + self.t_cont_o_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None + self.t_tgt_embedding_bias = nn.Parameter(torch.zeros(self.t_tgt_size, self.hidden_size)) + + if self.s_cont_embedding_vectors is not None: + torch.nn.init.xavier_normal_(self.s_cont_embedding_vectors) + if self.t_cont_k_embedding_vectors is not None: + torch.nn.init.xavier_normal_(self.t_cont_k_embedding_vectors) + if self.t_cont_o_embedding_vectors is not None: + torch.nn.init.xavier_normal_(self.t_cont_o_embedding_vectors) + torch.nn.init.xavier_normal_(self.t_tgt_embedding_vectors) + + def _apply_embedding(self, + cat: Optional[Tensor], + cont: Optional[Tensor], + cat_emb: Optional[nn.ModuleList], + cont_emb: Tensor, + cont_bias: Tensor, + ) -> Tuple[Optional[Tensor], Optional[Tensor]]: + e_cat = torch.stack([embed(cat[...,i]) for i, embed in enumerate(cat_emb)], dim=-2) if cat is not None else None + if cont is not None: + #the line below is equivalent to following einsums + #e_cont = torch.einsum('btf,fh->bthf', cont, cont_emb) + #e_cont = torch.einsum('bf,fh->bhf', cont, cont_emb) + e_cont = torch.mul(cont.unsqueeze(-1), cont_emb) + e_cont = e_cont + cont_bias + else: + e_cont = None + + if e_cat is not None and e_cont is not None: + return torch.cat([e_cat, e_cont], dim=-2) + elif e_cat is not None: + return e_cat + elif e_cont is not None: + return e_cont + else: + return None + + def forward(self, x: Dict[str, Tensor]): + # temporal/static categorical/continuous known/observed input + x = {k:v for k,v in x.items() if v.numel()} + s_cat_inp = x.get('s_cat', None) + s_cont_inp = x.get('s_cont', None) + t_cat_k_inp = x.get('k_cat', None) + t_cont_k_inp = x.get('k_cont', None) + t_cat_o_inp = x.get('o_cat', None) + t_cont_o_inp = x.get('o_cont', None) + t_tgt_obs = x['target'] # Has to be present + + # Static inputs are expected to be equal for all timesteps + # For memory efficiency there is no assert statement + s_cat_inp = s_cat_inp[:,0,:] if s_cat_inp is not None else None + s_cont_inp = s_cont_inp[:,0,:] if s_cont_inp is not None else None + + s_inp = self._apply_embedding(s_cat_inp, + s_cont_inp, + self.s_cat_embed, + self.s_cont_embedding_vectors, + self.s_cont_embedding_bias) + t_known_inp = self._apply_embedding(t_cat_k_inp, + t_cont_k_inp, + self.t_cat_k_embed, + self.t_cont_k_embedding_vectors, + self.t_cont_k_embedding_bias) + t_observed_inp = self._apply_embedding(t_cat_o_inp, + t_cont_o_inp, + self.t_cat_o_embed, + self.t_cont_o_embedding_vectors, + self.t_cont_o_embedding_bias) + + # Temporal observed targets + # t_observed_tgt = torch.einsum('btf,fh->btfh', t_tgt_obs, self.t_tgt_embedding_vectors) + t_observed_tgt = torch.matmul(t_tgt_obs.unsqueeze(3).unsqueeze(4), self.t_tgt_embedding_vectors.unsqueeze(1)).squeeze(3) + t_observed_tgt = t_observed_tgt + self.t_tgt_embedding_bias + + return s_inp, t_known_inp, t_observed_inp, t_observed_tgt + +class GCGRUCell(nn.Module): + def __init__(self, input_size, hidden_size): + super().__init__() + self.conv_i = GraphConv(input_size, 3 * hidden_size) #According to https://arxiv.org/pdf/1903.05631.pdf + self.conv_h = GraphConv(hidden_size, 3 * hidden_size) # this should be ChebConv + self.hidden_size = hidden_size + self.state = None + def forward(self, graph, feat, hx): + i = self.conv_i(graph, feat) + h = self.conv_h(graph, hx) + i_r, i_z, i_n = torch.chunk(i, 3, dim=-1) + h_r, h_z, h_n = torch.chunk(h, 3, dim=-1) + r = torch.sigmoid(i_r + h_r) + z = torch.sigmoid(i_z + h_z) + n = torch.tanh(i_n + r * h_n) + h = (1-z) * n + z * hx + + return h + +class GCGRU(nn.Module): + def __init__(self, input_size, hidden_size, num_layers): + super().__init__() + self.input_size = input_size + self.hidden_size = hidden_size + self.num_layers = num_layers + cells = [GCGRUCell(input_size, hidden_size)] + cells += [GCGRUCell(hidden_size, hidden_size) for _ in range(num_layers - 1)] + self.cells = nn.ModuleList(cells) + + def forward(self, graph, input, hx=None): + if hx is None: + hx = [torch.zeros(graph.num_nodes(), self.hidden_size, + dtype=input.dtype, device=input.device)] * self.num_layers + + + out = [] + states = [] + intermediate = [input[:,t,...] for t in range(input.shape[1])] + + for i, cell in enumerate(self.cells): + inner_out = [] + h = hx[i] + for x in intermediate: + h = cell(graph, x, h) + inner_out.append(h) + out.append(inner_out) + intermediate = inner_out + + output = torch.stack(out[-1], dim=1) + + return output, out[-1] + + +class ToyModel(nn.Module): + def __init__(self, config): + super().__init__() + self.encoder_steps = config.encoder_length + self.num_future_vars = config.num_future_vars + self.num_historic_vars = config.num_historic_vars + self.num_static_vars = config.num_static_vars + self.hidden_size = config.hidden_size + self.embedding = TFTEmbedding(config) + + self.static_proj = nn.Linear(config.hidden_size * self.num_static_vars, config.num_layers * config.hidden_size) + self.history_recurrent = GCGRU(config.hidden_size, config.hidden_size, config.num_layers) + self.future_recurrent = GCGRU(config.hidden_size, config.hidden_size, config.num_layers) + self.history_down_proj = nn.Linear(self.num_historic_vars * config.hidden_size, config.hidden_size) + self.future_down_proj = nn.Linear(self.num_future_vars * config.hidden_size, config.hidden_size) + self.out_proj = nn.Linear(config.hidden_size, 1) + + def forward(self, graph): + s_inp, t_known_inp, t_observed_inp, t_observed_tgt = self.embedding(graph.ndata) + s_inp = s_inp.view(s_inp.shape[0], -1) + init_state = self.static_proj(s_inp) + init_state = init_state.view(init_state.shape[0], -1, self.hidden_size).transpose(0,1) + + feat = torch.cat([t_known_inp, t_observed_inp, t_observed_tgt], dim=2) + historic_feat = feat[:,:self.encoder_steps,:] + historic_feat = historic_feat.view(historic_feat.shape[0], historic_feat.shape[1], -1) + historic_feat = self.history_down_proj(historic_feat) + history, state = self.history_recurrent(graph, historic_feat, hx=init_state) + + future_feat = t_known_inp[:,self.encoder_steps:, :] + future_feat = future_feat.view(future_feat.shape[0], future_feat.shape[1], -1) + future_feat = self.future_down_proj(future_feat) + future, _ = self.future_recurrent(graph, future_feat, hx=state) + out = self.out_proj(future) + + return out diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/interpretability.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/interpretability.py new file mode 100644 index 000000000..b155fcf5d --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/interpretability.py @@ -0,0 +1,31 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from abc import ABCMeta, abstractmethod + + +class InterpretableModelBase(object, metaclass=ABCMeta): + def __init__(self, *args, **kwargs): + self.interpretable = True + self.activations = {} + + @abstractmethod + def _register_interpretable_hooks(self): + return + + def enable_activations_dump(self): + self._register_interpretable_hooks() + + @abstractmethod + def get_activations(self, sample_number, *args, **kwargs): + return diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/lstm.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/lstm.py index 08f47e306..c843ba056 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/lstm.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/lstm.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,20 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, List, Optional, Tuple - import torch import torch.nn as nn -import torch.nn.functional as F -from apex.normalization.fused_layer_norm import FusedLayerNorm from torch import Tensor from models.tft_pyt.modeling import * class LSTM(nn.Module): - """ - Implementation from LSTM portion of https://arxiv.org/abs/1912.09363 + """ + Implementation from LSTM portion of https://arxiv.org/abs/1912.09363 """ def __init__(self, config): @@ -58,7 +54,7 @@ def forward(self, x: Tensor) -> Tensor: _historical_inputs.insert(0, t_observed_inp[:, : self.encoder_steps, :]) historical_inputs = torch.cat(_historical_inputs, dim=-2) - future_inputs = t_known_inp[:, self.encoder_steps :] + future_inputs = t_known_inp[:, self.encoder_steps:] # Encoders historical_features, _ = self.history_vsn(historical_inputs, cs) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/mtgnn.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/mtgnn.py new file mode 100644 index 000000000..1c810317e --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/mtgnn.py @@ -0,0 +1,338 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +import torch.nn as nn +import torch.nn.functional as F +import numbers +import pickle + +from .tft_pyt.modeling import LazyEmbedding + +# This is copied from torch source and adjusted to take in indices of nodes as well +class LayerNorm(nn.Module): + __constants__ = ['normalized_shape', 'weight', 'bias', 'eps', 'elementwise_affine'] + def __init__(self, normalized_shape, eps=1e-5, elementwise_affine=True): + super(LayerNorm, self).__init__() + if isinstance(normalized_shape, numbers.Integral): + normalized_shape = (normalized_shape,) + self.normalized_shape = tuple(normalized_shape) + self.eps = eps + self.elementwise_affine = elementwise_affine + if self.elementwise_affine: + self.weight = nn.Parameter(torch.Tensor(*normalized_shape)) + self.bias = nn.Parameter(torch.Tensor(*normalized_shape)) + else: + self.register_parameter('weight', None) + self.register_parameter('bias', None) + self.reset_parameters() + + def reset_parameters(self): + if self.elementwise_affine: + nn.init.ones_(self.weight) + nn.init.zeros_(self.bias) + + def forward(self, input, idx): + if self.elementwise_affine: + return F.layer_norm(input, tuple(input.shape[1:]), self.weight[:,idx,:], self.bias[:,idx,:], self.eps) + else: + return F.layer_norm(input, tuple(input.shape[1:]), self.weight, self.bias, self.eps) + + def extra_repr(self): + return '{normalized_shape}, eps={eps}, ' \ + 'elementwise_affine={elementwise_affine}'.format(**self.__dict__) + + +class GraphConstructor(nn.Module): + + def __init__(self, nnodes, k, dim, alpha=3, static_feat=None): + super().__init__() + self.nnodes = nnodes + if static_feat is not None: + xd = static_feat.shape[1] + self.lin1 = nn.Linear(xd, dim) + self.lin2 = nn.Linear(xd, dim) + else: + self.emb1 = nn.Embedding(nnodes, dim) + self.emb2 = nn.Embedding(nnodes, dim) + self.lin1 = nn.Linear(dim, dim) + self.lin2 = nn.Linear(dim, dim) + + self.k = k + self.dim = dim + self.alpha = alpha + self.static_feat = static_feat + + def forward(self, idx): + if self.static_feat is None: + nodevec1 = self.emb1(idx) + nodevec2 = self.emb2(idx) + else: + nodevec1 = self.static_feat[idx, :] + nodevec2 = nodevec1 + + nodevec1 = torch.tanh(self.alpha*self.lin1(nodevec1)) + nodevec2 = torch.tanh(self.alpha*self.lin2(nodevec2)) + + #a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0)) + # This comes from (AB^T)^T = BA^T + m = torch.mm(nodevec1, nodevec2.transpose(1, 0)) + a = m - m.transpose(1,0) + ##### + adj = F.relu(torch.tanh(self.alpha*a)) + mask = adj.new_zeros((idx.size(0), idx.size(0))) + s1,t1 = (adj + torch.rand_like(adj)*0.01).topk(self.k,1) + mask.scatter_(1, t1, 1) + adj = adj*mask + return adj + +class MixProp(nn.Module): + def __init__(self, c_in, c_out, gdep, alpha): + super().__init__() + self.linear = torch.nn.Conv2d((gdep+1)*c_in, c_out, kernel_size=(1, 1)) + self.gdep = gdep + self.alpha = alpha + + def forward(self, x, adj): + adj = adj + torch.eye(adj.size(0), device=adj.device) + d = adj.sum(1) + a = adj / d.unsqueeze(-1) + h = x + out = [h] + for i in range(self.gdep): + h = torch.einsum('ncwl,vw->ncvl', h, a) + h = self.alpha * x + (1 - self.alpha) * h + out.append(h) + ho = torch.cat(out, dim=1) + ho = self.linear(ho) + return ho + +class GCModule(nn.Module): + + def __init__(self, conv_channels, residual_channels, gcn_depth, propalpha): + super().__init__() + self.gc1 = MixProp(conv_channels, residual_channels, gcn_depth, propalpha) + self.gc2 = MixProp(conv_channels, residual_channels, gcn_depth, propalpha) + + def forward(self, x, adj): + x1 = self.gc1(x, adj) + x2 = self.gc2(x, adj.transpose(1, 0)) + return x1 + x2 + +class DilatedInception(nn.Module): + def __init__(self, cin, cout, dilation_factor=2): + super().__init__() + self.kernel_set = [2,3,6,7] + cout = int(cout / len(self.kernel_set)) + self.tconv = nn.ModuleList([nn.Conv2d(cin, cout, (1, k), dilation=(1, dilation_factor)) for k in self.kernel_set]) + + def forward(self,input): + x = [] + for conv in self.tconv: + x.append(conv(input)) + + # This truncation is described in the paper and seemingly drops some information + # Information drop is counteracted by padding time dimension with 0. + # Ex: for the largest filter of size 7 input is paddded by 7 zeros. + for i in range(len(self.kernel_set)): + x[i] = x[i][...,-x[-1].size(3):] + x = torch.cat(x,dim=1) + return x + +class TCModule(nn.Module): + def __init__(self, residual_channels, conv_channels, dilation_factor): + super().__init__() + self.filter = DilatedInception(residual_channels, conv_channels, dilation_factor) + self.gate = DilatedInception(residual_channels, conv_channels, dilation_factor) + + def forward(self, x): + f = self.filter(x) + f = torch.tanh(f) + g = self.gate(x) + g = torch.sigmoid(g) + x = f * g + return x + + +class MTGNNLayer(nn.Module): + def __init__(self, + r_channels, + c_channels, + s_channels, + kernel_size, + dilation_factor, + dropout, + num_nodes, + use_gcn, + gcn_depth, + propalpha): + super().__init__() + self.use_gcn = use_gcn + self.tc_module = TCModule(r_channels, c_channels, dilation_factor) + self.skip_conv = nn.Conv2d(in_channels=c_channels, + out_channels=s_channels, + kernel_size=(1, kernel_size)) + self.dropout = nn.Dropout(dropout) + self.ln = LayerNorm((r_channels, num_nodes, kernel_size),elementwise_affine=True) + + if use_gcn: + self.out_module = GCModule(c_channels, r_channels, gcn_depth, propalpha) + else: + self.out_module = nn.Conv2d(in_channels=c_channels, + out_channels=r_channels, + kernel_size=(1, 1)) + def forward(self, x, idx, adp): + residual = x + x = self.tc_module(x) + x = self.dropout(x) + s = x + s = self.skip_conv(s) + if self.use_gcn: + x = self.out_module(x, adp) + else: + x = self.out_module(x) + + x = x + residual[:, :, :, -x.size(3):] + x = self.ln(x,idx) + + return x, s + + +class MTGNN(nn.Module): + def __init__(self, config): + super().__init__() + self.config = config + self.use_gcn = config.use_gcn + self.gcn_depth = config.gcn_depth + self.predefined_adj = config.get('predefined_adj') + if self.predefined_adj is not None: + A = pickle.load(open(self.predefined_adj, 'rb')) + self.register_buffer('predefined_adj', A) + self.propalpha = config.propalpha + self.tanhalpha = config.tanhalpha + + self.num_nodes = config.num_nodes + self.dropout = config.dropout + self.in_dim = config.in_dim + self.out_dim = config.example_length - config.encoder_length + self.residual_channels = config.residual_channels + self.conv_channels = config.conv_channels + self.skip_channels = config.skip_channels + self.end_channels = config.end_channels + self.subgraph_size = config.subgraph_size + self.node_dim = config.node_dim + self.dilation_exponential = config.dilation_exponential + self.seq_length = config.encoder_length + self.num_layers = config.num_layers + self.use_embedding = config.use_embedding + + ### New embedding + if self.use_embedding: + self.config.hidden_size = self.config.in_dim + self.embedding = LazyEmbedding(self.config) + + self.include_static_data = config.include_static_data + #### + + + self.layers = nn.ModuleList() + self.start_conv = nn.LazyConv2d(out_channels=self.residual_channels, kernel_size=(1, 1)) + self.gc = GraphConstructor(self.num_nodes, self.subgraph_size, self.node_dim, alpha=self.tanhalpha) + + kernel_size = 7 + + def rf_size(c,q,m): + assert q >= 1 + if q > 1: + return int(1 + (c-1)*(q**m - 1)/(q-1)) + return m*(c-1) + 1 + + self.receptive_field = rf_size(kernel_size, self.dilation_exponential, self.num_layers) + new_dilation = 1 + for j in range(self.num_layers): + rfs = rf_size(kernel_size, self.dilation_exponential, j+1) + kernel_len = max(self.seq_length, self.receptive_field) - rfs + 1 + + self.layers.append(MTGNNLayer(self.residual_channels, self.conv_channels, self.skip_channels, + kernel_len, new_dilation, self.dropout, self.num_nodes, self.use_gcn, + self.gcn_depth, self.propalpha + ) + ) + + new_dilation *= self.dilation_exponential + + self.end_conv_1 = nn.Conv2d(in_channels=self.skip_channels, + out_channels=self.end_channels, + kernel_size=(1, 1)) + self.end_conv_2 = nn.Conv2d(in_channels=self.end_channels, + out_channels=self.out_dim, + kernel_size=(1, 1)) + + if self.seq_length > self.receptive_field: + self.skip0 = nn.LazyConv2d(out_channels=self.skip_channels, kernel_size=(1, self.seq_length)) + self.skipE = nn.Conv2d(in_channels=self.residual_channels, + out_channels=self.skip_channels, + kernel_size=(1, self.seq_length - self.receptive_field + 1) + ) + + else: + self.skip0 = nn.LazyConv2d(out_channels=self.skip_channels, kernel_size=(1, self.receptive_field)) + self.skipE = nn.Conv2d(in_channels=self.residual_channels, out_channels=self.skip_channels, kernel_size=(1, 1)) + + idx = torch.arange(self.num_nodes) + self.register_buffer('idx', idx) + + def forward(self, batch, idx=None): + if self.use_embedding: + batch = {k: v[:, :self.seq_length] if v is not None else None for k, v in batch.items()} + emb = self.embedding(batch) + emb = [e.view(*e.shape[:-2], -1) for e in emb if e is not None] + emb[0] = emb[0].unsqueeze(1).expand(emb[0].shape[0], self.seq_length, *emb[0].shape[1:]) + if not self.include_static_data: + emb = emb[1:] + input = torch.cat(emb, dim=-1).transpose(1, 3) + else: + + # TSPP compatibility code + t = batch['k_cont'][:, :self.seq_length, 0, 2:] + t = torch.einsum('btk,k->bt', t, t.new([1, 0.16])) + t = t.unsqueeze(-1).expand(*t.shape, self.num_nodes) + target = batch['target'][:, :self.seq_length].squeeze(-1) + input = torch.stack((target, t), dim=1).transpose(2, 3) + #### + + seq_len = input.size(3) + assert seq_len == self.seq_length, 'input sequence length not equal to preset sequence length' + if idx is None: + idx = self.idx + + if self.seq_length < self.receptive_field: + input = nn.functional.pad(input, (self.receptive_field - self.seq_length, 0, 0, 0)) + + if self.use_gcn: + if not self.predefined_adj: + adp = self.gc(idx) + else: + adp = self.predefined_adj + + x = self.start_conv(input) # 1x1 conv for upscaling. Acts like a linear procection on 1 dim + skip = self.skip0(F.dropout(input, self.dropout, training=self.training)) + for layer in self.layers: + x, s = layer(x, idx, adp) + skip = skip + s + + skip = self.skipE(x) + skip + x = F.relu(skip) + x = F.relu(self.end_conv_1(x)) + x = self.end_conv_2(x) + return x diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nbeats.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nbeats.py new file mode 100644 index 000000000..bc5365cf5 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nbeats.py @@ -0,0 +1,154 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import torch +from torch import nn + + +class Block(nn.Module): + + def __init__(self, units, thetas_dim, backcast_length, forecast_length): + super(Block, self).__init__() + self.thetas_dim = thetas_dim + self.backcast_length = backcast_length + self.forecast_length = forecast_length + ff = [nn.Linear(backcast_length, units), nn.ReLU()] + [item for _ in range(3) for item in (nn.Linear(units, units), nn.ReLU())] + self.ff = nn.Sequential(*ff) + + if self.thetas_dim: # generic block skips this stage + self.theta_b_fc = nn.Linear(units, thetas_dim, bias=False) + self.ff.add_module(str(len(self.ff)), self.theta_b_fc) + + +class SeasonalityBlock(Block): + + def __init__(self, units, thetas_dim, backcast_length, forecast_length): + + if not thetas_dim: + # Auto determine according to paper: horizon/2 sines, horizon/2 cosines + thetas_dim = forecast_length + + super(SeasonalityBlock, self).__init__(units, thetas_dim, backcast_length, + forecast_length) + + def get_seasonality_basis(num_thetas, linspace): + p = num_thetas + p1, p2 = (p // 2, p // 2) if p % 2 == 0 else (p // 2, p // 2 + 1) + s1 = [np.cos(2 * np.pi * i * linspace) for i in range(p1)] + s2 = [np.sin(2 * np.pi * i * linspace) for i in range(p2)] + s = np.stack(s1+s2) + return torch.FloatTensor(s) + + self.forecast_length = forecast_length + linspace = np.concatenate([np.arange(backcast_length) / backcast_length, np.arange(forecast_length) / forecast_length]) + self.register_buffer('basis', get_seasonality_basis(self.thetas_dim, linspace)) + + def forward(self, x): + x = squeeze_last_dim(x) + x = self.ff(x) + x = x.mm(self.basis) + backcast, forecast = x[:,:-self.forecast_length], x[:,-self.forecast_length:] + return backcast, forecast + + +class TrendBlock(Block): + + def __init__(self, units, thetas_dim, backcast_length, forecast_length): + super(TrendBlock, self).__init__(units, thetas_dim, backcast_length, + forecast_length) + + self.forecast_length = forecast_length + linspace = np.concatenate([np.arange(backcast_length) / backcast_length, np.arange(forecast_length) / forecast_length]) + basis = np.stack([linspace ** i for i in range(thetas_dim)]) + self.register_buffer('basis', torch.FloatTensor(basis)) + + def forward(self, x): + x = squeeze_last_dim(x) + x = self.ff(x) + x = x.mm(self.basis) + backcast, forecast = x[:, :-self.forecast_length], x[:, -self.forecast_length:] + return backcast, forecast + + +class GenericBlock(Block): + + def __init__(self, units, thetas_dim, backcast_length, forecast_length): + + super(GenericBlock, self).__init__(units, None, backcast_length, forecast_length) + + self.backcast_fc = nn.Linear(units, backcast_length) + self.forecast_fc = nn.Linear(units, forecast_length) + + def forward(self, x): + x = squeeze_last_dim(x) + x = self.ff(x) + + backcast = self.backcast_fc(x) + forecast = self.forecast_fc(x) + + return backcast, forecast + +class NBeatsNet(nn.Module): + BLOCK_MAP = {'seasonality': SeasonalityBlock, + 'trend': TrendBlock, + 'generic': GenericBlock + } + + def __init__(self, config): + super(NBeatsNet, self).__init__() + model_config = config + + self.forecast_length = config.example_length - config.encoder_length + self.backcast_length = config.encoder_length + self.stacks = nn.ModuleList([self.create_stack(c) for c in config.stacks]) + + def create_stack(self, stack_config): + blocks = nn.ModuleList() + + for block_id in range(stack_config.num_blocks): + block_init = NBeatsNet.BLOCK_MAP[stack_config.type] + if stack_config.share_weights and block_id != 0: + block = blocks[-1] # pick up the last one when we share weights. + else: + block = block_init(units = stack_config.hidden_size, + thetas_dim=stack_config.theta_dim, + backcast_length=self.backcast_length, + forecast_length=self.forecast_length) + blocks.append(block) + return blocks + + def forward(self, batch_dict): + backcast = batch_dict['target'][:,:self.backcast_length,:] + backcast = squeeze_last_dim(backcast) + forecast = backcast.new_zeros(size=(backcast.size()[0], self.forecast_length,)) + for stack in self.stacks: + for block in stack: + b, f = block(backcast) + backcast = backcast - b + forecast = forecast + f + forecast = forecast.unsqueeze(2) + return forecast + + +def squeeze_last_dim(tensor): + if len(tensor.shape) == 3 and tensor.shape[-1] == 1: # (128, 10, 1) => (128, 10). + return tensor[..., 0] + return tensor + + +def linear_space(backcast_length, forecast_length): + ls = np.arange(-backcast_length, forecast_length, 1) / forecast_length + b_ls = ls[:backcast_length] + f_ls = ls[backcast_length:] + return b_ls, f_ls diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nhits.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nhits.py new file mode 100644 index 000000000..739f2cbe8 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/nhits.py @@ -0,0 +1,156 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Tuple + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class _IdentityBasis(nn.Module): + def __init__(self, backcast_size: int, forecast_size: int, interpolation_mode: str): + super().__init__() + assert (interpolation_mode in ['linear','nearest']) or ('cubic' in interpolation_mode) + self.forecast_size = forecast_size + self.backcast_size = backcast_size + self.interpolation_mode = interpolation_mode + + def forward(self, theta: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + + backcast = theta[:, :self.backcast_size] + knots = theta[:, self.backcast_size:] + + if self.interpolation_mode in ['nearest','linear']: + knots = knots[:,None,:] + forecast = F.interpolate(knots, size=self.forecast_size, mode=self.interpolation_mode) + forecast = forecast[:,0,:] + elif 'cubic' in self.interpolation_mode: + batch_size = len(backcast) + knots = knots[:,None,None,:] + forecast = torch.zeros((len(knots), self.forecast_size)).to(knots.device) + n_batches = int(np.ceil(len(knots)/batch_size)) + for i in range(n_batches): + forecast_i = F.interpolate(knots[i*batch_size:(i+1)*batch_size], size=self.forecast_size, mode='bicubic') + forecast[i*batch_size:(i+1)*batch_size] += forecast_i[:,0,0,:] + + return backcast, forecast + +ACTIVATIONS = ['ReLU', + 'Softplus', + 'Tanh', + 'SELU', + 'LeakyReLU', + 'PReLU', + 'Sigmoid'] + +POOLING = ['MaxPool1d', + 'AvgPool1d'] + +class NHITSBlock(nn.Module): + """ + N-HiTS block which takes a basis function as an argument. + """ + def __init__(self, + input_size: int, + n_theta: int, + n_mlp_layers: int, + hidden_size: int, + basis: nn.Module, + n_pool_kernel_size: int, + pooling_mode: str, + dropout_prob: float, + activation: str): + """ + """ + super().__init__() + + n_time_in_pooled = int(np.ceil(input_size/n_pool_kernel_size)) + + self.dropout_prob = dropout_prob + + assert activation in ACTIVATIONS, f'{activation} is not in {ACTIVATIONS}' + assert pooling_mode in POOLING, f'{pooling_mode} is not in {POOLING}' + + activ = getattr(nn, activation)() + + self.pooling_layer = getattr(nn, pooling_mode)(kernel_size=n_pool_kernel_size, + stride=n_pool_kernel_size, ceil_mode=True) + + # Block MLPs + mlp = [nn.Linear(n_time_in_pooled, hidden_size)] + mlp += [item for _ in range(n_mlp_layers) for item in (nn.Linear(hidden_size, hidden_size), activ)] + layers = mlp + [nn.Linear(hidden_size, n_theta)] + + self.layers = nn.Sequential(*layers) + self.basis = basis + + def forward(self, insample_y: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]: + + # Pooling + insample_y = insample_y.unsqueeze(1) + insample_y = self.pooling_layer(insample_y) + insample_y = insample_y.squeeze(1) + + # Compute local projection weights and projection + theta = self.layers(insample_y) + backcast, forecast = self.basis(theta) + return backcast, forecast + +class NHITS(nn.Module): + def __init__(self, config): + super().__init__() + assert len(config.n_pool_kernel_size) == len(config.n_freq_downsample) == len(config.n_blocks) + + self.config = config + self.input_size = config.encoder_length + self.h = config.example_length - config.encoder_length + + blocks = self.create_stack(config) + self.blocks = torch.nn.ModuleList(blocks) + + def create_stack(self, config): + + block_list = [] + for n, k, f in zip(config.n_blocks, config.n_pool_kernel_size, config.n_freq_downsample): + for _ in range(n): + n_theta = (self.input_size + max(self.h//f, 1) ) + basis = _IdentityBasis(backcast_size=self.input_size, + forecast_size=self.h, + interpolation_mode=config.interpolation_mode) + nbeats_block = NHITSBlock(input_size=self.input_size, + n_theta=n_theta, + n_mlp_layers=config.n_mlp_layers, + hidden_size=config.hidden_size, + n_pool_kernel_size=k, + pooling_mode=config.pooling_mode, + basis=basis, + dropout_prob=config.dropout_prob_theta, + activation=config.activation) + block_list.append(nbeats_block) + + return block_list + + def forward(self, batch): + residuals = batch['target'][:, :self.input_size, 0] + + forecast = residuals[:, -1:] # Level with Naive1 + block_forecasts = [ forecast.repeat(1, self.h) ] + + for i, block in enumerate(self.blocks): + backcast, block_forecast = block(insample_y=residuals) + residuals = residuals - backcast + forecast = forecast + block_forecast + + return forecast.unsqueeze(2) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/stat_models.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/stat_models.py index 889357f0b..e10dbac9b 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/stat_models.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/stat_models.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,12 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 from abc import ABC import os import pmdarima as pm -# import cuml import numpy as np -from cuml.tsa.auto_arima import AutoARIMA as cuMLAutoArima import pickle as pkl class StatModel(ABC): @@ -40,38 +39,29 @@ def load(self, path): class AutoARIMA(StatModel): def __init__(self, config): super().__init__(config) - self.models = [] + self.models = {} - def fit(self, label, data): - self.model = pm.auto_arima(label, X=data) - self.models.append(self.model) + def fit(self, example): + id, label, data = example['id'], example['endog'], example['exog'] + data = data if data.shape[-1] != 0 else None + model = pm.auto_arima(label, X=data, **self.config) + self.model = model - def predict(self, data, i): - model = self.models[i] - return model.predict(self.horizon, X=data) - - def save(self): - with open('arima.pkl', 'wb') as f: - pkl.dump(self.models, f) - - def load(self, path): - with open(os.path.join(path, 'arima.pkl'), 'rb') as f: - self.models = pkl.load(f) - -class CUMLAutoARIMA(StatModel): - def __init__(self, config): - super().__init__(config) - self.models = [] - - def fit(self, label, data): - self.model = cuMLAutoArima(label.astype(np.float64)) - self.model.search() - self.model.fit() - self.models.append(self.model) - - def predict(self, data, i): - model = self.models[i] - return model.forecast(self.horizon).get() + def predict(self, example): + model = self.model + if len(example['endog_update']) != 0: + model.update(example['endog_update'], X=data if (data := example['exog_update']).shape[-1] != 0 else None) + # Issue is related to https://github.com/alkaline-ml/pmdarima/issues/492 + try: + preds = model.predict(self.horizon, X=data if (data := example['exog']).shape[-1] != 0 else None) + except ValueError as e: + if "Input contains NaN, infinity or a value too large for dtype('float64')." in str(e): + print(str(e)) + preds = np.empty(self.horizon) + preds.fill(self.model.arima_res_.data.endog[-1]) + else: + raise + return preds def save(self): with open('arima.pkl', 'wb') as f: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft.py new file mode 100644 index 000000000..70af5a607 --- /dev/null +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft.py @@ -0,0 +1,123 @@ +# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import torch +from data.data_utils import InputTypes, DataTypes +from matplotlib import pyplot as plt +from models.interpretability import InterpretableModelBase +from models.tft_pyt.modeling import TemporalFusionTransformer +from mpl_toolkits.axes_grid1 import make_axes_locatable + + +class InterpretableTFTBase(InterpretableModelBase): + def __init__(self, *args, **kwargs): + super(InterpretableTFTBase, self).__init__(*args, **kwargs) + + @classmethod + def _get_future_features(cls, features): + future_features = [feature.name for feature in features if feature.feature_type == InputTypes.KNOWN + and feature.feature_embed_type == DataTypes.CATEGORICAL] \ + + [feature.name for feature in features if feature.feature_type == InputTypes.KNOWN + and feature.feature_embed_type == DataTypes.CONTINUOUS] + return future_features + + @classmethod + def _get_history_features(cls, features): + history_features = [feature.name for feature in features if feature.feature_type == InputTypes.OBSERVED + and feature.feature_embed_type == DataTypes.CATEGORICAL] \ + + [feature.name for feature in features if feature.feature_type == InputTypes.OBSERVED + and feature.feature_embed_type == DataTypes.CONTINUOUS] \ + + [feature.name for feature in features if feature.feature_type == InputTypes.KNOWN + and feature.feature_embed_type == DataTypes.CATEGORICAL] \ + + [feature.name for feature in features if feature.feature_type == InputTypes.KNOWN + and feature.feature_embed_type == DataTypes.CONTINUOUS] \ + + [feature.name for feature in features if feature.feature_type == InputTypes.TARGET] + + return history_features + + @classmethod + def _get_heatmap_fig(cls, tensor, features, max_size=16, min_size=4): + shape = tensor.shape + ratio = max(max(shape) // max_size, 1) + fig_size = max(shape[1] / ratio, min_size), max(shape[0] / ratio, min_size) + fig = plt.figure(figsize=fig_size) + ticks = list(range(shape[0])) + plt.yticks(ticks, features) + plt.xlabel('Time step') + plt.imshow(tensor, cmap='hot', interpolation='nearest') + plt.colorbar() + return fig + + @classmethod + def _get_vsn_fig(cls, activations, sample_number, features): + _, sparse_matrix = activations + sample_sparse_matrix = sparse_matrix[sample_number] + final_tensor = sample_sparse_matrix.permute(1, 0) + fig = cls._get_heatmap_fig(final_tensor.detach().cpu(), features) + return fig + + @classmethod + def _get_attention_heatmap_fig(cls, heads, max_size=16, min_size=4): + row_size = max(min_size, max_size / len(heads)) + fig, axes = plt.subplots(1, len(heads), figsize=(max_size, row_size)) + for i, (head, ax) in enumerate(zip(heads, axes), 1): + im = ax.imshow(head, cmap='hot', interpolation='nearest') + if i < len(heads): + ax.set_title(f'HEAD {i}') + else: + ax.set_title('MEAN') + divider = make_axes_locatable(ax) + cax = divider.append_axes('right', size='5%', pad=0.05) + fig.colorbar(im, cax=cax, orientation='vertical') + return fig + + @classmethod + def _get_attn_heads(cls, activations, sample_number): + heads = [] + _, attn_prob = activations + sample_attn_prob = attn_prob[sample_number] + n_heads = sample_attn_prob.shape[0] + for head_index in range(n_heads): + head = sample_attn_prob[head_index] + heads.append(head.detach().cpu()) + mean_head = torch.mean(sample_attn_prob, dim=0) + heads.append(mean_head.detach().cpu()) + fig = cls._get_attention_heatmap_fig(heads) + return fig + + def _get_activation(self, name): + def hook(model, input, output): + self.activations[name] = output + + return hook + + def get_activations(self, sample_number, features): + assert self.activations, "There are no activations available" + return { + "history_vsn": self._get_vsn_fig(self.activations['history_vsn'], sample_number, + self._get_history_features(features)), + "future_vsn": self._get_vsn_fig(self.activations['future_vsn'], sample_number, + self._get_future_features(features)), + "attention": self._get_attn_heads(self.activations['attention'], sample_number) + } + + def _register_interpretable_hooks(self): + self.TFTpart2.history_vsn.register_forward_hook(self._get_activation('history_vsn')) + self.TFTpart2.future_vsn.register_forward_hook(self._get_activation('future_vsn')) + self.TFTpart2.attention.register_forward_hook(self._get_activation('attention')) + + +class InterpretableTFT(TemporalFusionTransformer, InterpretableTFTBase): + def __init__(self, *args, **kwargs): + TemporalFusionTransformer.__init__(self, *args, **kwargs) + InterpretableTFTBase.__init__(self, *args, **kwargs) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/Dockerfile b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/Dockerfile deleted file mode 100644 index f8361f449..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/Dockerfile +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:21.12-py3 -FROM ${FROM_IMAGE_NAME} - -# Ensure apt-get won't prompt for selecting options -ENV DEBIAN_FRONTEND=noninteractive -ENV DCGM_VERSION=2.2.9 - -# Install perf_client required library -RUN apt-get update && \ - apt-get install -y libb64-dev libb64-0d curl && \ - curl -s -L -O https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/datacenter-gpu-manager_${DCGM_VERSION}_amd64.deb && \ - dpkg -i datacenter-gpu-manager_${DCGM_VERSION}_amd64.deb && \ - rm datacenter-gpu-manager_${DCGM_VERSION}_amd64.deb && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Set workdir and python path -WORKDIR /workspace -ENV PYTHONPATH /workspace - -# In some cases in needed to uninstall typing -RUN apt update && apt install -y p7zip-full -RUN pip install --upgrade pip -RUN pip uninstall -y typing - -# Install requirements - -ADD requirements.txt /workspace/requirements.txt -ADD triton/requirements.txt /workspace/triton/requirements.txt -RUN pip install -r /workspace/requirements.txt -RUN pip install -r /workspace/triton/requirements.txt -RUN pip install nvidia-pyindex -RUN pip install git+https://github.com/NVIDIA/dllogger#egg=dllogger - -# Add model files to workspace -ADD . /workspace - - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/NOTICE b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/NOTICE deleted file mode 100644 index ae19bb47b..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/NOTICE +++ /dev/null @@ -1,3 +0,0 @@ -TFT for PyTorch - -This repository includes software from https://github.com/google-research/google-research/tree/master/tft licensed under the Apache License, Version 2.0 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/README.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/README.md deleted file mode 100644 index ad4ed27d0..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/README.md +++ /dev/null @@ -1,508 +0,0 @@ -# Temporal Fusion Transformer For PyTorch - -This repository provides a script and recipe to train the Temporal Fusion Transformer model to achieve state-of-the-art accuracy. The content of this repository is tested and maintained by NVIDIA. - -## Table Of Contents - -- [Model overview](#model-overview) - * [Model architecture](#model-architecture) - * [Default configuration](#default-configuration) - * [Feature support matrix](#feature-support-matrix) - * [Features](#features) - * [Mixed precision training](#mixed-precision-training) - * [Enabling mixed precision](#enabling-mixed-precision) - * [Enabling TF32](#enabling-tf32) - * [Glossary](#glossary) -- [Setup](#setup) - * [Requirements](#requirements) -- [Quick Start Guide](#quick-start-guide) -- [Advanced](#advanced) - * [Scripts and sample code](#scripts-and-sample-code) - * [Command-line options](#command-line-options) - * [Getting the data](#getting-the-data) - * [Dataset guidelines](#dataset-guidelines) - * [Multi-dataset](#multi-dataset) - * [Training process](#training-process) - * [Inference process](#inference-process) - * [Triton deployment](#triton-deployment) -- [Performance](#performance) - * [Benchmarking](#benchmarking) - * [Training performance benchmark](#training-performance-benchmark) - * [Inference performance benchmark](#inference-performance-benchmark) - * [Results](#results) - * [Training accuracy results](#training-accuracy-results) - * [Training accuracy: NVIDIA DGX A100 (8x A100 80GB)](#training-accuracy-nvidia-dgx-a100-8x-a100-80gb) - * [Training accuracy: NVIDIA DGX-1 (8x V100 16GB)](#training-accuracy-nvidia-dgx-1-8x-v100-16gb) - * [Training stability test](#training-stability-test) - * [Training performance results](#training-performance-results) - * [Training performance: NVIDIA DGX A100 (8x A100 80GB)](#training-performance-nvidia-dgx-a100-8x-a100-80gb) - * [Training performance: NVIDIA DGX-1 (8x V100 16GB)](#training-performance-nvidia-dgx-1-8x-v100-16gb) - * [Inference performance results](#inference-performance-results) - * [Inference Performance: NVIDIA DGX A100](#inference-performance-nvidia-dgx-a100) - * [Inference Performance: NVIDIA DGX-1 V100](#inference-performance-nvidia-dgx-1-v100) -- [Release notes](#release-notes) - * [Changelog](#changelog) - * [Known issues](#known-issues) - - - -## Model overview - -The Temporal Fusion Transformer [TFT](https://arxiv.org/abs/1912.09363) model is a state-of-the-art architecture for interpretable, multi-horizon time-series prediction. The model was first developed and [implemented by Google](https://github.com/google-research/google-research/tree/master/tft) with the collaboration with the University of Oxford. -This implementation differs from the reference implementation by addressing the issue of missing data, which is common in production datasets, by either masking their values in attention matrices or embedding them as a special value in the latent space. -This model enables the prediction of confidence intervals for future values of time series for multiple future timesteps. - -This model is trained with mixed precision using Tensor Cores on Volta, Turing, and the NVIDIA Ampere GPU architectures. Therefore, researchers can get results 1.45x faster than training without Tensor Cores while experiencing the benefits of mixed precision training. This model is tested against each NGC monthly container release to ensure consistent accuracy and performance over time. - -### Model architecture - -The TFT model is a hybrid architecture joining LSTM encoding of time series and interpretability of transformer attention layers. Prediction is based on three types of variables: static (constant for a given time series), known (known in advance for whole history and future), observed (known only for historical data). All these variables come in two flavors: categorical, and continuous. In addition to historical data, we feed the model with historical values of time series. All variables are embedded in high-dimensional space by learning an embedding vector. Categorical variables embeddings are learned in the classical sense of embedding discrete values. The model learns a single vector for each continuous variable, which is then scaled by this variable’s value for further processing. The next step is to filter variables through the Variable Selection Network (VSN), which assigns weights to the inputs in accordance with their relevance to the prediction. Static variables are used as a context for variable selection of other variables and as an initial state of LSTM encoders. -After encoding, variables are passed to multi-head attention layers (decoder), which produce the final prediction. Whole architecture is interwoven with residual connections with gating mechanisms that allow the architecture to adapt to various problems by skipping some parts of it. -For the sake of explainability, heads of self-attention layers share value matrices. This allows interpreting self-attention as an ensemble of models predicting different temporal patterns over the same feature set. The other feature that helps us understand the model is VSN activations, which tells us how relevant the given feature is to the prediction. -![](TFT_architecture.PNG) -*image source: https://arxiv.org/abs/1912.09363* - -### Default configuration - -The specific configuration of the TFT model depends on the dataset used. Not only is the volume of the model subject to change but so are the data sampling and preprocessing strategies. During preprocessing, data is normalized per feature. For a part of the datasets, we apply scaling per-time-series, which takes into account shifts in distribution between entities (i.e., a factory consumes more electricity than an average house). The model is trained with the quantile loss: -For quantiles in [0.1, 0.5, 0.9]. The default configurations are tuned for distributed training on DGX-1-32G with mixed precision. We use dynamic loss scaling. Specific values are provided in the table below. - -| Dataset | Training samples | Validation samples | Test samples | History length | Forecast horizon | Dropout | Hidden size | #Heads | BS | LR | Gradient clipping | -| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| Electricity | 450k | 50k | 53.5k | 168 | 24 | 0.1 | 128 | 4 | 8x1024 | 1e-3 | 0.0 | -| Traffic | 450k | 50k | 139.6k | 168 | 24 | 0.3 | 128 | 4 | 8x1024 | 1e-3 | 0.0 - -### Feature support matrix - -The following features are supported by this model: - -| Feature | Yes column -|----------------------------|-------------------------- -|Distributed data parallel | Yes -|PyTorch AMP | Yes - - -#### Features - -[Automatic Mixed Precision](https://pytorch.org/docs/stable/amp.html) -provides an easy way to leverage Tensor Cores’ performance. It allows the execution of parts of a network in lower precision. Refer to [Mixed precision training](#mixed-precision-training) for more information. - -[PyTorch -DistributedDataParallel](https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel) - a module -wrapper that enables easy multiprocess distributed data-parallel -training. - -### Mixed precision training - -Mixed precision is the combined use of different numerical precisions in a -computational method. -[Mixed precision](https://arxiv.org/abs/1710.03740) training offers significant -computational speedup by performing operations in half-precision format while -storing minimal information in single-precision to retain as much information -as possible in critical parts of the network. Since the introduction of [Tensor Cores](https://developer.nvidia.com/tensor-cores) in Volta, and following with -both the Turing and Ampere architectures, significant training speedups are -experienced by switching to -mixed precision -- up to 3x overall speedup on the most arithmetically intense -model architectures. Using mixed precision training previously required two -steps: - -1. Porting the model to use the FP16 data type where appropriate. -2. Manually adding loss scaling to preserve small gradient values. - -The ability to train deep learning networks with lower precision was introduced -in the Pascal architecture and first supported in [CUDA -8](https://devblogs.nvidia.com/parallelforall/tag/fp16/) in the NVIDIA Deep -Learning SDK. - -For information about: -* How to train using mixed precision, refer to the [Mixed Precision - Training](https://arxiv.org/abs/1710.03740) paper and [Training With Mixed - Precision](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html) - documentation. -* Techniques used for mixed precision training, refer to the [Mixed-Precision - Training of Deep Neural - Networks](https://devblogs.nvidia.com/mixed-precision-training-deep-neural-networks/) - blog. -* APEX tools for mixed precision training, refer to the [NVIDIA Apex: Tools for Easy Mixed-Precision Training in - PyTorch](https://devblogs.nvidia.com/apex-pytorch-easy-mixed-precision-training/) - . - - -#### Enabling mixed precision - - -Mixed precision is enabled in PyTorch by using the Automatic Mixed Precision torch.cuda.amp module, which casts variables to half-precision upon retrieval while storing variables in single-precision format. Furthermore, to preserve small gradient magnitudes in backpropagation, a [loss scaling](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html#lossscaling) step must be included when applying gradients. In PyTorch, loss scaling can be applied automatically by the GradScaler class. All the necessary steps to implement AMP are verbosely described [here](https://pytorch.org/docs/stable/notes/amp_examples.html#amp-examples). - -To enable mixed precision for TFT, simply add the `--use_amp` option to the training script. -#### Enabling TF32 - -TensorFloat-32 (TF32) is the new math mode in [NVIDIA A100](https://www.nvidia.com/en-us/data-center/a100/) GPUs for handling the matrix math, also called tensor operations. TF32 running on Tensor Cores in A100 GPUs can provide up to 10x speedups compared to single-precision floating-point math (FP32) on Volta GPUs. - -TF32 Tensor Cores can speed up networks using FP32, typically with no loss of accuracy. It is more robust than FP16 for models which require high dynamic range for weights or activations. - -For more information, refer to the [TensorFloat-32 in the A100 GPU Accelerates AI Training, HPC up to 20x](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) blog post. - -TF32 is supported in the NVIDIA Ampere GPU architecture and is enabled by default. - - - -### Glossary - -**Multi horizon prediction** -Process of estimating values of a time series for multiple future time steps. - -**Quantiles** -Cut points dividing the range of a probability distribution intervals with equal probabilities. - -**Time series** -Series of data points indexed and equally spaced in time. - -**Transformer** -The paper [Attention Is All You Need](https://arxiv.org/abs/1706.03762) introduces a novel architecture called Transformer that uses an attention mechanism and transforms one sequence into another. - - -## Setup - -The following section lists the requirements that you need to meet in order to start training the TFT model. - -### Requirements - -This repository contains Dockerfile, which extends the PyTorch NGC container and encapsulates some dependencies. Aside from these dependencies, ensure you have the following components: -- [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -- [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) -- Supported GPUs: -- [NVIDIA Volta architecture](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) -- [NVIDIA Turing architecture](https://www.nvidia.com/en-us/design-visualization/technologies/turing-architecture/) -- [NVIDIA Ampere architecture](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/) - -For more information about how to get started with NGC containers, refer to the following sections from the NVIDIA GPU Cloud Documentation and the Deep Learning Documentation: -- [Getting Started Using NVIDIA GPU Cloud](https://docs.nvidia.com/ngc/ngc-getting-started-guide/index.html) -- [Accessing And Pulling From The NGC Container Registry](https://docs.nvidia.com/deeplearning/frameworks/user-guide/index.html#accessing_registry) -- Running [PyTorch](https://docs.nvidia.com/deeplearning/frameworks/pytorch-release-notes/running.html#running) - - -For those unable to use the PyTorch NGC container to set up the required environment or create your own container, refer to the versioned [NVIDIA Container Support Matrix](https://docs.nvidia.com/deeplearning/frameworks/support-matrix/index.html). - -## Quick Start Guide - -To train your model using mixed or TF32 precision with Tensor Cores, perform the following steps using the default parameters of the TFT model on any of the benchmark datasets. For the specifics concerning training and inference, refer to the [Advanced](#advanced) section. - -1. Clone the repository. -```bash -git clone https://github.com/NVIDIA/DeepLearningExamples -cd DeepLearningExamples/PyTorch/Forecasting/TFT -``` - -2. Build the TFT PyTorch NGC container. -```bash -docker build --network=host -t tft . -``` - -3. Start an interactive session in the NGC container to run training/inference. -```bash -docker run -it --rm --ipc=host --network=host --gpus all -v /path/to/your/data:/data/ tft -``` - -Note: Ensure to mount your dataset using the -v flag to make it available for training inside the NVIDIA Docker container. - -4. Download and preprocess datasets. -```bash -bash scripts/get_data.sh -``` - -5. Start training. Choose one of the scripts provided in the `scripts/` directory. Results are stored in the `/results` directory. -These scripts are tuned for DGX1-32G. If you have a different system, use NGPU and BATCH_SIZE variables to adjust the parameters for your system. -```bash -bash scripts/run_electricity.sh -bash scripts/run_traffic.sh -``` - -6. Start validation/evaluation. The metric we use for evaluation is q-risk. We can compare it per-quantile in the Pareto sense or jointly as one number indicating accuracy. -```bash -python inference.py \ ---checkpoint \ ---data /data/processed//test.csv \ ---cat_encodings /data/processed//cat_encodings.bin \ ---tgt_scalers /data/processed//tgt_scalers.bin -``` - -7. Start inference/predictions. Visualize and save predictions by running the following command. -```bash -python inference.py \ ---checkpoint \ ---data /data/processed//test.csv \ ---cat_encodings /data/processed//cat_encodings.bin \ ---tgt_scalers /data/processed//tgt_scalers.bin \ ---visualize \ ---save_predictions -``` - - - -Now that you have your model trained and evaluated, you can choose to compare your training results with our [Training accuracy results](#training-accuracy-results). You can also choose to benchmark your performance to [Training performance benchmark](#training-performance-results). Following the steps in these sections will ensure that you achieve the same accuracy and performance results as stated in the [Results](#results) section. -## Advanced - -The following sections provide more details about the dataset, running training and inference, and the training results. - -### Scripts and sample code - -In the root directory, the most important files are: - -`train.py`: Entry point for training -`data_utils.py`: File containing the dataset implementation and preprocessing functions -`modeling.py`: Definition of the model -`configuration.py`: Contains configuration classes for various experiments -`test.py`: Entry point testing trained model. -`Dockerfile`: Container definition -`log_helper.py`: Contains helper functions for setting up dllogger -`criterions.py`: Definitions of loss functions - -The `scripts` directory contains scripts for default use cases: -`run_electricity.sh`: train default model on the electricity dataset -`run_traffic.sh`: train default model on the traffic dataset - -### Command-line options - -To view the full list of available options and their descriptions, use the `-h` or `--help` command-line option, for example: -`python train.py --help`. - -The following example output is printed when running the model: -``` -usage: train.py [-h] --data_path DATA_PATH --dataset {electricity,volatility,traffic,favorita} [--epochs EPOCHS] [--sample_data SAMPLE_DATA SAMPLE_DATA] [--batch_size BATCH_SIZE] [--lr LR] [--seed SEED] [--use_amp] [--clip_grad CLIP_GRAD] - [--early_stopping EARLY_STOPPING] [--results RESULTS] [--log_file LOG_FILE] [--distributed_world_size N] [--distributed_rank DISTRIBUTED_RANK] [--local_rank LOCAL_RANK] [--overwrite_config OVERWRITE_CONFIG] - -optional arguments: - -h, --help show this help message and exit - --data_path DATA_PATH - --dataset {electricity,volatility,traffic,favorita} - --epochs EPOCHS - --sample_data SAMPLE_DATA SAMPLE_DATA - --batch_size BATCH_SIZE - --lr LR - --seed SEED - --use_amp Enable automatic mixed precision - --clip_grad CLIP_GRAD - --early_stopping EARLY_STOPPING - Stop training if validation loss does not improve for more than this number of epochs. - --results RESULTS - --log_file LOG_FILE - --distributed_world_size N - total number of GPUs across all nodes (default: all visible GPUs) - --distributed_rank DISTRIBUTED_RANK - rank of the current worker - --local_rank LOCAL_RANK - rank of the current worker - --overwrite_config OVERWRITE_CONFIG - JSON string used to overload config - -``` - -### Getting the data - -The TFT model was trained on the electricity and traffic benchmark datasets. This repository contains the `get_data.sh` download script, which for electricity and and traffic datasets will automatically download and preprocess the training, validation and test datasets, and produce files that contain scalers. -#### Dataset guidelines - -The `data_utils.py` file contains all functions that are used to preprocess the data. Initially the data is loaded to a `pandas.DataFrame` and parsed to the common format which contains the features we will use for training. Then standardized data is cleaned, normalized, encoded and binarized. -This step does the following: -Drop all the columns that are not marked in the configuration file as used for training or preprocessing -Flatten indices in case time series are indexed by more than one column -Split the data into training, validation and test splits -Filter out all the time series shorter than minimal example length -Normalize columns marked as continuous in the configuration file -Encode as integers columns marked as categorical -Save the data in csv and binary formats - -#### Multi-dataset -In order to use an alternate dataset, you have to write a function that parses your data to a common format. The format is as follows: -There is at least one id column -There is exactly one time column (that can also be used as a feature column) -Each feature is in a separate column -Each row represents a moment in time for only one time series -Additionally, you must specify a configuration of the network, including a data description. Refer to the example in `configuration.py` file. -### Training process - -The `train.py` script is an entry point for a training procedure. Refined recipes can be found in the `scripts` directory. -The model trains for at most `--epochs` epochs. If option `--early_stopping N` is set, then training will end if for N subsequent epochs validation loss hadn’t improved. -The details of the architecture and the dataset configuration are encapsulated by the `--dataset` option. This option chooses one of the configurations stored in the `configuration.py` file. You can enable mixed precision training by providing the `--use_amp` option. The training script supports multi-GPU training with the APEX package. To enable distributed training prepend training command with `python -m torch.distributed.run --nproc_per_node=${NGPU}`. - -Example command: -``` -python -m torch.distributed.launch --nproc_per_node=8 train.py \ - --dataset electricity \ - --data_path /data/processed/electricity_bin \ - --batch_size=1024 \ - --sample 450000 50000 \ - --lr 1e-3 \ - --epochs 25 \ - --early_stopping 5 \ - --seed 1 \ - --use_amp \ - --results /results/TFT_electricity_bs8x1024_lr1e-3/seed_1 -``` - -The model is trained by optimizing quantile loss -. After training, the checkpoint with the least validation loss is evaluated on a test split with q-risk metric . -Results are by default stored in the `/results` directory. This can be changed by providing the `--results` option. At the end of the training, the results directory will contain the trained checkpoint which had the lowest validation loss, dllogger logs (in dictionary per line format), and TensorBoard logs. - -### Inference process - -Inference can be run by launching the `inference.py` script. The script requires a trained checkpoint to run. It is crucial to prepare the data in the same way as training data prior to running the inference. Example command: -``` -python inference.py \ ---checkpoint /results/checkpoint.pt \ ---data /data/processed/electricity_bin/test.csv \ ---tgt_scalers /data/processed/electricity_bin/tgt_scalers.bin \ ---cat_encodings /data/processed/electricity_bin/cat_encodings.bin \ ---batch_size 2048 \ ---visualize \ ---save_predictions \ ---joint_visualization \ ---results /results \ ---use_amp -``` - -In the default setting, it performs the evaluation of the model on a specified dataset and prints q-risk evaluated on this dataset. In order to save the predictions, use the `--save_predictions` option. Predictions will be stored in the directory specified by the `--results` option in the csv format. Option `--joint_visualization` allows us to plot graphs in TensorBoard format, allowing us to inspect the results and compare them to true values. Using `--visualize`, you can save plots for each example in a separate file. - - -### Triton deployment - -The [NVIDIA Triton Inference Server](https://github.com/triton-inference-server/server) provides a cloud inferencing solution optimized for NVIDIA GPUs. The server provides an inference service via an HTTP or GRPC endpoint, allowing remote clients to request inferencing for any model being managed by the server. More information on how to perform inference using NVIDIA Triton Inference Server can be found in [triton/README.md](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Forecasting/TFT/triton). - -## Performance - -### Benchmarking - -The following section shows how to run benchmarks measuring the model performance in training and inference modes. - -#### Training performance benchmark - -In order to run training benchmarks, use the `scripts/benchmark.sh` script. - -#### Inference performance benchmark - -To benchmark the inference performance on a specific batch size and dataset, run the `inference.py` script. -### Results - -The following sections provide details on how we achieved our performance and accuracy in training and inference. - -#### Training accuracy results - -We conducted an extensive hyperparameter search along with stability tests. The presented results are the averages from the hundreds of runs. - -##### Training accuracy: NVIDIA DGX A100 (8x A100 80GB) - -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA A100 (8x A100 80GB) GPUs. - -| Dataset | GPUs | Batch size / GPU | Accuracy - TF32 | Accuracy - mixed precision | Time to train - TF32 | Time to train - mixed precision | Time to train speedup (TF32 to mixed precision) -|-------------|---|------|-----------------------|-----------------------|-------|-------|------- -| Electricity | 8 | 1024 | 0.027 / 0.057 / 0.029 | 0.028 / 0.057 / 0.029 | 216s | 176s | 1.227x -| Traffic | 8 | 1024 | 0.043 / 0.108 / 0.079 | 0.042 / 0.107 / 0.078 | 151s | 126s | 1.198x - - - - -##### Training accuracy: NVIDIA DGX-1 (8x V100 16GB) - -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 with (8x V100 16GB) GPUs. - -| Dataset | GPUs | Batch size / GPU | Accuracy - FP32 | Accuracy - mixed precision | Time to train - FP32 | Time to train - mixed precision | Time to train speedup (FP32 to mixed precision) -|-------------|---|------|-----------------------|-----------------------|-------|-------|----------- -| Electricity | 8 | 1024 | 0.028 / 0.057 / 0.029 | 0.027 / 0.057 / 0.029 | 381s | 261s | 1.460x -| Traffic | 8 | 1024 | 0.042 / 0.106 / 0.076 | 0.040 / 0.103 / 0.074 | 256s | 176s | 1.455x - - - -##### Training stability test - -In order to get a greater picture of the model’s accuracy, we performed a hyperparameter search along with stability tests on 100 random seeds for each configuration. Then, for each benchmark dataset, we have chosen the architecture with the least mean test q-risk. The table below summarizes the best configurations. - -| Dataset | #GPU | Hidden size | #Heads | Local BS | LR | Gradient clipping | Dropout | Mean q-risk | Std q-risk | Min q-risk | Max q-risk -|-------------|------|-------------|--------|----------|------|-------------------|---------|-------------|------------| -----------|------ -| Electricity | 8 | 128 | 4 | 1024 | 1e-3 | 0.0 | 0.1 | 0.1131 | 0.0025 | 0.1080 | 0.1200 -| Traffic | 8 | 128 | 4 | 1024 | 1e-3 | 0.0 | 0.3 | 0.2180 | 0.0049 | 0.2069 | 0.2336 - - -#### Training performance results - -##### Training performance: NVIDIA DGX A100 (8x A100 80GB) - -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA A100 (8x A100 80GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. - -| Dataset | GPUs | Batch size / GPU | Throughput - TF32 | Throughput - mixed precision | Throughput speedup (TF32 - mixed precision) | Weak scaling - TF32 | Weak scaling - mixed precision -|-------------|---|------|--------|--------|-------|-------|----- -| Electricity | 1 | 1024 | 10173 | 13703 | 1.35x | 1 | 1 -| Electricity | 8 | 1024 | 80596 | 107761 | 1.34x | 7.92x | 7.86x -| Traffic | 1 | 1024 | 10197 | 13779 | 1.35x | 1 | 1 -| Traffic | 8 | 1024 | 80692 | 107979 | 1.34x | 7.91x | 7.84x - - -To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). - -The performance metrics used were items per second. - - -##### Training performance: NVIDIA DGX-1 (8x V100 16GB) - -Our results were obtained by running the `train.sh` training script in the [PyTorch 21.06 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 with (8x V100 16GB) GPUs. Performance numbers (in items/images per second) were averaged over an entire training epoch. - -| Dataset | GPUs | Batch size / GPU | Throughput - FP32 | Throughput - mixed precision | Throughput speedup (FP32 - mixed precision) | Weak scaling - FP32 | Weak scaling - mixed precision -|-------------|---|------|-------|-------|-------|------|---- -| Electricity | 1 | 1024 | 5580 | 9148 | 1.64x | 1 | 1 -| Electricity | 8 | 1024 | 43351 | 69855 | 1.61x | 7.77x | 7.64x -| Traffic | 1 | 1024 | 5593 | 9194 | 1.64x | 1 | 1 -| Traffic | 8 | 1024 | 43426 | 69983 | 1.61x | 7.76x | 7.61x - - - -To achieve these same results, follow the steps in the [Quick Start Guide](#quick-start-guide). - -The performance metrics used were items per second. - - -#### Inference Performance Results - - -##### Inference Performance: NVIDIA DGX A100 - -Our results were obtained by running the `inference.py` script in the [PyTorch 21.12 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX A100. Throughput is measured in items per second and latency is measured in milliseconds. -To benchmark the inference performance on a specific batch size and dataset, run the `inference.py` script. -| Dataset | GPUs | Batch size / GPU | Throughput - mixed precision (item/s) | Average Latency (ms) | Latency p90 (ms) | Latency p95 (ms) | Latency p99 (ms) -|-------------|--------|-----|---------------------------------|-----------------|-------------|-------------|------------ -| Electricity | 1 | 1 | 144.37 | 6.93 | 7.00 | 7.04 | 7.25 -| Electricity | 1 | 2 | 277.53 | 7.21 | 7.25 | 7.27 | 7.48 -| Electricity | 1 | 4 | 564.37 | 7.09 | 7.13 | 7.15 | 7.64 -| Electricity | 1 | 8 | 1399.25 | 5.72 | 5.71 | 5.77 | 7.51 -| Traffic | 1 | 1 | 145.26 | 6.88 | 6.91 | 6.95 | 7.60 -| Traffic | 1 | 2 | 277.97 | 7.19 | 7.28 | 7.30 | 7.46 -| Traffic | 1 | 4 | 563.05 | 7.10 | 7.14 | 7.16 | 7.42 -| Traffic | 1 | 8 | 1411.62 | 5.67 | 5.69 | 5.79 | 6.21 - - -##### Inference Performance: NVIDIA DGX-1 V100 - -Our results were obtained by running the `inference.py` script in the [PyTorch 21.12 NGC container](https://ngc.nvidia.com/catalog/containers/nvidia:pytorch) on NVIDIA DGX-1 V100. Throughput is measured in items per second and latency is measured in milliseconds. -To benchmark the inference performance on a specific batch size and dataset, run the `inference.py` script. -| Dataset | GPUs | Batch size / GPU | Throughput - mixed precision (item/s) | Average Latency (ms) | Latency p90 (ms) | Latency p95 (ms) | Latency p99 (ms) -|-------------|--------|-----|---------------------------------|-----------------|-------------|-------------|------------ -| Electricity | 1 | 1 | 95.65 | 10.45 | 11.30 | 11.95 | 12.13 -| Electricity | 1 | 2 | 193.15 | 10.35 | 10.80 | 11.46 | 12.16 -| Electricity | 1 | 4 | 381.09 | 10.49 | 10.75 | 12.29 | 12.41 -| Electricity | 1 | 8 | 805.49 | 9.93 | 10.41 | 10.48 | 10.91 -| Traffic | 1 | 1 | 96.72 | 10.34 | 10.53 | 11.99 | 12.13 -| Traffic | 1 | 2 | 192.93 | 10.37 | 10.80 | 11.97 | 12.12 -| Traffic | 1 | 4 | 379.00 | 10.55 | 10.88 | 11.09 | 11.96 -| Traffic | 1 | 8 | 859.69 | 9.30 | 10.58 | 10.65 | 11.28 -## Release notes -The performance measurements in this document were conducted at the time of publication and may not reflect the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to https://developer.nvidia.com/deep-learning-performance-training-inference. - -### Changelog - -November 2021 -- Initial release - -February 2022 -- 21.12 Container Update -- Triton Inference Performance Numbers -### Known issues -There are no known issues with this model. - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/TFT_architecture.PNG b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/TFT_architecture.PNG deleted file mode 100644 index c3431031d..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/TFT_architecture.PNG and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/configuration.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/configuration.py deleted file mode 100644 index 5eee08be7..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/configuration.py +++ /dev/null @@ -1,264 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from data_utils import InputTypes, DataTypes, FeatureSpec -import datetime - -class ElectricityConfig(): - def __init__(self): - - self.features = [ - FeatureSpec('id', InputTypes.ID, DataTypes.CATEGORICAL), - FeatureSpec('hours_from_start', InputTypes.TIME, DataTypes.CONTINUOUS), - FeatureSpec('power_usage', InputTypes.TARGET, DataTypes.CONTINUOUS), - FeatureSpec('hour', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('day_of_week', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('hours_from_start', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('categorical_id', InputTypes.STATIC, DataTypes.CATEGORICAL), - ] - # Dataset split boundaries - self.time_ids = 'days_from_start' # This column contains time indices across which we split the data - self.train_range = (1096, 1315) - self.valid_range = (1308, 1339) - self.test_range = (1332, 1346) - self.dataset_stride = 1 #how many timesteps between examples - self.scale_per_id = True - self.missing_id_strategy = None - self.missing_cat_data_strategy='encode_all' - - # Feature sizes - self.static_categorical_inp_lens = [369] - self.temporal_known_categorical_inp_lens = [] - self.temporal_observed_categorical_inp_lens = [] - self.quantiles = [0.1, 0.5, 0.9] - - self.example_length = 8 * 24 - self.encoder_length = 7 * 24 - - self.n_head = 4 - self.hidden_size = 128 - self.dropout = 0.1 - self.attn_dropout = 0.0 - - #### Derived variables #### - self.temporal_known_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.KNOWN and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_observed_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.OBSERVED and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_target_size = len([x for x in self.features if x.feature_type == InputTypes.TARGET]) - self.static_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.STATIC and x.feature_embed_type == DataTypes.CONTINUOUS]) - - self.num_static_vars = self.static_continuous_inp_size + len(self.static_categorical_inp_lens) - self.num_future_vars = self.temporal_known_continuous_inp_size + len(self.temporal_known_categorical_inp_lens) - self.num_historic_vars = sum([self.num_future_vars, - self.temporal_observed_continuous_inp_size, - self.temporal_target_size, - len(self.temporal_observed_categorical_inp_lens), - ]) - -class VolatilityConfig(): - def __init__(self): - - self.features = [ - FeatureSpec('Symbol', InputTypes.ID, DataTypes.CATEGORICAL), - FeatureSpec('days_from_start', InputTypes.TIME, DataTypes.CONTINUOUS), - FeatureSpec('log_vol', InputTypes.TARGET, DataTypes.CONTINUOUS), - FeatureSpec('open_to_close', InputTypes.OBSERVED, DataTypes.CONTINUOUS), - FeatureSpec('days_from_start', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('day_of_week', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('day_of_month', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('week_of_year', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('month', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('Region', InputTypes.STATIC, DataTypes.CATEGORICAL), - ] - - # Dataset split boundaries - self.time_ids = 'date' # This column contains time indices across which we split the data - self.train_range = ('2000-01-01', '2016-01-01') - self.valid_range = ('2016-01-01', '2018-01-01') - self.test_range = ('2018-01-01', '2019-06-28') - self.dataset_stride = 1 #how many timesteps between examples - self.scale_per_id = False - self.missing_id_strategy = None - self.missing_cat_data_strategy='encode_all' - - # Feature sizes - self.static_categorical_inp_lens = [4] - self.temporal_known_categorical_inp_lens = [7,31,53,12] - self.temporal_observed_categorical_inp_lens = [] - self.quantiles = [0.1, 0.5, 0.9] - - self.example_length = 257 - self.encoder_length = 252 - - self.n_head = 4 - self.hidden_size = 96 - self.dropout = 0.4 - self.attn_dropout = 0.0 - - #### Derived variables #### - self.temporal_known_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.KNOWN and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_observed_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.OBSERVED and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_target_size = len([x for x in self.features if x.feature_type == InputTypes.TARGET]) - self.static_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.STATIC and x.feature_embed_type == DataTypes.CONTINUOUS]) - - self.num_static_vars = self.static_continuous_inp_size + len(self.static_categorical_inp_lens) - self.num_future_vars = self.temporal_known_continuous_inp_size + len(self.temporal_known_categorical_inp_lens) - self.num_historic_vars = sum([self.num_future_vars, - self.temporal_observed_continuous_inp_size, - self.temporal_target_size, - len(self.temporal_observed_categorical_inp_lens), - ]) - -class TrafficConfig(): - def __init__(self): - - self.features = [ - FeatureSpec('id', InputTypes.ID, DataTypes.CATEGORICAL), - FeatureSpec('hours_from_start', InputTypes.TIME, DataTypes.CONTINUOUS), - FeatureSpec('values', InputTypes.TARGET, DataTypes.CONTINUOUS), - FeatureSpec('time_on_day', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('day_of_week', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('hours_from_start', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('categorical_id', InputTypes.STATIC, DataTypes.CATEGORICAL), - ] - # Dataset split boundaries - self.time_ids = 'sensor_day' # This column contains time indices across which we split the data - self.train_range = (0, 151) - self.valid_range = (144, 166) - self.test_range = (159, float('inf')) - self.dataset_stride = 1 #how many timesteps between examples - self.scale_per_id = False - self.missing_id_strategy = None - self.missing_cat_data_strategy='encode_all' - - # Feature sizes - self.static_categorical_inp_lens = [963] - self.temporal_known_categorical_inp_lens = [] - self.temporal_observed_categorical_inp_lens = [] - self.quantiles = [0.1, 0.5, 0.9] - - self.example_length = 8 * 24 - self.encoder_length = 7 * 24 - - self.n_head = 4 - self.hidden_size = 128 - self.dropout = 0.3 - self.attn_dropout = 0.0 - - #### Derived variables #### - self.temporal_known_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.KNOWN and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_observed_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.OBSERVED and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_target_size = len([x for x in self.features if x.feature_type == InputTypes.TARGET]) - self.static_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.STATIC and x.feature_embed_type == DataTypes.CONTINUOUS]) - - self.num_static_vars = self.static_continuous_inp_size + len(self.static_categorical_inp_lens) - self.num_future_vars = self.temporal_known_continuous_inp_size + len(self.temporal_known_categorical_inp_lens) - self.num_historic_vars = sum([self.num_future_vars, - self.temporal_observed_continuous_inp_size, - self.temporal_target_size, - len(self.temporal_observed_categorical_inp_lens), - ]) - -class FavoritaConfig(): - def __init__(self): - self.features = [ - FeatureSpec('traj_id', InputTypes.ID, DataTypes.CATEGORICAL), - #FeatureSpec('days_from_start', InputTypes.TIME, DataTypes.CONTINUOUS), - FeatureSpec('date', InputTypes.TIME, DataTypes.DATE), - FeatureSpec('log_sales', InputTypes.TARGET, DataTypes.CONTINUOUS), - # XXX for no apparent reason TF implementation doesn't scale day_of_month - # and month variables. We probably should set them to be categorical - FeatureSpec('day_of_month', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('month', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('onpromotion', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('day_of_week', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('national_hol', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('regional_hol', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('local_hol', InputTypes.KNOWN, DataTypes.CATEGORICAL), - FeatureSpec('open', InputTypes.KNOWN, DataTypes.CONTINUOUS), - FeatureSpec('transactions', InputTypes.OBSERVED, DataTypes.CONTINUOUS), - FeatureSpec('oil', InputTypes.OBSERVED, DataTypes.CONTINUOUS), - FeatureSpec('categorical_id', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('item_nbr', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('store_nbr', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('city', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('state', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('type', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('cluster', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('family', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('class', InputTypes.STATIC, DataTypes.CATEGORICAL), - FeatureSpec('perishable', InputTypes.STATIC, DataTypes.CATEGORICAL) - ] - - # Dataset split boundaries - self.time_ids = 'date' # This column contains time indices across which we split the data - # When relative split is set then it is necessary to provide valid boundary. - # Valid split is shifted from train split by number of forecast steps to the future - # The test split is shifted by the number of forecast steps from the valid split - self.relative_split = True - self.valid_boundary = str(datetime.datetime(2015, 12, 1)) - - self.train_range = None - self.valid_range = None - self.test_range = None - - self.dataset_stride = 1 #how many timesteps between examples - self.scale_per_id = True - self.missing_cat_data_strategy='encode_all' - self.missing_id_strategy = 'drop' - - # Feature sizes - self.static_categorical_inp_lens = [90200, 3426, 53, 22, 16, 5, 17, 32, 313, 2] - self.temporal_known_categorical_inp_lens = [2, 7, 55, 5, 25] - self.temporal_observed_categorical_inp_lens = [] - self.quantiles = [0.1, 0.5, 0.9] - - self.example_length = 120 - self.encoder_length = 90 - - self.n_head = 4 - self.hidden_size = 240 - self.dropout = 0.1 - self.attn_dropout = 0.0 - - #### Derived variables #### - self.temporal_known_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.KNOWN and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_observed_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.OBSERVED and x.feature_embed_type == DataTypes.CONTINUOUS]) - self.temporal_target_size = len([x for x in self.features if x.feature_type == InputTypes.TARGET]) - self.static_continuous_inp_size = len([x for x in self.features - if x.feature_type == InputTypes.STATIC and x.feature_embed_type == DataTypes.CONTINUOUS]) - - self.num_static_vars = self.static_continuous_inp_size + len(self.static_categorical_inp_lens) - self.num_future_vars = self.temporal_known_continuous_inp_size + len(self.temporal_known_categorical_inp_lens) - self.num_historic_vars = sum([self.num_future_vars, - self.temporal_observed_continuous_inp_size, - self.temporal_target_size, - len(self.temporal_observed_categorical_inp_lens), - ]) - -CONFIGS = {'electricity': ElectricityConfig, - 'volatility': VolatilityConfig, - 'traffic': TrafficConfig, - 'favorita': FavoritaConfig, - } diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/criterions.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/criterions.py deleted file mode 100644 index 5c9df6aee..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/criterions.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import torch -import torch.nn as nn -import torch.nn.functional as F - -class QuantileLoss(nn.Module): - def __init__(self, config): - super().__init__() - self.register_buffer('q', torch.tensor(config.quantiles)) - - def forward(self, predictions, targets): - diff = predictions - targets - ql = (1-self.q)*F.relu(diff) + self.q*F.relu(-diff) - losses = ql.view(-1, ql.shape[-1]).mean(0) - return losses diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/data_utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/data_utils.py deleted file mode 100644 index f38f8bfbe..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/data_utils.py +++ /dev/null @@ -1,790 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -################################ -# Copyright 2021 The Google Research Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import math -import pickle -import enum -import datetime - -from collections import namedtuple, OrderedDict - -import sklearn.preprocessing -from sklearn.impute import SimpleImputer -import pandas as pd -import numpy as np -from bisect import bisect - -import torch -from torch.utils.data import Dataset,IterableDataset,DataLoader - -class DataTypes(enum.IntEnum): - """Defines numerical types of each column.""" - CONTINUOUS = 0 - CATEGORICAL = 1 - DATE = 2 - STR = 3 - -class InputTypes(enum.IntEnum): - """Defines input types of each column.""" - TARGET = 0 - OBSERVED = 1 - KNOWN = 2 - STATIC = 3 - ID = 4 # Single column used as an entity identifier - TIME = 5 # Single column exclusively used as a time index - -FeatureSpec = namedtuple('FeatureSpec', ['name', 'feature_type', 'feature_embed_type']) -DTYPE_MAP = { - DataTypes.CONTINUOUS : np.float32, - DataTypes.CATEGORICAL : np.int64, - DataTypes.DATE:'datetime64[ns]', - DataTypes.STR: str - } - -FEAT_ORDER = [ - (InputTypes.STATIC, DataTypes.CATEGORICAL), - (InputTypes.STATIC, DataTypes.CONTINUOUS), - (InputTypes.KNOWN, DataTypes.CATEGORICAL), - (InputTypes.KNOWN, DataTypes.CONTINUOUS), - (InputTypes.OBSERVED, DataTypes.CATEGORICAL), - (InputTypes.OBSERVED, DataTypes.CONTINUOUS), - (InputTypes.TARGET, DataTypes.CONTINUOUS), - (InputTypes.ID, DataTypes.CATEGORICAL) - ] - -FEAT_NAMES = ['s_cat' , 's_cont' , 'k_cat' , 'k_cont' , 'o_cat' , 'o_cont' , 'target', 'id'] -DEFAULT_ID_COL = 'id' - -class TFTBinaryDataset(Dataset): - def __init__(self, path, config): - super(TFTBinaryDataset).__init__() - self.features = [x for x in config.features if x.feature_embed_type != DataTypes.DATE] - self.example_length = config.example_length - self.stride = config.dataset_stride - - self.grouped = pickle.load(open(path, 'rb')) - self.grouped = [x for x in self.grouped if x.shape[0] >= self.example_length] - self._cum_examples_in_group = np.cumsum([(g.shape[0] - self.example_length + 1)//self.stride for g in self.grouped]) - - - self.feature_type_col_map = [[i for i,f in enumerate(self.features) if (f.feature_type, f.feature_embed_type) == x] for x in FEAT_ORDER] - - # The list comprehension below is an elaborate way of rearranging data into correct order, - # simultaneously doing casting to proper types. Probably can be written neater - self.grouped = [ - [ - arr[:, idxs].view(dtype=np.float32).astype(DTYPE_MAP[t[1]]) - for t, idxs in zip(FEAT_ORDER, self.feature_type_col_map) - ] - for arr in self.grouped - ] - - def __len__(self): - return self._cum_examples_in_group[-1] if len(self._cum_examples_in_group) else 0 - - def __getitem__(self, idx): - g_idx = bisect(self._cum_examples_in_group, idx) - e_idx = idx - self._cum_examples_in_group[g_idx-1] if g_idx else idx - - group = self.grouped[g_idx] - - tensors = [ - torch.from_numpy(feat[e_idx * self.stride:e_idx*self.stride + self.example_length]) - if feat.size else torch.empty(0) - for feat in group - ] - - return OrderedDict(zip(FEAT_NAMES, tensors)) - - -class TFTDataset(Dataset): - def __init__(self, path, config): - super(TFTDataset).__init__() - self.features = config.features - self.data = pd.read_csv(path, index_col=0) - self.example_length = config.example_length - self.stride = config.dataset_stride - - # name field is a column name. - # there can be multiple entries with the same name because one column can be interpreted in many ways - time_col_name = next(x.name for x in self.features if x.feature_type==InputTypes.TIME) - id_col_name = next(x.name for x in self.features if x.feature_type==InputTypes.ID) - if not id_col_name in self.data.columns: - id_col_name = DEFAULT_ID_COL - self.features = [x for x in self.features if x.feature_type!=InputTypes.ID] - self.features.append(FeatureSpec(DEFAULT_ID_COL, InputTypes.ID, DataTypes.CATEGORICAL)) - col_dtypes = {v.name:DTYPE_MAP[v.feature_embed_type] for v in self.features} - - - self.data.sort_values(time_col_name,inplace=True) - self.data = self.data[set(x.name for x in self.features)] #leave only relevant columns - self.data = self.data.astype(col_dtypes) - self.data = self.data.groupby(id_col_name).filter(lambda group: len(group) >= self.example_length) - self.grouped = list(self.data.groupby(id_col_name)) - - self._cum_examples_in_group = np.cumsum([(len(g[1]) - self.example_length + 1)//self.stride for g in self.grouped]) - - def __len__(self): - return self._cum_examples_in_group[-1] - - def __getitem__(self, idx): - g_idx = len([x for x in self._cum_examples_in_group if x <= idx]) - e_idx = idx - self._cum_examples_in_group[g_idx-1] if g_idx else idx - - group = self.grouped[g_idx][1] - sliced = group.iloc[e_idx * self.stride:e_idx*self.stride + self.example_length] - - # We need to be sure that tensors are returned in the correct order - tensors = tuple([] for _ in range(8)) - for v in self.features: - if v.feature_type == InputTypes.STATIC and v.feature_embed_type == DataTypes.CATEGORICAL: - tensors[0].append(torch.from_numpy(sliced[v.name].to_numpy())) - elif v.feature_type == InputTypes.STATIC and v.feature_embed_type == DataTypes.CONTINUOUS: - tensors[1].append(torch.from_numpy(sliced[v.name].to_numpy())) - elif v.feature_type == InputTypes.KNOWN and v.feature_embed_type == DataTypes.CATEGORICAL: - tensors[2].append(torch.from_numpy(sliced[v.name].to_numpy())) - elif v.feature_type == InputTypes.KNOWN and v.feature_embed_type == DataTypes.CONTINUOUS: - tensors[3].append(torch.from_numpy(sliced[v.name].to_numpy())) - elif v.feature_type == InputTypes.OBSERVED and v.feature_embed_type == DataTypes.CATEGORICAL: - tensors[4].append(torch.from_numpy(sliced[v.name].to_numpy())) - elif v.feature_type == InputTypes.OBSERVED and v.feature_embed_type == DataTypes.CONTINUOUS: - tensors[5].append(torch.from_numpy(sliced[v.name].to_numpy())) - elif v.feature_type == InputTypes.TARGET: - tensors[6].append(torch.from_numpy(sliced[v.name].to_numpy())) - elif v.feature_type == InputTypes.ID: - tensors[7].append(torch.from_numpy(sliced[v.name].to_numpy())) - - - tensors = [torch.stack(x, dim=-1) if x else torch.empty(0) for x in tensors] - - return OrderedDict(zip(FEAT_NAMES, tensors)) - -def get_dataset_splits(df, config): - - if hasattr(config, 'relative_split') and config.relative_split: - forecast_len = config.example_length - config.encoder_length - # The valid split is shifted from the train split by number of the forecast steps to the future. - # The test split is shifted by the number of the forecast steps from the valid split - train = [] - valid = [] - test = [] - - for _, group in df.groupby(DEFAULT_ID_COL): - index = group[config.time_ids] - _train = group.loc[index < config.valid_boundary] - _valid = group.iloc[(len(_train) - config.encoder_length):(len(_train) + forecast_len)] - _test = group.iloc[(len(_train) - config.encoder_length + forecast_len):(len(_train) + 2*forecast_len)] - train.append(_train) - valid.append(_valid) - test.append(_test) - - train = pd.concat(train, axis=0) - valid = pd.concat(valid, axis=0) - test = pd.concat(test, axis=0) - else: - index = df[config.time_ids] - train = df.loc[(index >= config.train_range[0]) & (index < config.train_range[1])] - valid = df.loc[(index >= config.valid_range[0]) & (index < config.valid_range[1])] - test = df.loc[(index >= config.test_range[0]) & (index < config.test_range[1])] - - return train, valid, test - -def flatten_ids(df, config): - - if config.missing_id_strategy == 'drop': - if hasattr(config, 'combine_ids') and config.combine_ids: - index = np.logical_or.reduce([df[c].isna() for c in config.combine_ids]) - else: - id_col = next(x.name for x in config.features if x.feature_type == InputTypes.ID) - index = df[id_col].isna() - index = index[index == True].index # Extract indices of nans - df.drop(index, inplace=True) - - if not (hasattr(config, 'combine_ids') and config.combine_ids): - id_col = next(x.name for x in config.features if x.feature_type == InputTypes.ID) - ids = df[id_col].apply(str) - df.drop(id_col, axis=1, inplace=True) - encoder = sklearn.preprocessing.LabelEncoder().fit(ids.values) - df[DEFAULT_ID_COL] = encoder.transform(ids) - encoders = OrderedDict({id_col: encoder}) - - else: - encoders = {c:sklearn.preprocessing.LabelEncoder().fit(df[c].values) for c in config.combine_ids} - encoders = OrderedDict(encoders) - lens = [len(v.classes_) for v in encoders.values()] - clens = np.roll(np.cumprod(lens), 1) - clens[0] = 1 - - # this takes a looooooot of time. Probably it would be better to create 2 dummy columns - df[DEFAULT_ID_COL] = df.apply(lambda row: sum([encoders[c].transform([row[c]])[0]*clens[i] for i,c in enumerate(encoders.keys())]), axis=1) - df.drop(config.combine_ids, axis=1, inplace=True) - - return DEFAULT_ID_COL, encoders - -def impute(df, config): - #XXX This ensures that out scaling will have the same mean. We still need to check the variance - if not hasattr(config, 'missing_data_label'): - return df, None - else: - imp = SimpleImputer(missing_values=config.missing_data_label, strategy='mean') - mask = df.applymap(lambda x: True if x == config.missing_data_label else False) - data = df.values - col_mask = (data == config.missing_data_label).all(axis=0) - data[:,~col_mask] = imp.fit_transform(data) - return data, mask - -def normalize_reals(train, valid, test, config, id_col=DEFAULT_ID_COL): - tgt_cols = [x.name for x in config.features if x.feature_type == InputTypes.TARGET] - real_cols = list(set(v.name for v in config.features if v.feature_embed_type == DataTypes.CONTINUOUS).difference(set(tgt_cols))) - real_scalers = {} - tgt_scalers = {} - - def apply_scalers(df, name=None): - if name is None: - name = df.name - mask = df.applymap(lambda x: True if x == config.missing_data_label else False) if hasattr(config, 'missing_data_label') else None - df[real_cols] = real_scalers[name].transform(df[real_cols]) - if mask is not None and any(mask): - df[real_cols].mask(mask, 10**9) - df[tgt_cols] = tgt_scalers[name].transform(df[tgt_cols]) - return df - - if config.scale_per_id: - for identifier, sliced in train.groupby(id_col): - data = sliced[real_cols] - data, _ = impute(data, config) - real_scalers[identifier] = sklearn.preprocessing.StandardScaler().fit(data) - # XXX We should probably remove examples that contain NaN as a target - target = sliced[tgt_cols] - tgt_scalers[identifier] = sklearn.preprocessing.StandardScaler().fit(target) - - train = train.groupby(id_col).apply(apply_scalers) - # For valid and testing leave only timeseries previously present in train subset - # XXX for proper data science we should consider encoding unseen timeseries as a special case, not throwing them away - valid = valid.loc[valid[id_col].isin(real_scalers.keys())] - valid = valid.groupby(id_col).apply(apply_scalers) - test = test.loc[test[id_col].isin(real_scalers.keys())] - test = test.groupby(id_col).apply(apply_scalers) - - else: - data, _ = impute(train[real_cols], config) - real_scalers[''] = sklearn.preprocessing.StandardScaler().fit(data) - tgt_scalers[''] = sklearn.preprocessing.StandardScaler().fit(train[tgt_cols]) - - train = apply_scalers(train, name='') - valid = apply_scalers(valid, name='') - test = apply_scalers(test, name='') - - return train, valid, test, real_scalers, tgt_scalers - -def encode_categoricals(train, valid, test, config): - cat_encodings = {} - cat_cols = list(set(v.name for v in config.features if v.feature_embed_type == DataTypes.CATEGORICAL and v.feature_type != InputTypes.ID)) - num_classes = [] #XXX Maybe we should modify config based on this value? Or send a warninig? - # For TC performance reasons we might want for num_classes[i] be divisible by 8 - - # Train categorical encoders - for c in cat_cols: - if config.missing_cat_data_strategy == 'special_token': - #XXX this will probably require some data augmentation - unique = train[c].unique() - valid[c].loc[valid[c].isin(unique)] = '' - test[c].loc[test[c].isin(unique)] = '' - - if config.missing_cat_data_strategy == 'encode_all' or \ - config.missing_cat_data_strategy == 'special_token': - srs = pd.concat([train[c], valid[c], test[c]]).apply(str) - cat_encodings[c] = sklearn.preprocessing.LabelEncoder().fit(srs.values) - elif config.missing_cat_data_strategy == 'drop': - # TODO: implement this. In addition to dropping rows this has to split specific time series in chunks - # to prevent data from having temporal gaps - pass - num_classes.append(srs.nunique()) - print('Categorical variables encodings lens: ', num_classes) - - - for split in [train, valid, test]: - for c in cat_cols: - srs = split[c].apply(str) - split[c] = srs - split.loc[:,c] = cat_encodings[c].transform(srs) - - return cat_encodings - - -def preprocess(src_path, dst_path, config): - df = pd.read_csv(src_path, index_col=0) - - for c in config.features: - if c.feature_embed_type == DataTypes.DATE: - df[c.name] = pd.to_datetime(df[c.name]) - - # Leave only columns relevant to preprocessing - relevant_columns = list(set([f.name for f in config.features] + [config.time_ids])) - df = df[relevant_columns] - - - id_col, id_encoders = flatten_ids(df, config) - df = df.reindex(sorted(df.columns), axis=1) - - train, valid, test = get_dataset_splits(df, config) - - # Length filter the data (all timeseries shorter than example len will be dropped) - #for df in [train, valid, test]: - # df.groupby(id_col).filter(lambda x: len(x) >= config.example_length) - train = pd.concat([x[1] for x in train.groupby(id_col) if len(x[1]) >= config.example_length]) - valid = pd.concat([x[1] for x in valid.groupby(id_col) if len(x[1]) >= config.example_length]) - test = pd.concat([x[1] for x in test.groupby(id_col) if len(x[1]) >= config.example_length]) - - train, valid, test, real_scalers, tgt_scalers = normalize_reals(train, valid, test, config, id_col) - - cat_encodings = encode_categoricals(train, valid, test, config) - - os.makedirs(dst_path, exist_ok=True) - - train.to_csv(os.path.join(dst_path, 'train.csv')) - valid.to_csv(os.path.join(dst_path, 'valid.csv')) - test.to_csv(os.path.join(dst_path, 'test.csv')) - - # Save relevant columns in binary form for faster dataloading - # IMORTANT: We always expect id to be a single column indicating the complete timeseries - # We also expect a copy of id in form of static categorical input!!! - col_names = [id_col] + [x.name for x in config.features if x.feature_embed_type != DataTypes.DATE and x.feature_type != InputTypes.ID] - grouped_train = [x[1][col_names].values.astype(np.float32).view(dtype=np.int32) for x in train.groupby(id_col)] - grouped_valid = [x[1][col_names].values.astype(np.float32).view(dtype=np.int32) for x in valid.groupby(id_col)] - grouped_test = [x[1][col_names].values.astype(np.float32).view(dtype=np.int32) for x in test.groupby(id_col)] - - pickle.dump(grouped_train, open(os.path.join(dst_path, 'train.bin'), 'wb')) - pickle.dump(grouped_valid, open(os.path.join(dst_path, 'valid.bin'), 'wb')) - pickle.dump(grouped_test, open(os.path.join(dst_path, 'test.bin'), 'wb')) - - - with open(os.path.join(dst_path, 'real_scalers.bin'), 'wb') as f: - pickle.dump(real_scalers, f) - with open(os.path.join(dst_path, 'tgt_scalers.bin'), 'wb') as f: - pickle.dump(tgt_scalers, f) - with open(os.path.join(dst_path, 'cat_encodings.bin'), 'wb') as f: - pickle.dump(cat_encodings, f) - with open(os.path.join(dst_path, 'id_encoders.bin'), 'wb') as f: - pickle.dump(id_encoders, f) - - -def sample_data(dataset, num_samples): - if num_samples < 0: - return dataset - else: - return torch.utils.data.Subset(dataset, np.random.choice(np.arange(len(dataset)), size=num_samples, replace=False)) - - -def standarize_electricity(path): - """Code taken from https://github.com/google-research/google-research/blob/master/tft/script_download_data.py""" - df = pd.read_csv(os.path.join(path, 'LD2011_2014.txt'), index_col=0, sep=';', decimal=',') - df.index = pd.to_datetime(df.index) - df.sort_index(inplace=True) - - # Used to determine the start and end dates of a series - output = df.resample('1h').mean().replace(0., np.nan) - - earliest_time = output.index.min() - - df_list = [] - for label in output: - print('Processing {}'.format(label)) - srs = output[label] - - start_date = min(srs.fillna(method='ffill').dropna().index) - end_date = max(srs.fillna(method='bfill').dropna().index) - - active_range = (srs.index >= start_date) & (srs.index <= end_date) - srs = srs[active_range].fillna(0.) - - tmp = pd.DataFrame({'power_usage': srs}) - date = tmp.index - tmp['t'] = (date - earliest_time).seconds / 60 / 60 + ( - date - earliest_time).days * 24 - tmp['days_from_start'] = (date - earliest_time).days - tmp['categorical_id'] = label - tmp['date'] = date - tmp['id'] = label - tmp['hour'] = date.hour - tmp['day'] = date.day - tmp['day_of_week'] = date.dayofweek - tmp['month'] = date.month - - df_list.append(tmp) - - output = pd.concat(df_list, axis=0, join='outer').reset_index(drop=True) - - output['categorical_id'] = output['id'].copy() - output['hours_from_start'] = output['t'] - output['categorical_day_of_week'] = output['day_of_week'].copy() - output['categorical_hour'] = output['hour'].copy() - - output.to_csv(os.path.join(path, 'standarized.csv')) - -def standarize_volatility(path): - df = pd.read_csv(os.path.join(path, 'oxfordmanrealizedvolatilityindices.csv'), index_col=0) # no explicit index - - # Adds additional date/day fields - idx = [str(s).split('+')[0] for s in df.index - ] # ignore timezones, we don't need them - dates = pd.to_datetime(idx) - df['date'] = dates - df['days_from_start'] = (dates - pd.datetime(2000, 1, 3)).days - df['day_of_week'] = dates.dayofweek - df['day_of_month'] = dates.day - df['week_of_year'] = dates.weekofyear - df['month'] = dates.month - df['year'] = dates.year - df['categorical_id'] = df['Symbol'].copy() - - # Processes log volatility - vol = df['rv5_ss'].copy() - vol.loc[vol == 0.] = np.nan - df['log_vol'] = np.log(vol) - - # Adds static information - symbol_region_mapping = { - '.AEX': 'EMEA', - '.AORD': 'APAC', - '.BFX': 'EMEA', - '.BSESN': 'APAC', - '.BVLG': 'EMEA', - '.BVSP': 'AMER', - '.DJI': 'AMER', - '.FCHI': 'EMEA', - '.FTMIB': 'EMEA', - '.FTSE': 'EMEA', - '.GDAXI': 'EMEA', - '.GSPTSE': 'AMER', - '.HSI': 'APAC', - '.IBEX': 'EMEA', - '.IXIC': 'AMER', - '.KS11': 'APAC', - '.KSE': 'APAC', - '.MXX': 'AMER', - '.N225': 'APAC ', - '.NSEI': 'APAC', - '.OMXC20': 'EMEA', - '.OMXHPI': 'EMEA', - '.OMXSPI': 'EMEA', - '.OSEAX': 'EMEA', - '.RUT': 'EMEA', - '.SMSI': 'EMEA', - '.SPX': 'AMER', - '.SSEC': 'APAC', - '.SSMI': 'EMEA', - '.STI': 'APAC', - '.STOXX50E': 'EMEA' - } - - df['Region'] = df['Symbol'].apply(lambda k: symbol_region_mapping[k]) - - # Performs final processing - output_df_list = [] - for grp in df.groupby('Symbol'): - sliced = grp[1].copy() - sliced.sort_values('days_from_start', inplace=True) - # Impute log volatility values - sliced['log_vol'].fillna(method='ffill', inplace=True) - sliced.dropna() - output_df_list.append(sliced) - - df = pd.concat(output_df_list, axis=0) - - df.to_csv(os.path.join(path, 'standarized.csv')) - - -def standarize_traffic(path): - def process_list(s, variable_type=int, delimiter=None): - """Parses a line in the PEMS format to a list.""" - if delimiter is None: - l = [ - variable_type(i) for i in s.replace('[', '').replace(']', '').split() - ] - else: - l = [ - variable_type(i) - for i in s.replace('[', '').replace(']', '').split(delimiter) - ] - - return l - - def read_single_list(filename): - """Returns single list from a file in the PEMS-custom format.""" - with open(os.path.join(path, filename), 'r') as dat: - l = process_list(dat.readlines()[0]) - return l - - def read_matrix(filename): - """Returns a matrix from a file in the PEMS-custom format.""" - array_list = [] - with open(os.path.join(path, filename), 'r') as dat: - lines = dat.readlines() - for i, line in enumerate(lines): - if (i + 1) % 50 == 0: - print('Completed {} of {} rows for {}'.format(i + 1, len(lines), - filename)) - array = [ - process_list(row_split, variable_type=float, delimiter=None) - for row_split in process_list( - line, variable_type=str, delimiter=';') - ] - array_list.append(array) - - return array_list - - shuffle_order = np.array(read_single_list('randperm')) - 1 # index from 0 - train_dayofweek = read_single_list('PEMS_trainlabels') - train_tensor = read_matrix('PEMS_train') - test_dayofweek = read_single_list('PEMS_testlabels') - test_tensor = read_matrix('PEMS_test') - - # Inverse permutate shuffle order - print('Shuffling') - inverse_mapping = { - new_location: previous_location - for previous_location, new_location in enumerate(shuffle_order) - } - reverse_shuffle_order = np.array([ - inverse_mapping[new_location] - for new_location, _ in enumerate(shuffle_order) - ]) - - # Group and reoder based on permuation matrix - print('Reodering') - day_of_week = np.array(train_dayofweek + test_dayofweek) - combined_tensor = np.array(train_tensor + test_tensor) - - day_of_week = day_of_week[reverse_shuffle_order] - combined_tensor = combined_tensor[reverse_shuffle_order] - - # Put everything back into a dataframe - print('Parsing as dataframe') - labels = ['traj_{}'.format(i) for i in read_single_list('stations_list')] - - hourly_list = [] - for day, day_matrix in enumerate(combined_tensor): - # Hourly data - hourly = pd.DataFrame(day_matrix.T, columns=labels) - hourly['hour_on_day'] = [int(i / 6) for i in hourly.index - ] # sampled at 10 min intervals - if hourly['hour_on_day'].max() > 23 or hourly['hour_on_day'].min() < 0: - raise ValueError('Invalid hour! {}-{}'.format( - hourly['hour_on_day'].min(), hourly['hour_on_day'].max())) - - hourly = hourly.groupby('hour_on_day', as_index=True).mean()[labels] - hourly['sensor_day'] = day - hourly['time_on_day'] = hourly.index - hourly['day_of_week'] = day_of_week[day] - - hourly_list.append(hourly) - - hourly_frame = pd.concat(hourly_list, axis=0, ignore_index=True, sort=False) - - # Flatten such that each entitiy uses one row in dataframe - store_columns = [c for c in hourly_frame.columns if 'traj' in c] - other_columns = [c for c in hourly_frame.columns if 'traj' not in c] - flat_df = pd.DataFrame(columns=['values', 'prev_values', 'next_values'] + - other_columns + ['id']) - - for store in store_columns: - print('Processing {}'.format(store)) - - sliced = hourly_frame[[store] + other_columns].copy() - sliced.columns = ['values'] + other_columns - sliced['id'] = int(store.replace('traj_', '')) - - # Sort by Sensor-date-time - key = sliced['id'].apply(str) \ - + sliced['sensor_day'].apply(lambda x: '_{:03d}'.format(x)) \ - + sliced['time_on_day'].apply(lambda x: '_{:03d}'.format(x)) - sliced = sliced.set_index(key).sort_index() - - sliced['values'] = sliced['values'].fillna(method='ffill') - sliced['prev_values'] = sliced['values'].shift(1) - sliced['next_values'] = sliced['values'].shift(-1) - - flat_df = flat_df.append(sliced.dropna(), ignore_index=True, sort=False) - - # Filter to match range used by other academic papers - index = flat_df['sensor_day'] - flat_df = flat_df[index < 173].copy() - - # Creating columns fo categorical inputs - flat_df['categorical_id'] = flat_df['id'].copy() - flat_df['hours_from_start'] = flat_df['time_on_day'] \ - + flat_df['sensor_day']*24. - flat_df['categorical_day_of_week'] = flat_df['day_of_week'].copy() - flat_df['categorical_time_on_day'] = flat_df['time_on_day'].copy() - - flat_df.to_csv(os.path.join(path, 'standarized.csv')) - - -# XXX needs rework -def standarize_favorita(data_folder): - import gc - # Extract only a subset of data to save/process for efficiency - start_date = pd.datetime(2015, 1, 1) - end_date = pd.datetime(2016, 6, 1) - - print('Regenerating data...') - - # load temporal data - temporal = pd.read_csv(os.path.join(data_folder, 'train.csv'), index_col=0) - - store_info = pd.read_csv(os.path.join(data_folder, 'stores.csv'), index_col=0) - oil = pd.read_csv( - os.path.join(data_folder, 'oil.csv'), index_col=0).iloc[:, 0] - holidays = pd.read_csv(os.path.join(data_folder, 'holidays_events.csv')) - items = pd.read_csv(os.path.join(data_folder, 'items.csv'), index_col=0) - transactions = pd.read_csv(os.path.join(data_folder, 'transactions.csv')) - - # Take first 6 months of data - temporal['date'] = pd.to_datetime(temporal['date']) - - # Filter dates to reduce storage space requirements - if start_date is not None: - temporal = temporal[(temporal['date'] >= start_date)] - if end_date is not None: - temporal = temporal[(temporal['date'] < end_date)] - - dates = temporal['date'].unique() - - # Add trajectory identifier - temporal['traj_id'] = temporal['store_nbr'].apply( - str) + '_' + temporal['item_nbr'].apply(str) - temporal['unique_id'] = temporal['traj_id'] + '_' + temporal['date'].apply( - str) - - # Remove all IDs with negative returns - print('Removing returns data') - min_returns = temporal['unit_sales'].groupby(temporal['traj_id']).min() - valid_ids = set(min_returns[min_returns >= 0].index) - selector = temporal['traj_id'].apply(lambda traj_id: traj_id in valid_ids) - new_temporal = temporal[selector].copy() - del temporal - gc.collect() - temporal = new_temporal - temporal['open'] = 1 - - # Resampling - print('Resampling to regular grid') - resampled_dfs = [] - for traj_id, raw_sub_df in temporal.groupby('traj_id'): - print('Resampling', traj_id) - sub_df = raw_sub_df.set_index('date', drop=True).copy() - sub_df = sub_df.resample('1d').last() - sub_df['date'] = sub_df.index - sub_df[['store_nbr', 'item_nbr', 'onpromotion']] \ - = sub_df[['store_nbr', 'item_nbr', 'onpromotion']].fillna(method='ffill') - sub_df['open'] = sub_df['open'].fillna( - 0) # flag where sales data is unknown - sub_df['log_sales'] = np.log(sub_df['unit_sales']) - - resampled_dfs.append(sub_df.reset_index(drop=True)) - - new_temporal = pd.concat(resampled_dfs, axis=0) - del temporal - gc.collect() - temporal = new_temporal - - print('Adding oil') - oil.name = 'oil' - oil.index = pd.to_datetime(oil.index) - #XXX the lines below match the value of the oil on given date with the rest of the timeseries - # missing values in oil series are copied from the index before. Then the oil series is joined with - # temporal. Then there are some dates present in temporal which arent present in oil, for which - # oil values is substituted with -1. WHY?! - #TODO: check how many nans there are after first step. Previously oil series was extended by dates - # present in dates variable with nan value, which were forward filled. - # This behavior is no longer supported by pandas, so we changed to DataFrame.isin method. - # This leaves us with more nans after first step than previously. To achieve previous behavior - # we have to join series before filling nans. - temporal = temporal.join( - #oil.loc[oil.index.isin(dates)].fillna(method='ffill'), on='date', how='left') - oil.loc[oil.index.isin(dates)], on='date', how='left') - temporal['oil'] = temporal['oil'].fillna(method='ffill') - temporal['oil'] = temporal['oil'].fillna(-1) - - print('Adding store info') - temporal = temporal.join(store_info, on='store_nbr', how='left') - - print('Adding item info') - temporal = temporal.join(items, on='item_nbr', how='left') - - transactions['date'] = pd.to_datetime(transactions['date']) - temporal = temporal.merge( - transactions, - left_on=['date', 'store_nbr'], - right_on=['date', 'store_nbr'], - how='left') - temporal['transactions'] = temporal['transactions'].fillna(-1) - - # Additional date info - temporal['day_of_week'] = pd.to_datetime(temporal['date'].values).dayofweek - temporal['day_of_month'] = pd.to_datetime(temporal['date'].values).day - temporal['month'] = pd.to_datetime(temporal['date'].values).month - - # Add holiday info - print('Adding holidays') - holiday_subset = holidays[holidays['transferred'].apply( - lambda x: not x)].copy() - holiday_subset.columns = [ - s if s != 'type' else 'holiday_type' for s in holiday_subset.columns - ] - holiday_subset['date'] = pd.to_datetime(holiday_subset['date']) - local_holidays = holiday_subset[holiday_subset['locale'] == 'Local'] - regional_holidays = holiday_subset[holiday_subset['locale'] == 'Regional'] - national_holidays = holiday_subset[holiday_subset['locale'] == 'National'] - - temporal['national_hol'] = temporal.merge( - national_holidays, left_on=['date'], right_on=['date'], - how='left')['description'].fillna('') - temporal['regional_hol'] = temporal.merge( - regional_holidays, - left_on=['state', 'date'], - right_on=['locale_name', 'date'], - how='left')['description'].fillna('') - temporal['local_hol'] = temporal.merge( - local_holidays, - left_on=['city', 'date'], - right_on=['locale_name', 'date'], - how='left')['description'].fillna('') - - temporal.sort_values('unique_id', inplace=True) - - # Transform date to integer index - start_date = pd.to_datetime(min(temporal['date'])) - dates = temporal['date'].apply(pd.to_datetime) - temporal['days_from_start'] = (dates - start_date).dt.days - temporal['categorical_id'] = temporal['traj_id'].copy() - - print('Saving processed file to {}'.format(os.path.join(data_folder, 'standarized.csv'))) - temporal.to_csv(os.path.join(data_folder, 'standarized.csv')) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/ema.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/ema.py deleted file mode 100644 index de9b33da2..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/ema.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Exponential Moving Average (EMA) of model updates -""" - -from collections import OrderedDict -from copy import deepcopy - -import torch -import torch.nn as nn - -class ModelEma(nn.Module): - """ Model Exponential Moving Average V2 - - Keep a moving average of everything in the model state_dict (parameters and buffers). - V2 of this module is simpler, it does not match params/buffers based on name but simply - iterates in order. It works with torchscript (JIT of full model). - - """ - def __init__(self, model, decay=0.999, device=None): - super().__init__() - # make a copy of the model for accumulating moving average of weights - self.module = deepcopy(model) - self.module.eval() - self.decay = decay - self.device = device # perform ema on different device from model if set - if self.device is not None: - self.module.to(device=device) - - def update(self, model): - update_fn=lambda ema_v, model_v: self.decay * ema_v + (1. - self.decay) * model_v - with torch.no_grad(): - for ema_v, model_v in zip(self.module.state_dict().values(), model.state_dict().values()): - if self.device is not None: - model_v = model_v.to(device=self.device) - ema_v.copy_(update_fn(ema_v, model_v)) - - def set(self, model): - with torch.no_grad(): - for ema_v, model_v in zip(self.module.state_dict().values(), model.state_dict().values()): - if self.device is not None: - model_v = model_v.to(device=self.device) - ema_v.copy_( model_v ) - - def forward(self, x): - return self.module(x) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/gpu_affinity.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/gpu_affinity.py deleted file mode 100644 index 79fb1fc48..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/gpu_affinity.py +++ /dev/null @@ -1,157 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import collections -import math -import os -import pathlib -import re - -import pynvml - -pynvml.nvmlInit() - - -def systemGetDriverVersion(): - return pynvml.nvmlSystemGetDriverVersion() - - -def deviceGetCount(): - return pynvml.nvmlDeviceGetCount() - - -class device: - # assume nvml returns list of 64 bit ints - _nvml_affinity_elements = math.ceil(os.cpu_count() / 64) - - def __init__(self, device_idx): - super().__init__() - self.handle = pynvml.nvmlDeviceGetHandleByIndex(device_idx) - - def getName(self): - return pynvml.nvmlDeviceGetName(self.handle) - - def getCpuAffinity(self): - affinity_string = '' - for j in pynvml.nvmlDeviceGetCpuAffinity( - self.handle, device._nvml_affinity_elements - ): - # assume nvml returns list of 64 bit ints - affinity_string = '{:064b}'.format(j) + affinity_string - affinity_list = [int(x) for x in affinity_string] - affinity_list.reverse() # so core 0 is in 0th element of list - - ret = [i for i, e in enumerate(affinity_list) if e != 0] - return ret - - -def set_socket_affinity(gpu_id): - dev = device(gpu_id) - affinity = dev.getCpuAffinity() - os.sched_setaffinity(0, affinity) - - -def set_single_affinity(gpu_id): - dev = device(gpu_id) - affinity = dev.getCpuAffinity() - os.sched_setaffinity(0, affinity[:1]) - - -def set_single_unique_affinity(gpu_id, nproc_per_node): - devices = [device(i) for i in range(nproc_per_node)] - socket_affinities = [dev.getCpuAffinity() for dev in devices] - - siblings_list = get_thread_siblings_list() - siblings_dict = dict(siblings_list) - - # remove siblings - for idx, socket_affinity in enumerate(socket_affinities): - socket_affinities[idx] = list(set(socket_affinity) - set(siblings_dict.values())) - - affinities = [] - assigned = [] - - for socket_affinity in socket_affinities: - for core in socket_affinity: - if core not in assigned: - affinities.append([core]) - assigned.append(core) - break - os.sched_setaffinity(0, affinities[gpu_id]) - - -def set_socket_unique_affinity(gpu_id, nproc_per_node, mode): - device_ids = [device(i) for i in range(nproc_per_node)] - socket_affinities = [dev.getCpuAffinity() for dev in device_ids] - - siblings_list = get_thread_siblings_list() - siblings_dict = dict(siblings_list) - - # remove siblings - for idx, socket_affinity in enumerate(socket_affinities): - socket_affinities[idx] = list(set(socket_affinity) - set(siblings_dict.values())) - - socket_affinities_to_device_ids = collections.defaultdict(list) - - for idx, socket_affinity in enumerate(socket_affinities): - socket_affinities_to_device_ids[tuple(socket_affinity)].append(idx) - - for socket_affinity, device_ids in socket_affinities_to_device_ids.items(): - devices_per_group = len(device_ids) - cores_per_device = len(socket_affinity) // devices_per_group - for group_id, device_id in enumerate(device_ids): - if device_id == gpu_id: - if mode == 'interleaved': - affinity = list(socket_affinity[group_id::devices_per_group]) - elif mode == 'continuous': - affinity = list(socket_affinity[group_id*cores_per_device:(group_id+1)*cores_per_device]) - else: - raise RuntimeError('Unknown set_socket_unique_affinity mode') - - # reintroduce siblings - affinity += [siblings_dict[aff] for aff in affinity if aff in siblings_dict] - os.sched_setaffinity(0, affinity) - - -def get_thread_siblings_list(): - path = '/sys/devices/system/cpu/cpu*/topology/thread_siblings_list' - thread_siblings_list = [] - pattern = re.compile(r'(\d+)\D(\d+)') - for fname in pathlib.Path(path[0]).glob(path[1:]): - with open(fname) as f: - content = f.read().strip() - res = pattern.findall(content) - if res: - pair = tuple(map(int, res[0])) - thread_siblings_list.append(pair) - return thread_siblings_list - - -def set_affinity(gpu_id, nproc_per_node, mode='socket'): - if mode == 'socket': - set_socket_affinity(gpu_id) - elif mode == 'single': - set_single_affinity(gpu_id) - elif mode == 'single_unique': - set_single_unique_affinity(gpu_id, nproc_per_node) - elif mode == 'socket_unique_interleaved': - set_socket_unique_affinity(gpu_id, nproc_per_node, 'interleaved') - elif mode == 'socket_unique_continuous': - set_socket_unique_affinity(gpu_id, nproc_per_node, 'continuous') - else: - raise RuntimeError('Unknown affinity mode') - - affinity = os.sched_getaffinity(0) - return affinity - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/inference.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/inference.py deleted file mode 100644 index 056429f16..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/inference.py +++ /dev/null @@ -1,239 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import pandas as pd -import numpy as np -import pickle -import argparse -import torch -from torch.utils.data import DataLoader -from torch.cuda import amp -from torch.utils.tensorboard import SummaryWriter -from tqdm import tqdm -from modeling import TemporalFusionTransformer -from configuration import ElectricityConfig -from data_utils import TFTDataset -from utils import PerformanceMeter -from criterions import QuantileLoss -import dllogger -from log_helper import setup_logger - -def _unscale_per_id(config, values, ids, scalers): - values = values.cpu().numpy() - num_horizons = config.example_length - config.encoder_length + 1 - flat_values = pd.DataFrame( - values, - columns=[f't{j}' for j in range(num_horizons - values.shape[1], num_horizons)] - ) - flat_values['id'] = ids - df_list = [] - for idx, group in flat_values.groupby('id'): - scaler = scalers[idx] - group_copy = group.copy() - for col in group_copy.columns: - if not 'id' in col: - _col = np.expand_dims(group_copy[col].values, -1) - _t_col = scaler.inverse_transform(_col)[:,-1] - group_copy[col] = _t_col - df_list.append(group_copy) - flat_values = pd.concat(df_list, axis=0) - - flat_values = flat_values[[col for col in flat_values if not 'id' in col]] - flat_tensor = torch.from_numpy(flat_values.values) - return flat_tensor - -def _unscale(config, values, scaler): - values = values.cpu().numpy() - num_horizons = config.example_length - config.encoder_length + 1 - flat_values = pd.DataFrame( - values, - columns=[f't{j}' for j in range(num_horizons - values.shape[1], num_horizons)] - ) - for col in flat_values.columns: - if not 'id' in col: - _col = np.expand_dims(flat_values[col].values, -1) - _t_col = scaler.inverse_transform(_col)[:,-1] - flat_values[col] = _t_col - - flat_values = flat_values[[col for col in flat_values if not 'id' in col]] - flat_tensor = torch.from_numpy(flat_values.values) - return flat_tensor - -def predict(args, config, model, data_loader, scalers, cat_encodings, extend_targets=False): - model.eval() - predictions = [] - targets = [] - ids = [] - perf_meter = PerformanceMeter() - n_workers = args.distributed_world_size if hasattr(args, 'distributed_world_size') else 1 - - for step, batch in enumerate(data_loader): - perf_meter.reset_current_lap() - with torch.no_grad(): - batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in batch.items()} - ids.append(batch['id'][:,0,:]) - targets.append(batch['target']) - predictions.append(model(batch).float()) - - perf_meter.update(args.batch_size * n_workers, - exclude_from_total=step in [0, len(data_loader)-1]) - - targets = torch.cat(targets, dim=0) - if not extend_targets: - targets = targets[:,config.encoder_length:,:] - predictions = torch.cat(predictions, dim=0) - - if config.scale_per_id: - ids = torch.cat(ids, dim=0).cpu().numpy() - - unscaled_predictions = torch.stack( - [_unscale_per_id(config, predictions[:,:,i], ids, scalers) for i in range(len(config.quantiles))], - dim=-1) - unscaled_targets = _unscale_per_id(config, targets[:,:,0], ids, scalers).unsqueeze(-1) - else: - ids = None - unscaled_predictions = torch.stack( - [_unscale(config, predictions[:,:,i], scalers['']) for i in range(len(config.quantiles))], - dim=-1) - unscaled_targets = _unscale(config, targets[:,:,0], scalers['']).unsqueeze(-1) - - return unscaled_predictions, unscaled_targets, ids, perf_meter - -def visualize_v2(args, config, model, data_loader, scalers, cat_encodings): - unscaled_predictions, unscaled_targets, ids, _ = predict(args, config, model, data_loader, scalers, cat_encodings, extend_targets=True) - - num_horizons = config.example_length - config.encoder_length + 1 - pad = unscaled_predictions.new_full((unscaled_targets.shape[0], unscaled_targets.shape[1] - unscaled_predictions.shape[1], unscaled_predictions.shape[2]), fill_value=float('nan')) - pad[:,-1,:] = unscaled_targets[:,-num_horizons,:] - unscaled_predictions = torch.cat((pad, unscaled_predictions), dim=1) - - ids = torch.from_numpy(ids.squeeze()) - joint_graphs = torch.cat([unscaled_targets, unscaled_predictions], dim=2) - graphs = {i:joint_graphs[ids == i, :, :] for i in set(ids.tolist())} - for key, g in graphs.items(): - for i, ex in enumerate(g): - df = pd.DataFrame(ex.numpy(), - index=range(num_horizons - ex.shape[0], num_horizons), - columns=['target'] + [f'P{int(q*100)}' for q in config.quantiles]) - fig = df.plot().get_figure() - ax = fig.get_axes()[0] - _values = df.values[config.encoder_length-1:,:] - ax.fill_between(range(num_horizons), _values[:,1], _values[:,-1], alpha=0.2, color='green') - os.makedirs(os.path.join(args.results, 'single_example_vis', str(key)), exist_ok=True) - fig.savefig(os.path.join(args.results, 'single_example_vis', str(key), f'{i}.pdf')) - -def inference(args, config, model, data_loader, scalers, cat_encodings): - unscaled_predictions, unscaled_targets, ids, perf_meter = predict(args, config, model, data_loader, scalers, cat_encodings) - - if args.joint_visualization or args.save_predictions: - ids = torch.from_numpy(ids.squeeze()) - #ids = torch.cat([x['id'][0] for x in data_loader.dataset]) - joint_graphs = torch.cat([unscaled_targets, unscaled_predictions], dim=2) - graphs = {i:joint_graphs[ids == i, :, :] for i in set(ids.tolist())} - for key, g in graphs.items(): #timeseries id, joint targets and predictions - _g = {'targets': g[:,:,0]} - _g.update({f'P{int(q*100)}':g[:,:,i+1] for i, q in enumerate(config.quantiles)}) - - if args.joint_visualization: - summary_writer = SummaryWriter(log_dir=os.path.join(args.results, 'predictions_vis', str(key))) - for q, t in _g.items(): # target and quantiles, timehorizon values - if q == 'targets': - targets = torch.cat([t[:,0], t[-1,1:]]) # WIP - # We want to plot targets on the same graph as predictions. Probably could be written better. - for i, val in enumerate(targets): - summary_writer.add_scalars(str(key), {f'{q}':val}, i) - continue - - # Tensor t contains different time horizons which are shifted in phase - # Next lines realign them - y = t.new_full((t.shape[0] + t.shape[1] -1, t.shape[1]), float('nan')) - for i in range(y.shape[1]): - y[i:i+t.shape[0], i] = t[:,i] - - for i, vals in enumerate(y): # timestep, timehorizon values value - summary_writer.add_scalars(str(key), {f'{q}_t+{j+1}':v for j,v in enumerate(vals) if v == v}, i) - summary_writer.close() - - if args.save_predictions: - for q, t in _g.items(): - df = pd.DataFrame(t.tolist()) - df.columns = [f't+{i+1}' for i in range(len(df.columns))] - os.makedirs(os.path.join(args.results, 'predictions', str(key)), exist_ok=True) - df.to_csv(os.path.join(args.results, 'predictions', str(key), q+'.csv')) - - losses = QuantileLoss(config)(unscaled_predictions, unscaled_targets) - normalizer = unscaled_targets.abs().mean() - q_risk = 2 * losses / normalizer - - perf_dict = { - 'throughput': perf_meter.avg, - 'latency_avg': perf_meter.total_time/len(perf_meter.intervals), - 'latency_p90': perf_meter.p(90), - 'latency_p95': perf_meter.p(95), - 'latency_p99': perf_meter.p(99), - 'total_infernece_time': perf_meter.total_time, - } - - return q_risk, perf_dict - - -def main(args): - - setup_logger(args) - # Set up model - state_dict = torch.load(args.checkpoint) - config = state_dict['config'] - model = TemporalFusionTransformer(config).cuda() - model.load_state_dict(state_dict['model']) - model.eval() - model.cuda() - - # Set up dataset - test_split = TFTDataset(args.data, config) - data_loader = DataLoader(test_split, batch_size=args.batch_size, num_workers=4) - - scalers = pickle.load(open(args.tgt_scalers, 'rb')) - cat_encodings = pickle.load(open(args.cat_encodings, 'rb')) - - if args.visualize: - # TODO: abstract away all forms of visualization. - visualize_v2(args, config, model, data_loader, scalers, cat_encodings) - - quantiles, perf_dict = inference(args, config, model, data_loader, scalers, cat_encodings) - quantiles = {'test_p10': quantiles[0].item(), 'test_p50': quantiles[1].item(), 'test_p90': quantiles[2].item(), 'sum':sum(quantiles).item()} - finish_log = {**quantiles, **perf_dict} - dllogger.log(step=(), data=finish_log, verbosity=1) - print('Test q-risk: P10 {} | P50 {} | P90 {}'.format(*quantiles)) - print('Latency:\n\tAverage {:.3f}s\n\tp90 {:.3f}s\n\tp95 {:.3f}s\n\tp99 {:.3f}s'.format( - perf_dict['latency_avg'], perf_dict['latency_p90'], perf_dict['latency_p95'], perf_dict['latency_p99'])) - -if __name__=='__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--checkpoint', type=str, - help='Path to the checkpoint') - parser.add_argument('--data', type=str, - help='Path to the test split of the dataset') - parser.add_argument('--tgt_scalers', type=str, - help='Path to the tgt_scalers.bin file produced by the preprocessing') - parser.add_argument('--cat_encodings', type=str, - help='Path to the cat_encodings.bin file produced by the preprocessing') - parser.add_argument('--batch_size', type=int, default=64) - parser.add_argument('--visualize', action='http://github.com/store_true', help='Visualize predictions - each example on the separate plot') - parser.add_argument('--joint_visualization', action='http://github.com/store_true', help='Visualize predictions - each timeseries on separate plot. Projections will be concatenated.') - parser.add_argument('--save_predictions', action='http://github.com/store_true') - parser.add_argument('--results', type=str, default='/results') - parser.add_argument('--log_file', type=str, default='dllogger.json') - ARGS = parser.parse_args() - main(ARGS) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/log_helper.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/log_helper.py deleted file mode 100644 index 83d2ac7f7..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/log_helper.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import subprocess -import sys -import itertools -import atexit - -import dllogger -from dllogger import Backend, JSONStreamBackend, StdOutBackend - -import torch.distributed as dist -from torch.utils.tensorboard import SummaryWriter - -class TensorBoardBackend(Backend): - def __init__(self, verbosity, log_dir): - super().__init__(verbosity=verbosity) - self.summary_writer = SummaryWriter(log_dir=os.path.join(log_dir, 'TB_summary'), - flush_secs=120, - max_queue=200 - ) - self.hp_cache = None - atexit.register(self.summary_writer.close) - - @property - def log_level(self): - return self._log_level - - def metadata(self, timestamp, elapsedtime, metric, metadata): - pass - - def log(self, timestamp, elapsedtime, step, data): - if step == 'HPARAMS': - parameters = {k: v for k, v in data.items() if not isinstance(v, (list, tuple))} - #Unpack list and tuples - for d in [{k+f'_{i}':v for i,v in enumerate(l)} for k,l in data.items() if isinstance(l, (list, tuple))]: - parameters.update(d) - #Remove custom classes - parameters = {k: v for k, v in data.items() if isinstance(v, (int, float, str, bool))} - parameters.update({k:'None' for k, v in data.items() if v is None}) - self.hp_cache = parameters - if step == (): - if self.hp_cache is None: - print('Warning: Cannot save HParameters. Please log HParameters with step=\'HPARAMS\'', file=sys.stderr) - return - self.summary_writer.add_hparams(self.hp_cache, data) - if not isinstance(step, int): - return - for k, v in data.items(): - self.summary_writer.add_scalar(k, v, step) - - def flush(self): - pass - -def setup_logger(args): - os.makedirs(args.results, exist_ok=True) - log_path = os.path.join(args.results, args.log_file) - - if os.path.exists(log_path): - for i in itertools.count(): - s_fname = args.log_file.split('.') - fname = '.'.join(s_fname[:-1]) + f'_{i}.' + s_fname[-1] if len(s_fname) > 1 else args.stat_file + f'.{i}' - log_path = os.path.join(args.results, fname) - if not os.path.exists(log_path): - break - - def metric_format(metric, metadata, value): - return "{}: {}".format(metric, f'{value:.5f}' if isinstance(value, float) else value) - def step_format(step): - if step == (): - return "Finished |" - elif isinstance(step, int): - return "Step {0: <5} |".format(step) - return "Step {} |".format(step) - - - if not dist.is_initialized() or not args.distributed_world_size > 1 or args.distributed_rank == 0: - dllogger.init(backends=[JSONStreamBackend(verbosity=1, filename=log_path), - TensorBoardBackend(verbosity=1, log_dir=args.results), - StdOutBackend(verbosity=2, - step_format=step_format, - prefix_format=lambda x: "")#, - #metric_format=metric_format) - ]) - else: - dllogger.init(backends=[]) - dllogger.log(step='PARAMETER', data=vars(args), verbosity=0) - - container_setup_info = {**get_framework_env_vars(), **get_system_info()} - dllogger.log(step='ENVIRONMENT', data=container_setup_info, verbosity=0) - - dllogger.metadata('loss', {'GOAL': 'MINIMIZE', 'STAGE': 'TRAIN', 'format': ':5f'}) - dllogger.metadata('P10', {'GOAL': 'MINIMIZE', 'STAGE': 'TRAIN', 'format': ':5f'}) - dllogger.metadata('P50', {'GOAL': 'MINIMIZE', 'STAGE': 'TRAIN', 'format': ':5f'}) - dllogger.metadata('P90', {'GOAL': 'MINIMIZE', 'STAGE': 'TRAIN', 'format': ':5f'}) - dllogger.metadata('items/s', {'GOAL': 'MAXIMIZE', 'STAGE': 'TRAIN', 'format': ':1f'}) - dllogger.metadata('val_loss', {'GOAL': 'MINIMIZE', 'STAGE': 'VAL', 'format':':5f'}) - dllogger.metadata('val_P10', {'GOAL': 'MINIMIZE', 'STAGE': 'VAL', 'format': ':5f'}) - dllogger.metadata('val_P50', {'GOAL': 'MINIMIZE', 'STAGE': 'VAL', 'format': ':5f'}) - dllogger.metadata('val_P90', {'GOAL': 'MINIMIZE', 'STAGE': 'VAL', 'format': ':5f'}) - dllogger.metadata('val_items/s', {'GOAL': 'MAXIMIZE', 'STAGE': 'VAL', 'format': ':1f'}) - dllogger.metadata('test_P10', {'GOAL': 'MINIMIZE', 'STAGE': 'TEST', 'format': ':5f'}) - dllogger.metadata('test_P50', {'GOAL': 'MINIMIZE', 'STAGE': 'TEST', 'format': ':5f'}) - dllogger.metadata('test_P90', {'GOAL': 'MINIMIZE', 'STAGE': 'TEST', 'format': ':5f'}) - dllogger.metadata('throughput', {'GOAL': 'MAXIMIZE', 'STAGE': 'TEST', 'format': ':1f'}) - dllogger.metadata('latency_p90', {'GOAL': 'MIMIMIZE', 'STAGE': 'TEST', 'format': ':5f'}) - dllogger.metadata('latency_p95', {'GOAL': 'MIMIMIZE', 'STAGE': 'TEST', 'format': ':5f'}) - dllogger.metadata('latency_p99', {'GOAL': 'MIMIMIZE', 'STAGE': 'TEST', 'format': ':5f'}) - - -def get_framework_env_vars(): - return { - 'NVIDIA_PYTORCH_VERSION': os.environ.get('NVIDIA_PYTORCH_VERSION'), - 'PYTORCH_VERSION': os.environ.get('PYTORCH_VERSION'), - 'CUBLAS_VERSION': os.environ.get('CUBLAS_VERSION'), - 'NCCL_VERSION': os.environ.get('NCCL_VERSION'), - 'CUDA_DRIVER_VERSION': os.environ.get('CUDA_DRIVER_VERSION'), - 'CUDNN_VERSION': os.environ.get('CUDNN_VERSION'), - 'CUDA_VERSION': os.environ.get('CUDA_VERSION'), - 'NVIDIA_PIPELINE_ID': os.environ.get('NVIDIA_PIPELINE_ID'), - 'NVIDIA_BUILD_ID': os.environ.get('NVIDIA_BUILD_ID'), - 'NVIDIA_TF32_OVERRIDE': os.environ.get('NVIDIA_TF32_OVERRIDE'), - } - -def get_system_info(): - system_info = subprocess.run('nvidia-smi --query-gpu=gpu_name,memory.total,enforced.power.limit --format=csv'.split(), capture_output=True).stdout - system_info = [i.decode('utf-8') for i in system_info.split(b'\n')] - system_info = [x for x in system_info if x] - return {'system_info': system_info} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/modeling.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/modeling.py deleted file mode 100644 index 65e64983b..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/modeling.py +++ /dev/null @@ -1,367 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -import torch -import torch.nn as nn -import torch.nn.functional as F - -from torch import Tensor -from typing import Dict, Tuple, Optional, List - -if os.environ.get("TFT_SCRIPTING", False): - from torch.nn import LayerNorm -else: - from apex.normalization.fused_layer_norm import FusedLayerNorm as LayerNorm - -class MaybeLayerNorm(nn.Module): - def __init__(self, output_size, hidden_size, eps): - super().__init__() - if output_size and output_size == 1: - self.ln = nn.Identity() - else: - self.ln = LayerNorm(output_size if output_size else hidden_size, eps=eps) - - def forward(self, x): - return self.ln(x) - - -class GLU(nn.Module): - def __init__(self, hidden_size, output_size): - super().__init__() - self.lin = nn.Linear(hidden_size, output_size * 2) - - def forward(self, x: Tensor) -> Tensor: - x = self.lin(x) - x = F.glu(x) - return x - - -class GRN(nn.Module): - def __init__(self, - input_size, - hidden_size, - output_size=None, - context_hidden_size=None, - dropout=0): - super().__init__() - - - self.layer_norm = MaybeLayerNorm(output_size, hidden_size, eps=1e-3) - self.lin_a = nn.Linear(input_size, hidden_size) - if context_hidden_size is not None: - self.lin_c = nn.Linear(context_hidden_size, hidden_size, bias=False) - self.lin_i = nn.Linear(hidden_size, hidden_size) - self.glu = GLU(hidden_size, output_size if output_size else hidden_size) - self.dropout = nn.Dropout(dropout) - self.out_proj = nn.Linear(input_size, output_size) if output_size else None - - def forward(self, a: Tensor, c: Optional[Tensor] = None): - x = self.lin_a(a) - if c is not None: - x = x + self.lin_c(c).unsqueeze(1) - x = F.elu(x) - x = self.lin_i(x) - x = self.dropout(x) - x = self.glu(x) - y = a if not self.out_proj else self.out_proj(a) - x = x + y - x = self.layer_norm(x) - return x - -class TFTEmbedding(nn.Module): - def __init__(self, config): - super().__init__() - self.s_cat_inp_lens = config.static_categorical_inp_lens - self.t_cat_k_inp_lens = config.temporal_known_categorical_inp_lens - self.t_cat_o_inp_lens = config.temporal_observed_categorical_inp_lens - self.s_cont_inp_size = config.static_continuous_inp_size - self.t_cont_k_inp_size = config.temporal_known_continuous_inp_size - self.t_cont_o_inp_size = config.temporal_observed_continuous_inp_size - self.t_tgt_size = config.temporal_target_size - - self.hidden_size = config.hidden_size - - # There are 7 types of input: - # 1. Static categorical - # 2. Static continuous - # 3. Temporal known a priori categorical - # 4. Temporal known a priori continuous - # 5. Temporal observed categorical - # 6. Temporal observed continuous - # 7. Temporal observed targets (time series obseved so far) - - self.s_cat_embed = nn.ModuleList([ - nn.Embedding(n, self.hidden_size) for n in self.s_cat_inp_lens]) if self.s_cat_inp_lens else None - self.t_cat_k_embed = nn.ModuleList([ - nn.Embedding(n, self.hidden_size) for n in self.t_cat_k_inp_lens]) if self.t_cat_k_inp_lens else None - self.t_cat_o_embed = nn.ModuleList([ - nn.Embedding(n, self.hidden_size) for n in self.t_cat_o_inp_lens]) if self.t_cat_o_inp_lens else None - - self.s_cont_embedding_vectors = nn.Parameter(torch.Tensor(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None - self.t_cont_k_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None - self.t_cont_o_embedding_vectors = nn.Parameter(torch.Tensor(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None - self.t_tgt_embedding_vectors = nn.Parameter(torch.Tensor(self.t_tgt_size, self.hidden_size)) - - self.s_cont_embedding_bias = nn.Parameter(torch.zeros(self.s_cont_inp_size, self.hidden_size)) if self.s_cont_inp_size else None - self.t_cont_k_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_k_inp_size, self.hidden_size)) if self.t_cont_k_inp_size else None - self.t_cont_o_embedding_bias = nn.Parameter(torch.zeros(self.t_cont_o_inp_size, self.hidden_size)) if self.t_cont_o_inp_size else None - self.t_tgt_embedding_bias = nn.Parameter(torch.zeros(self.t_tgt_size, self.hidden_size)) - - if self.s_cont_embedding_vectors is not None: - torch.nn.init.xavier_normal_(self.s_cont_embedding_vectors) - if self.t_cont_k_embedding_vectors is not None: - torch.nn.init.xavier_normal_(self.t_cont_k_embedding_vectors) - if self.t_cont_o_embedding_vectors is not None: - torch.nn.init.xavier_normal_(self.t_cont_o_embedding_vectors) - torch.nn.init.xavier_normal_(self.t_tgt_embedding_vectors) - - def _apply_embedding(self, - cat: Optional[Tensor], - cont: Optional[Tensor], - cat_emb: Optional[nn.ModuleList], - cont_emb: Tensor, - cont_bias: Tensor, - ) -> Tuple[Optional[Tensor], Optional[Tensor]]: - e_cat = torch.stack([embed(cat[...,i]) for i, embed in enumerate(cat_emb)], dim=-2) if cat is not None else None - if cont is not None: - #the line below is equivalent to following einsums - #e_cont = torch.einsum('btf,fh->bthf', cont, cont_emb) - #e_cont = torch.einsum('bf,fh->bhf', cont, cont_emb) - e_cont = torch.mul(cont.unsqueeze(-1), cont_emb) - e_cont = e_cont + cont_bias - else: - e_cont = None - - if e_cat is not None and e_cont is not None: - return torch.cat([e_cat, e_cont], dim=-2) - elif e_cat is not None: - return e_cat - elif e_cont is not None: - return e_cont - else: - return None - - def forward(self, x: Dict[str, Tensor]): - # temporal/static categorical/continuous known/observed input - s_cat_inp = x.get('s_cat', None) - s_cont_inp = x.get('s_cont', None) - t_cat_k_inp = x.get('k_cat', None) - t_cont_k_inp = x.get('k_cont', None) - t_cat_o_inp = x.get('o_cat', None) - t_cont_o_inp = x.get('o_cont', None) - t_tgt_obs = x['target'] # Has to be present - - # Static inputs are expected to be equal for all timesteps - # For memory efficiency there is no assert statement - s_cat_inp = s_cat_inp[:,0,:] if s_cat_inp is not None else None - s_cont_inp = s_cont_inp[:,0,:] if s_cont_inp is not None else None - - s_inp = self._apply_embedding(s_cat_inp, - s_cont_inp, - self.s_cat_embed, - self.s_cont_embedding_vectors, - self.s_cont_embedding_bias) - t_known_inp = self._apply_embedding(t_cat_k_inp, - t_cont_k_inp, - self.t_cat_k_embed, - self.t_cont_k_embedding_vectors, - self.t_cont_k_embedding_bias) - t_observed_inp = self._apply_embedding(t_cat_o_inp, - t_cont_o_inp, - self.t_cat_o_embed, - self.t_cont_o_embedding_vectors, - self.t_cont_o_embedding_bias) - - # Temporal observed targets - # t_observed_tgt = torch.einsum('btf,fh->btfh', t_tgt_obs, self.t_tgt_embedding_vectors) - t_observed_tgt = torch.matmul(t_tgt_obs.unsqueeze(3).unsqueeze(4), self.t_tgt_embedding_vectors.unsqueeze(1)).squeeze(3) - t_observed_tgt = t_observed_tgt + self.t_tgt_embedding_bias - - return s_inp, t_known_inp, t_observed_inp, t_observed_tgt - -class VariableSelectionNetwork(nn.Module): - def __init__(self, config, num_inputs): - super().__init__() - self.joint_grn = GRN(config.hidden_size*num_inputs, config.hidden_size, output_size=num_inputs, context_hidden_size=config.hidden_size) - self.var_grns = nn.ModuleList([GRN(config.hidden_size, config.hidden_size, dropout=config.dropout) for _ in range(num_inputs)]) - - def forward(self, x: Tensor, context: Optional[Tensor] = None): - Xi = x.reshape(*x.shape[:-2], -1) - grn_outputs = self.joint_grn(Xi, c=context) - sparse_weights = F.softmax(grn_outputs, dim=-1) - transformed_embed_list = [m(x[...,i,:]) for i, m in enumerate(self.var_grns)] - transformed_embed = torch.stack(transformed_embed_list, dim=-1) - #the line below performs batched matrix vector multiplication - #for temporal features it's bthf,btf->bth - #for static features it's bhf,bf->bh - variable_ctx = torch.matmul(transformed_embed, sparse_weights.unsqueeze(-1)).squeeze(-1) - - return variable_ctx, sparse_weights - -class StaticCovariateEncoder(nn.Module): - def __init__(self, config): - super().__init__() - self.vsn = VariableSelectionNetwork(config, config.num_static_vars) - self.context_grns = nn.ModuleList([GRN(config.hidden_size, config.hidden_size, dropout=config.dropout) for _ in range(4)]) - - def forward(self, x: Tensor) -> Tuple[Tensor, Tensor, Tensor, Tensor]: - variable_ctx, sparse_weights = self.vsn(x) - - # Context vectors: - # variable selection context - # enrichment context - # state_c context - # state_h context - cs, ce, ch, cc = tuple(m(variable_ctx) for m in self.context_grns) - - return cs, ce, ch, cc - - -class InterpretableMultiHeadAttention(nn.Module): - def __init__(self, config): - super().__init__() - self.n_head = config.n_head - assert config.hidden_size % config.n_head == 0 - self.d_head = config.hidden_size // config.n_head - self.qkv_linears = nn.Linear(config.hidden_size, (2 * self.n_head + 1) * self.d_head, bias=False) - self.out_proj = nn.Linear(self.d_head, config.hidden_size, bias=False) - self.attn_dropout = nn.Dropout(config.attn_dropout) - self.out_dropout = nn.Dropout(config.dropout) - self.scale = self.d_head**-0.5 - self.register_buffer("_mask", torch.triu(torch.full((config.example_length, config.example_length), float('-inf')), 1).unsqueeze(0)) - - def forward(self, x: Tensor, mask_future_timesteps: bool = True) -> Tuple[Tensor, Tensor]: - bs, t, h_size = x.shape - qkv = self.qkv_linears(x) - q, k, v = qkv.split((self.n_head * self.d_head, self.n_head * self.d_head, self.d_head), dim=-1) - q = q.view(bs, t, self.n_head, self.d_head) - k = k.view(bs, t, self.n_head, self.d_head) - v = v.view(bs, t, self.d_head) - - # attn_score = torch.einsum('bind,bjnd->bnij', q, k) - attn_score = torch.matmul(q.permute((0, 2, 1, 3)), k.permute((0, 2, 3, 1))) - attn_score.mul_(self.scale) - - if mask_future_timesteps: - attn_score = attn_score + self._mask - - attn_prob = F.softmax(attn_score, dim=3) - attn_prob = self.attn_dropout(attn_prob) - - # attn_vec = torch.einsum('bnij,bjd->bnid', attn_prob, v) - attn_vec = torch.matmul(attn_prob, v.unsqueeze(1)) - m_attn_vec = torch.mean(attn_vec, dim=1) - out = self.out_proj(m_attn_vec) - out = self.out_dropout(out) - - return out, attn_vec - - - -class TemporalFusionTransformer(nn.Module): - """ - Implementation of https://arxiv.org/abs/1912.09363 - """ - def __init__(self, config): - super().__init__() - - if hasattr(config, 'model'): - config = config.model - - self.encoder_length = config.encoder_length #this determines from how distant past we want to use data from - - self.embedding = TFTEmbedding(config) - self.static_encoder = StaticCovariateEncoder(config) - - self.history_vsn = VariableSelectionNetwork(config, config.num_historic_vars) - self.history_encoder = nn.LSTM(config.hidden_size, config.hidden_size, batch_first=True) - self.future_vsn = VariableSelectionNetwork(config, config.num_future_vars) - self.future_encoder = nn.LSTM(config.hidden_size, config.hidden_size, batch_first=True) - - - self.input_gate = GLU(config.hidden_size, config.hidden_size) - self.input_gate_ln = LayerNorm(config.hidden_size, eps=1e-3) - - self.enrichment_grn = GRN(config.hidden_size, - config.hidden_size, - context_hidden_size=config.hidden_size, - dropout=config.dropout) - self.attention = InterpretableMultiHeadAttention(config) - self.attention_gate = GLU(config.hidden_size, config.hidden_size) - self.attention_ln = LayerNorm(config.hidden_size, eps=1e-3) - - self.positionwise_grn = GRN(config.hidden_size, - config.hidden_size, - dropout=config.dropout) - - self.decoder_gate = GLU(config.hidden_size, config.hidden_size) - self.decoder_ln = LayerNorm(config.hidden_size, eps=1e-3) - - self.quantile_proj = nn.Linear(config.hidden_size, len(config.quantiles)) - - def forward(self, x: Dict[str, Tensor]) -> Tensor: - s_inp, t_known_inp, t_observed_inp, t_observed_tgt = self.embedding(x) - - # Static context - cs, ce, ch, cc = self.static_encoder(s_inp) - ch, cc = ch.unsqueeze(0), cc.unsqueeze(0) #lstm initial states - - # Temporal input - _historical_inputs = [t_known_inp[:,:self.encoder_length,:], t_observed_tgt[:,:self.encoder_length,:]] - if t_observed_inp is not None: - _historical_inputs.insert(0,t_observed_inp[:,:self.encoder_length,:]) - - historical_inputs = torch.cat(_historical_inputs, dim=-2) - future_inputs = t_known_inp[:, self.encoder_length:] - - # Encoders - historical_features, _ = self.history_vsn(historical_inputs, cs) - history, state = self.history_encoder(historical_features, (ch, cc)) - future_features, _ = self.future_vsn(future_inputs, cs) - future, _ = self.future_encoder(future_features, state) - torch.cuda.synchronize() # this call gives perf boost for unknown reasons - - # skip connection - input_embedding = torch.cat([historical_features, future_features], dim=1) - temporal_features = torch.cat([history, future], dim=1) - temporal_features = self.input_gate(temporal_features) - temporal_features = temporal_features + input_embedding - temporal_features = self.input_gate_ln(temporal_features) - - # Static enrichment - enriched = self.enrichment_grn(temporal_features, c=ce) - - # Temporal self attention - x, _ = self.attention(enriched, mask_future_timesteps=True) - - # Don't compute hictorical quantiles - x = x[:, self.encoder_length:, :] - temporal_features = temporal_features[:, self.encoder_length:, :] - enriched = enriched[:, self.encoder_length:, :] - - x = self.attention_gate(x) - x = x + enriched - x = self.attention_ln(x) - - # Position-wise feed-forward - x = self.positionwise_grn(x) - - # Final skip connection - x = self.decoder_gate(x) - x = x + temporal_features - x = self.decoder_ln(x) - - out = self.quantile_proj(x) - - return out diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/requirements.txt b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/requirements.txt deleted file mode 100644 index d23942e2f..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -tensorboard -pandas==1.1.4 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_electricity_HP_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_electricity_HP_search.yaml deleted file mode 100644 index d448511da..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_electricity_HP_search.yaml +++ /dev/null @@ -1,27 +0,0 @@ -NGC: &NGC - hostname: ngc - instance: dgx1v.32g.8.norm.beta - - job_name: "ml-model.tft electricity HP search" - - docker_image: nvcr.io/nvidian/swdl/jbaczek:tft_pyt - datasets: - /data: 78291 - workspaces: - /ws: VUMFFB3uSv25FDlkXg80Vw - download_dir: /home/jbaczek/Downloads - -jobs: - - steps: - - EPOCHS=30 DATASET=electricity NGPU=8 DROPOUT=0.1 LR=5e-4 H_SIZE=128 N_HEADS=4 bash scripts/run_hp_search.sh - backend: *NGC - - - steps: - - EPOCHS=30 DATASET=electricity NGPU=8 DROPOUT=0.1 LR=5e-4 H_SIZE=128 N_HEADS=2 bash scripts/run_hp_search.sh - backend: *NGC - -reports: - filename: electricity_hp_search - types: - - xls - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_favorita_HP_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_favorita_HP_search.yaml deleted file mode 100644 index 4af7eb43c..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_favorita_HP_search.yaml +++ /dev/null @@ -1,27 +0,0 @@ -NGC: &NGC - hostname: ngc - instance: dgx1v.32g.8.norm - - job_name: "ml-model.tft favorita HP search" - - docker_image: nvcr.io/nvidian/swdl/jbaczek:tft_pyt - datasets: - /data: 78291 - workspaces: - /ws: VUMFFB3uSv25FDlkXg80Vw - download_dir: /home/jbaczek/Downloads - -jobs: - - steps: - - EPOCHS=10 DATASET=favorita NGPU=8 DROPOUT=0.1 LR=5e-4 H_SIZE=240 N_HEADS=4 bash scripts/run_hp_search.sh - backend: *NGC - - - steps: - - EPOCHS=10 DATASET=favorita NGPU=8 DROPOUT=0.1 LR=1e-3 H_SIZE=240 N_HEADS=4 bash scripts/run_hp_search.sh - backend: *NGC - -reports: - filename: favorita_hp_search - types: - - xls - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_traffic_HP_search.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_traffic_HP_search.yaml deleted file mode 100644 index e8bea00fb..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/autobench/ngc_traffic_HP_search.yaml +++ /dev/null @@ -1,31 +0,0 @@ -NGC: &NGC - hostname: ngc - instance: dgx1v.32g.8.norm - - job_name: "ml-model.tft traffic HP search" - - docker_image: nvcr.io/nvidian/swdl/jbaczek:tft_pyt - datasets: - /data: 78291 - workspaces: - /ws: VUMFFB3uSv25FDlkXg80Vw - download_dir: /home/jbaczek/Downloads - -jobs: - - steps: - - DATASET=traffic NGPU=8 DROPOUT=0.3 LR=5e-4 H_SIZE=128 N_HEADS=4 bash scripts/run_hp_search.sh - backend: *NGC - - - steps: - - DATASET=traffic NGPU=8 DROPOUT=0.3 LR=5e-3 H_SIZE=128 N_HEADS=4 bash scripts/run_hp_search.sh - backend: *NGC - - - steps: - - DATASET=traffic NGPU=8 DROPOUT=0.3 LR=1e-3 H_SIZE=128 N_HEADS=4 bash scripts/run_hp_search.sh - backend: *NGC - -reports: - filename: traffoc - types: - - xls - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/benchmark.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/benchmark.sh deleted file mode 100644 index 634d562bf..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/benchmark.sh +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/bash -NUM_GPUS=$(nvidia-smi --query-gpu=name --format=csv,noheader | wc -l) -[ $NUM_GPUS -eq 16 ] && WORKER_NUMS=(1 8 16) || WORKER_NUMS=(1 8) -DATASETS=(electricity volatility traffic favorita) - -rm -r /tmp/benchmark_results - -for DATASET in ${DATASETS[@]} -do - for NGPU in ${WORKER_NUMS[@]} - do - for BATCH_SIZE in 512 1024 1536 2048 2560 - do - for USE_AMP in --use_amp "" - do - for AFFINITY in "--affinity disabled" "--affinity single" "--affinity socket_unique_interleaved" - do - EXP_NAME="TFT_benchmark_${DATASET}_BS_${BATCH_SIZE}_${NGPU}GPU${USE_AMP}_${AFFINITY}" - python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset ${DATASET} \ - --data_path /data/processed/${DATASET}_bin \ - --batch_size=${BATCH_SIZE} \ - --lr 5e-4 \ - --epochs 1 \ - --sample 100000 5000 \ - --seed 1 \ - ${USE_AMP} \ - ${AFFINITY} \ - --clip_grad 0.1 \ - --results /tmp/benchmark_results/${EXP_NAME} - done - done - done - done -done -for P in `ls /tmp/benchmark_results/`; -do - echo ${P} - tail -n 1 /tmp/benchmark_results/${P}/dllogger.json -done diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/get_data.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/get_data.sh deleted file mode 100644 index 4c276dd5b..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/get_data.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -DATAPATH='/data' - -declare -A URLS=( ['electricity']='https://archive.ics.uci.edu/ml/machine-learning-databases/00321/LD2011_2014.txt.zip' - ['volatility']='https://realized.oxford-man.ox.ac.uk/images/oxfordmanrealizedvolatilityindices.zip' - ['traffic']='https://archive.ics.uci.edu/ml/machine-learning-databases/00204/PEMS-SF.zip' - ) - -mkdir -p ${DATAPATH}/raw -mkdir -p ${DATAPATH}/processed - -for DS in electricity volatility traffic -do - DS_PATH=${DATAPATH}/raw/${DS} - ZIP_FNAME=${DS_PATH}.zip - if [ ! -d ${DS_PATH} ] - then - wget "${URLS[${DS}]}" -O ${ZIP_FNAME} - unzip ${ZIP_FNAME} -d ${DS_PATH} - fi - python -c "from data_utils import standarize_${DS} as standarize; standarize(\"${DS_PATH}\")" - python -c "from data_utils import preprocess; \ - from configuration import ${DS^}Config as Config; \ - preprocess(\"${DS_PATH}/standarized.csv\", \"${DATAPATH}/processed/${DS}_bin\", Config())" -done - - -FAVORITA_ZIP="favorita-grocery-sales-forecasting.zip" -DS_PATH=${DATAPATH}/raw/favorita -if [ ! -f ${DS_PATH}/${FAVORITA_ZIP} ] -then - echo ${DS_PATH} not found. Please download the favorita dataset from https://www.kaggle.com/c/favorita-grocery-sales-forecasting/data - exit 1 -fi - -unzip ${DS_PATH}/${FAVORITA_ZIP} -d ${DS_PATH} -for F in `ls ${DATAPATH}/raw/favorita` -do - 7z e ${DS_PATH}/${F} -o${DS_PATH} -done -python -c "from data_utils import standarize_favorita as standarize; standarize(\"${DS_PATH}\")" -python -c "from data_utils import preprocess; \ - from configuration import FavoritaConfig as Config; \ - preprocess(\"${DS_PATH}/standarized.csv\", \"${DATAPATH}/processed/favorita_bin\", Config())" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_electricity.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_electricity.sh deleted file mode 100644 index e9e80f4f2..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_electricity.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${NGPU:=8} -: ${BATCH_SIZE:=1024} -: ${EPOCHS:=30} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset electricity \ - --data_path /data/processed/electricity_bin \ - --batch_size=${BATCH_SIZE} \ - --sample 450000 50000 \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_electricity_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed_${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_electricity_DGX1-16G.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_electricity_DGX1-16G.sh deleted file mode 100644 index e9e80f4f2..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_electricity_DGX1-16G.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${NGPU:=8} -: ${BATCH_SIZE:=1024} -: ${EPOCHS:=30} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset electricity \ - --data_path /data/processed/electricity_bin \ - --batch_size=${BATCH_SIZE} \ - --sample 450000 50000 \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_electricity_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed_${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_favorita.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_favorita.sh deleted file mode 100644 index b89b26866..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_favorita.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${NGPU:=8} -: ${BATCH_SIZE:=1024} -: ${EPOCHS:=10} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset favorita \ - --data_path /data/processed/favorita_bin \ - --batch_size=${BATCH_SIZE} \ - --sample 450000 50000 \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_favorita_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_favorita_DGX1-16G.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_favorita_DGX1-16G.sh deleted file mode 100644 index 2a23eb8cc..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_favorita_DGX1-16G.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${NGPU:=8} -: ${BATCH_SIZE:=512} -: ${EPOCHS:=10} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset favorita \ - --data_path /data/processed/favorita_bin \ - --batch_size=${BATCH_SIZE} \ - --sample 450000 50000 \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_favorita_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_hp_search.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_hp_search.sh deleted file mode 100644 index 89d08c4cd..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_hp_search.sh +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${BATCH_SIZE:=1024} -: ${H_SIZE:=128} -: ${N_HEADS:=1} -: ${NGPU:=8} -: ${EPOCHS:=20} -: ${DATASET:="electricity"} -: ${DROPOUT:=0.1} -: ${PREC:="amp"} - -SAMPLES="" -GNORMS=(0.01 0.1 1.0) -[ ${DATASET} = "volatility" ] || SAMPLES="--sample 450000 50000" -[ ${DATASET} = "traffic" ] && GNORMS=(0.1 1.0 10.0 100.0) -[ ${DATASET} = "favorita" ] && GNORMS=(0.1 1.0 10.0 100.0) - -[ ${PREC} = "amp" ] && AMP="--use_amp" -[ ${PREC} = "fp32" ] || [ ${PREC} = "tf32" ] && AMP="" - -for MAX_GNORM in "${GNORMS[@]}" -do - for EMA_DECAY in 0.25 0.5 0.75 0.9 0.95 - do - for SEED in {1..30} - do - EXP_NAME=TFT_${DATASET}_bs${NGPU}x${BATCH_SIZE}_HSIZE${H_SIZE}_NHEADS${N_HEADS}_LR${LR}_CLIP_GRAD${MAX_GNORM}_DROPOUT_${DROPOUT}_EMA${EMA_DECAY}_${PREC} - - for RETRY in {1..3} - do - python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset ${DATASET} \ - --data_path /ws/datasets/${DATASET}_bin \ - --batch_size=${BATCH_SIZE} \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - ${SAMPLES} \ - --seed ${SEED} \ - ${AMP} \ - --clip_grad ${MAX_GNORM} \ - --ema_decay ${EMA_DECAY} \ - --overwrite_config "{\"dropout\":$DROPOUT, \"hidden_size\":$H_SIZE, \"n_head\":$N_HEADS}" \ - --results /results/${EXP_NAME}/seed_${SEED} - - if [ -f /results/${EXP_NAME}/seed_${SEED}/dllogger.json ] - then - LAST_LINE=$( tail -n 1 /results/${EXP_NAME}/seed_${SEED}/dllogger.json | grep "\"step\": \[\]" ) - [[ $LAST_LINE = "" ]] || break - fi - echo RETRYING ... - rm -r /results/${EXP_NAME}/seed_${SEED} - - done - done - done -done diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_traffic.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_traffic.sh deleted file mode 100644 index e2013efb3..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_traffic.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${NGPU:=8} -: ${BATCH_SIZE:=1024} -: ${EPOCHS:=20} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset traffic \ - --data_path /data/processed/traffic_bin \ - --batch_size=${BATCH_SIZE} \ - --sample 450000 50000 \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_traffic_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed_${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_traffic_DGX1-16G.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_traffic_DGX1-16G.sh deleted file mode 100644 index e2013efb3..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_traffic_DGX1-16G.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${NGPU:=8} -: ${BATCH_SIZE:=1024} -: ${EPOCHS:=20} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset traffic \ - --data_path /data/processed/traffic_bin \ - --batch_size=${BATCH_SIZE} \ - --sample 450000 50000 \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_traffic_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed_${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_volatility.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_volatility.sh deleted file mode 100644 index 0f8132dd5..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_volatility.sh +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${BATCH_SIZE:=1024} -: ${NGPU:=8} -: ${EPOCHS:=10} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset volatility \ - --data_path /data/processed/volatility_bin \ - --batch_size=${BATCH_SIZE} \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_volatility_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed_${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_volatility_DGX1-16G.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_volatility_DGX1-16G.sh deleted file mode 100644 index baf23289e..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/scripts/run_volatility_DGX1-16G.sh +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -: ${SEED:=1} -: ${LR:=1e-3} -: ${BATCH_SIZE:=768} -: ${NGPU:=8} -: ${EPOCHS:=20} - -python -m torch.distributed.run --nproc_per_node=${NGPU} train.py \ - --dataset volatility \ - --data_path /data/processed/volatility_bin \ - --batch_size=${BATCH_SIZE} \ - --lr ${LR} \ - --epochs ${EPOCHS} \ - --seed ${SEED} \ - --use_amp \ - --results /results/TFT_volatility_bs${NGPU}x${BATCH_SIZE}_lr${LR}/seed_${SEED} diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/train.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/train.py deleted file mode 100644 index f3e3a2919..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/train.py +++ /dev/null @@ -1,286 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import time -import os -import pickle -import json - -import torch -import torch.nn as nn -import torch.nn.functional as F -import torch.distributed as dist -from torch.utils.data import DataLoader, DistributedSampler, RandomSampler -from apex import amp -from apex.optimizers import FusedAdam -#from torch.nn.parallel import DistributedDataParallel as DDP -from apex.parallel import DistributedDataParallel as DDP - -import numpy as np - -import dllogger - -from modeling import TemporalFusionTransformer -from configuration import CONFIGS -from data_utils import TFTBinaryDataset, sample_data -from log_helper import setup_logger -from criterions import QuantileLoss -from inference import predict -from utils import PerformanceMeter -import gpu_affinity -from ema import ModelEma - -def load_dataset(args, config): - train_split = TFTBinaryDataset(os.path.join(args.data_path, 'train.bin'), config) - train_split = sample_data(train_split, args.sample_data[0]) - if args.distributed_world_size > 1: - data_sampler = DistributedSampler(train_split, args.distributed_world_size, args.distributed_rank, seed=args.seed + args.distributed_rank, drop_last=True) - else: - data_sampler = RandomSampler(train_split) - train_loader = DataLoader(train_split, batch_size=args.batch_size, num_workers=4, sampler=data_sampler, pin_memory=True) - - valid_split = TFTBinaryDataset(os.path.join(args.data_path, 'valid.bin'), config) - valid_split = sample_data(valid_split, args.sample_data[1]) - if args.distributed_world_size > 1: - data_sampler = DistributedSampler(valid_split, args.distributed_world_size, args.distributed_rank, shuffle=False, drop_last=False) - else: - data_sampler = None - valid_loader = DataLoader(valid_split, batch_size=args.batch_size, sampler=data_sampler, num_workers=4, pin_memory=True) - - test_split = TFTBinaryDataset(os.path.join(args.data_path, 'test.bin'), config) - if args.distributed_world_size > 1: - data_sampler = DistributedSampler(test_split, args.distributed_world_size, args.distributed_rank, shuffle=False, drop_last=False) - else: - data_sampler = None - test_loader = DataLoader(test_split, batch_size=args.batch_size, sampler=data_sampler, num_workers=4, pin_memory=True) - - print_once(f'Train split length: {len(train_split)}') - print_once(f'Valid split length: {len(valid_split)}') - print_once(f'Test split length: {len(test_split)}') - - return train_loader, valid_loader, test_loader - -def print_once(*args, **kwargs): - if not dist.is_initialized() or dist.get_rank() == 0: - print(*args, **kwargs) - - -def main(args): - ### INIT DISTRIBUTED - args.distributed_world_size = int(os.environ.get('WORLD_SIZE', 1)) - args.local_rank = int(os.environ.get('LOCAL_RANK', 0)) - if args.distributed_world_size > 1: - dist.init_process_group(backend='nccl', init_method='env://') - print_once(f'Distributed training with {args.distributed_world_size} GPUs') - args.distributed_rank = dist.get_rank() - torch.cuda.set_device(args.local_rank) - torch.cuda.synchronize() - - # Enable CuDNN autotuner - nproc_per_node = torch.cuda.device_count() - if args.affinity != 'disabled': - affinity = gpu_affinity.set_affinity( - args.local_rank, - nproc_per_node, - args.affinity - ) - print(f'{args.local_rank}: thread affinity: {affinity}') - - torch.backends.cudnn.benchmark = True - - if args.seed: - np.random.seed(args.seed) - torch.manual_seed(args.seed) - torch.cuda.manual_seed(args.seed) - - setup_logger(args) - - config = CONFIGS[args.dataset]() - if args.overwrite_config: - config.__dict__.update(json.loads(args.overwrite_config)) - - dllogger.log(step='HPARAMS', data={**vars(args), **vars(config)}, verbosity=1) - - model = TemporalFusionTransformer(config).cuda() - if args.ema_decay: - model_ema = ModelEma(model, decay=args.ema_decay) - - print_once('Model params: {}'.format(sum(p.numel() for p in model.parameters()))) - criterion = QuantileLoss(config).cuda() - optimizer = FusedAdam(model.parameters(), lr=args.lr) - if args.use_amp: - model, optimizer = amp.initialize(model, optimizer, opt_level="O2", loss_scale="dynamic") - if args.distributed_world_size > 1: - #model = DDP(model, device_ids=[args.local_rank], output_device=args.local_rank, find_unused_parameters=True) - model = DDP(model) - - train_loader, valid_loader, test_loader = load_dataset(args, config) - - global_step = 0 - perf_meter = PerformanceMeter() - - for epoch in range(args.epochs): - start = time.time() - dllogger.log(step=global_step, data={'epoch': epoch}, verbosity=1) - - model.train() - for local_step, batch in enumerate(train_loader): - perf_meter.reset_current_lap() - batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in batch.items()} - predictions = model(batch) - targets = batch['target'][:,config.encoder_length:,:] - p_losses = criterion(predictions, targets) - loss = p_losses.sum() - - if args.use_amp: - with amp.scale_loss(loss, optimizer) as scaled_loss: - scaled_loss.backward() - else: - loss.backward() - if not args.grad_accumulation or (global_step+1) % args.grad_accumulation == 0: - if args.clip_grad: - torch.nn.utils.clip_grad_norm_(model.parameters(), args.clip_grad) - optimizer.step() - optimizer.zero_grad() - if args.ema_decay: - model_ema.update(model) - - if args.distributed_world_size > 1: - dist.all_reduce(p_losses) - p_losses /= args.distributed_world_size - loss = p_losses.sum() - - torch.cuda.synchronize() - ips = perf_meter.update(args.batch_size * args.distributed_world_size, - exclude_from_total=local_step in [0, len(train_loader)-1]) - - log_dict = {'P10':p_losses[0].item(), 'P50':p_losses[1].item(), 'P90':p_losses[2].item(), 'loss': loss.item(), 'items/s':ips} - dllogger.log(step=global_step, data=log_dict, verbosity=1) - global_step += 1 - - validate(args, config, model_ema if args.ema_decay else model, criterion, valid_loader, global_step) - - if validate.early_stop_c >= args.early_stopping: - print_once('Early stopping') - break - - ### TEST PHASE ### - state_dict = torch.load(os.path.join(args.results, 'checkpoint.pt'), map_location='cpu') - if isinstance(model, DDP): - model.module.load_state_dict(state_dict['model']) - else: - model.load_state_dict(state_dict['model']) - model.cuda().eval() - - tgt_scalers = pickle.load(open(os.path.join(args.data_path, 'tgt_scalers.bin'), 'rb')) - cat_encodings = pickle.load(open(os.path.join(args.data_path,'cat_encodings.bin'), 'rb')) - - unscaled_predictions, unscaled_targets, _, _ = predict(args, config, model, test_loader, tgt_scalers, cat_encodings) - losses = QuantileLoss(config)(unscaled_predictions, unscaled_targets) - normalizer = unscaled_targets.abs().mean() - quantiles = 2 * losses / normalizer - - if args.distributed_world_size > 1: - quantiles = quantiles.cuda() - dist.all_reduce(quantiles) - quantiles /= args.distributed_world_size - - quantiles = {'test_p10': quantiles[0].item(), 'test_p50': quantiles[1].item(), 'test_p90': quantiles[2].item(), 'sum':sum(quantiles).item()} - finish_log = {**quantiles, 'average_ips':perf_meter.avg, 'convergence_step':validate.conv_step} - dllogger.log(step=(), data=finish_log, verbosity=1) - -def validate(args, config, model, criterion, dataloader, global_step): - if not hasattr(validate, 'best_valid_loss'): - validate.best_valid_loss = float('inf') - if not hasattr(validate, 'early_stop_c'): - validate.early_stop_c = 0 - model.eval() - - losses = [] - validation_start = time.time() - for batch in dataloader: - with torch.no_grad(): - batch = {key: tensor.cuda() if tensor.numel() else None for key, tensor in batch.items()} - predictions = model(batch) - targets = batch['target'][:,config.encoder_length:,:] - p_losses = criterion(predictions, targets) - bs = next(t for t in batch.values() if t is not None).shape[0] - losses.append((p_losses, bs)) - - validation_end = time.time() - - p_losses = sum([l[0]*l[1] for l in losses])/sum([l[1] for l in losses]) #takes into accunt that the last batch is not full - if args.distributed_world_size > 1: - dist.all_reduce(p_losses) - p_losses = p_losses/args.distributed_world_size - - ips = len(dataloader.dataset) / (validation_end - validation_start) - - log_dict = {'P10':p_losses[0].item(), 'P50':p_losses[1].item(), 'P90':p_losses[2].item(), 'loss': p_losses.sum().item(), 'items/s':ips} - - if log_dict['loss'] < validate.best_valid_loss: - validate.best_valid_loss = log_dict['loss'] - validate.early_stop_c = 0 - validate.conv_step = global_step - if not dist.is_initialized() or dist.get_rank() == 0: - state_dict = model.module.state_dict() if isinstance(model, (DDP, ModelEma)) else model.state_dict() - ckpt = {'args':args, 'config':config, 'model':state_dict} - torch.save(ckpt, os.path.join(args.results, 'checkpoint.pt')) - if args.distributed_world_size > 1: - dist.barrier() - else: - validate.early_stop_c += 1 - - log_dict = {'val_'+k:v for k,v in log_dict.items()} - dllogger.log(step=global_step, data=log_dict, verbosity=1) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--data_path', type=str, required=True, - help='Path to the dataset') - parser.add_argument('--dataset', type=str, required=True, choices=CONFIGS.keys(), - help='Dataset name') - parser.add_argument('--epochs', type=int, default=25, - help='Default number of training epochs') - parser.add_argument('--sample_data', type=lambda x: int(float(x)), nargs=2, default=[-1, -1], - help="""Subsample the dataset. Specify number of training and valid examples. - Values can be provided in scientific notation. Floats will be truncated.""") - parser.add_argument('--batch_size', type=int, default=64) - parser.add_argument('--lr', type=float, default=1e-3) - parser.add_argument('--seed', type=int, default=1) - parser.add_argument('--use_amp', action='http://github.com/store_true', help='Enable automatic mixed precision') - parser.add_argument('--clip_grad', type=float, default=0.0) - parser.add_argument('--grad_accumulation', type=int, default=0) - parser.add_argument('--early_stopping', type=int, default=1000, - help='Stop training if validation loss does not improve for more than this number of epochs.') - parser.add_argument('--results', type=str, default='/results', - help='Directory in which results are stored') - parser.add_argument('--log_file', type=str, default='dllogger.json', - help='Name of dllogger output file') - parser.add_argument('--overwrite_config', type=str, default='', - help='JSON string used to overload config') - parser.add_argument('--affinity', type=str, - default='socket_unique_interleaved', - choices=['socket', 'single', 'single_unique', - 'socket_unique_interleaved', - 'socket_unique_continuous', - 'disabled'], - help='type of CPU affinity') - parser.add_argument("--ema_decay", type=float, default=0.0, help='Use exponential moving average') - - - ARGS = parser.parse_args() - main(ARGS) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/README.md b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/README.md deleted file mode 100644 index 36ed084ec..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/README.md +++ /dev/null @@ -1,2492 +0,0 @@ -# Deploying the TFT model on Triton Inference Server - -This folder contains instructions for deployment to run inference -on Triton Inference Server as well as a detailed performance analysis. -The purpose of this document is to help you with achieving -the best inference performance. - -## Table of contents - - [Solution overview](#solution-overview) - - [Introduction](#introduction) - - [Deployment process](#deployment-process) - - [Setup](#setup) - - [Quick Start Guide](#quick-start-guide) - - [Deployment on Production](#deployment-on-production) - - [Performance](#performance) - - [Offline scenario](#offline-scenario) - - [Offline: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: electricity](#offline-nvidia-a30-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Offline: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: traffic](#offline-nvidia-a30-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Offline: NVIDIA A30, PyTorch with FP16, Dataset: electricity](#offline-nvidia-a30-pytorch-with-fp16-dataset-electricity) - - [Offline: NVIDIA A30, PyTorch with FP16, Dataset: traffic](#offline-nvidia-a30-pytorch-with-fp16-dataset-traffic) - - [Offline: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: electricity](#offline-nvidia-dgx-1-1x-v100-32gb-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Offline: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: traffic](#offline-nvidia-dgx-1-1x-v100-32gb-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Offline: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: electricity](#offline-nvidia-dgx-1-1x-v100-32gb-pytorch-with-fp16-dataset-electricity) - - [Offline: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: traffic](#offline-nvidia-dgx-1-1x-v100-32gb-pytorch-with-fp16-dataset-traffic) - - [Offline: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: electricity](#offline-nvidia-dgx-a100-1x-a100-80gb-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Offline: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: traffic](#offline-nvidia-dgx-a100-1x-a100-80gb-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Offline: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: electricity](#offline-nvidia-dgx-a100-1x-a100-80gb-pytorch-with-fp16-dataset-electricity) - - [Offline: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: traffic](#offline-nvidia-dgx-a100-1x-a100-80gb-pytorch-with-fp16-dataset-traffic) - - [Offline: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: electricity](#offline-nvidia-t4-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Offline: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: traffic](#offline-nvidia-t4-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Offline: NVIDIA T4, PyTorch with FP16, Dataset: electricity](#offline-nvidia-t4-pytorch-with-fp16-dataset-electricity) - - [Offline: NVIDIA T4, PyTorch with FP16, Dataset: traffic](#offline-nvidia-t4-pytorch-with-fp16-dataset-traffic) - - [Online scenario](#online-scenario) - - [Online: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: electricity](#online-nvidia-a30-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Online: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: traffic](#online-nvidia-a30-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Online: NVIDIA A30, PyTorch with FP16, Dataset: electricity](#online-nvidia-a30-pytorch-with-fp16-dataset-electricity) - - [Online: NVIDIA A30, PyTorch with FP16, Dataset: traffic](#online-nvidia-a30-pytorch-with-fp16-dataset-traffic) - - [Online: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: electricity](#online-nvidia-dgx-1-1x-v100-32gb-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Online: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: traffic](#online-nvidia-dgx-1-1x-v100-32gb-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Online: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: electricity](#online-nvidia-dgx-1-1x-v100-32gb-pytorch-with-fp16-dataset-electricity) - - [Online: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: traffic](#online-nvidia-dgx-1-1x-v100-32gb-pytorch-with-fp16-dataset-traffic) - - [Online: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: electricity](#online-nvidia-dgx-a100-1x-a100-80gb-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Online: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: traffic](#online-nvidia-dgx-a100-1x-a100-80gb-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Online: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: electricity](#online-nvidia-dgx-a100-1x-a100-80gb-pytorch-with-fp16-dataset-electricity) - - [Online: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: traffic](#online-nvidia-dgx-a100-1x-a100-80gb-pytorch-with-fp16-dataset-traffic) - - [Online: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: electricity](#online-nvidia-t4-nvidia-tensorrt-with-fp16-dataset-electricity) - - [Online: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: traffic](#online-nvidia-t4-nvidia-tensorrt-with-fp16-dataset-traffic) - - [Online: NVIDIA T4, PyTorch with FP16, Dataset: electricity](#online-nvidia-t4-pytorch-with-fp16-dataset-electricity) - - [Online: NVIDIA T4, PyTorch with FP16, Dataset: traffic](#online-nvidia-t4-pytorch-with-fp16-dataset-traffic) - - [Advanced](#advanced) - - [Step by step deployment process](#step-by-step-deployment-process) - - [Latency explanation](#latency-explanation) - - [Release notes](#release-notes) - - [Changelog](#changelog) - - [Known issues](#known-issues) - - -## Solution overview -### Introduction -The [NVIDIA Triton Inference Server](https://github.com/NVIDIA/triton-inference-server) -provides a datacenter and cloud inferencing solution optimized for NVIDIA GPUs. -The server provides an inference service via an HTTP or gRPC endpoint, -allowing remote clients to request inferencing for any number of GPU -or CPU models being managed by the server. - -This README provides step-by-step deployment instructions for models generated -during training (as described in the [model README](../readme.md)). -Additionally, this README provides the corresponding deployment scripts that -ensure optimal GPU utilization during inferencing on Triton Inference Server. - -### Deployment process - -The deployment process consists of two steps: - -1. Conversion. - - The purpose of conversion is to find the best performing model - format supported by Triton Inference Server. - Triton Inference Server uses a number of runtime backends such as - [TensorRT](https://developer.nvidia.com/tensorrt), - [LibTorch](https://github.com/triton-inference-server/pytorch_backend) and - [ONNX Runtime](https://github.com/triton-inference-server/onnxruntime_backend) - to support various model types. Refer to the - [Triton documentation](https://github.com/triton-inference-server/backend#where-can-i-find-all-the-backends-that-are-available-for-triton) - for a list of available backends. - -2. Configuration. - - Model configuration on Triton Inference Server, which generates - necessary [configuration files](https://github.com/triton-inference-server/server/blob/master/docs/model_configuration.md). - -After deployment Triton inference server is used for evaluation of converted model in two steps: - -1. Accuracy tests. - - Produce results which are tested against given accuracy thresholds. - -2. Performance tests. - - Produce latency and throughput results for offline (static batching) - and online (dynamic batching) scenarios. - - -All steps are executed by provided runner script. Refer to [Quick Start Guide](#quick-start-guide) - - -## Setup -Ensure you have the following components: -* [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) -* [PyTorch NGC container 21.12](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/pytorch) -* [Triton Inference Server NGC container 21.12](https://ngc.nvidia.com/catalog/containers/nvidia:tritonserver) -* [NVIDIA CUDA](https://docs.nvidia.com/cuda/archive//index.html) -* [NVIDIA Ampere](https://www.nvidia.com/en-us/data-center/nvidia-ampere-gpu-architecture/), [Volta](https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/) or [Turing](https://www.nvidia.com/en-us/geforce/turing/) based GPU - - - -## Quick Start Guide -Running the following scripts will build and launch the container with all required dependencies for native PyTorch as well as Triton Inference Server. This is necessary for running inference and can also be used for data download, processing, and training of the model. - -1. Clone the repository. - -``` -git clone https://github.com/NVIDIA/DeepLearningExamples.git -cd DeepLearningExamples/PyTorch/Forecasting/TFT -``` - -2. Prepare dataset. -Please use the data download from the [Main QSG](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Forecasting/TFT#quick-start-guide) - - -3. Build and run a container that extends NGC PyTorch with the Triton client libraries and necessary dependencies. - -``` -./triton/scripts/docker/build.sh -./triton/scripts/docker/interactive.sh /path/to/your/data/ -``` - -4. Execute runner script (please mind, the run scripts are prepared per NVIDIA GPU). - -``` -NVIDIA A30: ./triton/runner/start_NVIDIA-A30.sh - -NVIDIA DGX-1 (1x V100 32GB): ./triton/runner/start_NVIDIA-DGX-1-\(1x-V100-32GB\).sh - -NVIDIA DGX A100 (1x A100 80GB): ./triton/runner/start_NVIDIA-DGX-A100-\(1x-A100-80GB\).sh - -NVIDIA T4: ./triton/runner/start_NVIDIA-T4.sh -``` -## Deployment on Production - -In order to achieve the best performance results on production use [Triton Model Navigator](https://github.com/triton-inference-server/model_navigator). -The Triton Model Navigator is a tool that provides the ability to automate the process of a model deployment on -the NVIDIA [Triton Inference Server](https://github.com/triton-inference-server). -The tool optimize models running conversion to available formats and applying addition Triton backends optimizations. -Then it uses [Triton Model Analyzer](https://github.com/triton-inference-server/model_analyzer) to find the best Triton Model configuration, -matches the provided constraints, and optimize performance. - -1. Export Model - -Export model from Python source to desired format (e.g. Savedmodel or TorchScript) - -
-Export Model Command - -```shell -if [[ "${EXPORT_FORMAT}" == "ts-trace" || "${EXPORT_FORMAT}" == "ts-script" ]]; then - export FORMAT_SUFFIX="pt" -else - export FORMAT_SUFFIX="${EXPORT_FORMAT}" -fi -python3 triton/export_model.py \ - --input-path triton/model.py \ - --input-type pyt \ - --output-path ${SHARED_DIR}/exported_model.${FORMAT_SUFFIX} \ - --output-type ${EXPORT_FORMAT} \ - --ignore-unknown-parameters \ - --onnx-opset 13 \ - \ - --checkpoint ${CHECKPOINT_DIR}/ \ - --precision ${EXPORT_PRECISION} \ - \ - --dataloader triton/dataloader.py \ - --dataset ${DATASETS_DIR}/${DATASET} \ - --batch-size 1 -```` - -
- - -2. Use Model Navigator to find best model configuration. - -
-Model Navigator Command - -```shell -model-navigator run --model-name TFT --model-path ${SHARED_DIR}/exported_model.onnx -``` -
- -Read more about Triton Model Navigator usage in [documentation](https://github.com/triton-inference-server/model_navigator) -## Performance -The performance measurements in this document were conducted at the time of publication and may not reflect -the performance achieved from NVIDIA’s latest software release. For the most up-to-date performance measurements, go to -[NVIDIA Data Center Deep Learning Product Performance](https://developer.nvidia.com/deep-learning-performance-training-inference). -### Offline scenario - -The offline scenario assumes the client and server are located on the same host. The tests uses: -- tensors are passed through shared memory between client and server, the Perf Analyzer flag `shared-memory=system` is used -- single request is send from client to server with static size of batch - - -#### Offline: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 595.0 | 0.0 | 0.2 | 0.1 | 0.1 | 1.3 | 0.0 | 0.0 | 1.7 | 1.7 | 1.8 | 1.8 | 1.7 | -| 2 | 1 | 804.6 | 0.0 | 0.1 | 0.0 | 0.1 | 2.1 | 0.1 | 0.0 | 2.5 | 2.6 | 2.6 | 2.6 | 2.5 | -| 4 | 1 | 1500.0 | 0.0 | 0.2 | 0.1 | 0.1 | 2.2 | 0.1 | 0.0 | 2.7 | 2.7 | 2.7 | 2.8 | 2.7 | -| 8 | 1 | 2696.0 | 0.1 | 0.2 | 0.1 | 0.1 | 2.5 | 0.0 | 0.0 | 2.9 | 3.0 | 3.1 | 3.3 | 3.0 | -| 16 | 1 | 4704.0 | 0.1 | 0.2 | 0.1 | 0.1 | 2.9 | 0.0 | 0.0 | 3.4 | 3.5 | 3.6 | 3.8 | 3.4 | -| 32 | 1 | 8576.0 | 0.1 | 0.2 | 0.0 | 0.1 | 3.2 | 0.1 | 0.0 | 3.7 | 3.9 | 3.9 | 4.0 | 3.7 | -| 64 | 1 | 14101.3 | 0.1 | 0.2 | 0.0 | 0.1 | 4.0 | 0.0 | 0.0 | 4.5 | 4.6 | 4.7 | 5.2 | 4.5 | -| 128 | 1 | 19227.2 | 0.1 | 0.2 | 0.1 | 0.1 | 6.1 | 0.0 | 0.0 | 6.5 | 6.7 | 8.0 | 8.3 | 6.6 | -| 256 | 1 | 24401.3 | 0.1 | 0.3 | 0.1 | 0.2 | 9.8 | 0.0 | 0.0 | 10.4 | 10.5 | 11.4 | 11.6 | 10.5 | -| 512 | 1 | 27235.7 | 0.1 | 0.4 | 0.1 | 1.0 | 17.1 | 0.1 | 0.0 | 18.8 | 18.8 | 18.8 | 18.8 | 18.8 | -| 1024 | 1 | 28782.6 | 0.1 | 0.4 | 0.1 | 1.9 | 32.9 | 0.2 | 0.0 | 35.5 | 35.6 | 35.6 | 35.7 | 35.5 | - -
- - - -#### Offline: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 605.4 | 0.0 | 0.2 | 0.0 | 0.1 | 1.3 | 0.0 | 0.0 | 1.6 | 1.7 | 1.7 | 1.7 | 1.6 | -| 2 | 1 | 840.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.1 | 0.0 | 0.0 | 2.4 | 2.4 | 2.4 | 2.5 | 2.4 | -| 4 | 1 | 1638.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.2 | 0.0 | 0.0 | 2.4 | 2.5 | 2.5 | 2.6 | 2.4 | -| 8 | 1 | 2876.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.5 | 0.0 | 0.0 | 2.8 | 2.9 | 2.9 | 2.9 | 2.8 | -| 16 | 1 | 5168.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.8 | 0.0 | 0.0 | 3.1 | 3.3 | 3.3 | 3.4 | 3.1 | -| 32 | 1 | 8576.0 | 0.0 | 0.1 | 0.0 | 0.1 | 3.3 | 0.0 | 0.0 | 3.7 | 3.9 | 4.0 | 4.1 | 3.7 | -| 64 | 1 | 14592.0 | 0.0 | 0.1 | 0.0 | 0.1 | 4.0 | 0.0 | 0.0 | 4.3 | 4.5 | 4.5 | 4.7 | 4.4 | -| 128 | 1 | 19520.0 | 0.0 | 0.1 | 0.0 | 0.1 | 6.2 | 0.0 | 0.0 | 6.5 | 6.6 | 7.9 | 8.3 | 6.5 | -| 256 | 1 | 24832.0 | 0.0 | 0.2 | 0.0 | 0.2 | 9.8 | 0.0 | 0.0 | 10.2 | 10.4 | 10.9 | 11.1 | 10.3 | -| 512 | 1 | 27235.7 | 0.1 | 0.4 | 0.1 | 1.1 | 17.0 | 0.1 | 0.0 | 18.8 | 18.8 | 18.8 | 18.9 | 18.8 | -| 1024 | 1 | 28725.7 | 0.1 | 0.4 | 0.1 | 2.0 | 32.9 | 0.2 | 0.0 | 35.6 | 35.7 | 35.7 | 35.8 | 35.6 | - -
- - - -#### Offline: NVIDIA A30, PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 126.5 | 0.1 | 0.4 | 0.1 | 0.1 | 7.2 | 0.0 | 0.0 | 7.8 | 8.0 | 8.8 | 9.5 | 7.9 | -| 2 | 1 | 234.8 | 0.1 | 0.4 | 0.1 | 0.1 | 7.8 | 0.0 | 0.0 | 8.3 | 9.9 | 10.1 | 10.3 | 8.5 | -| 4 | 1 | 431.1 | 0.1 | 0.4 | 0.1 | 0.1 | 8.5 | 0.0 | 0.0 | 8.6 | 10.3 | 10.4 | 10.5 | 9.2 | -| 8 | 1 | 860.8 | 0.1 | 0.4 | 0.1 | 0.2 | 8.5 | 0.0 | 0.0 | 8.9 | 10.5 | 10.7 | 10.8 | 9.3 | -| 16 | 1 | 1747.2 | 0.1 | 0.5 | 0.1 | 0.2 | 8.3 | 0.0 | 0.0 | 8.8 | 10.5 | 10.6 | 10.7 | 9.1 | -| 32 | 1 | 3205.8 | 0.1 | 0.4 | 0.1 | 0.2 | 9.1 | 0.0 | 0.0 | 9.8 | 11.2 | 11.3 | 11.4 | 10.0 | -| 64 | 1 | 6249.6 | 0.1 | 0.4 | 0.1 | 0.3 | 8.9 | 0.4 | 0.0 | 9.7 | 11.5 | 11.5 | 11.6 | 10.2 | -| 128 | 1 | 9216.0 | 0.1 | 0.3 | 0.1 | 0.5 | 8.9 | 3.9 | 0.0 | 13.9 | 14.1 | 14.2 | 14.4 | 13.9 | -| 256 | 1 | 11369.7 | 0.1 | 0.3 | 0.1 | 0.9 | 5.3 | 15.8 | 0.0 | 22.5 | 22.7 | 22.7 | 23.0 | 22.5 | -| 512 | 1 | 12383.8 | 0.1 | 0.3 | 0.1 | 1.6 | 5.4 | 33.8 | 0.0 | 41.3 | 41.5 | 41.6 | 41.7 | 41.3 | -| 1024 | 1 | 12849.9 | 0.1 | 0.4 | 0.1 | 3.2 | 5.6 | 70.2 | 0.0 | 79.6 | 80.0 | 80.1 | 80.3 | 79.6 | - -
- - - -#### Offline: NVIDIA A30, PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 189.0 | 0.1 | 0.3 | 0.0 | 0.1 | 4.8 | 0.0 | 0.0 | 4.6 | 7.4 | 7.4 | 8.5 | 5.3 | -| 2 | 1 | 252.9 | 0.1 | 0.4 | 0.1 | 0.1 | 7.2 | 0.0 | 0.0 | 7.9 | 8.0 | 8.0 | 8.1 | 7.9 | -| 4 | 1 | 500.0 | 0.1 | 0.4 | 0.1 | 0.1 | 7.3 | 0.0 | 0.0 | 8.0 | 8.0 | 8.0 | 9.2 | 8.0 | -| 8 | 1 | 998.0 | 0.1 | 0.3 | 0.1 | 0.1 | 7.4 | 0.0 | 0.0 | 8.0 | 8.0 | 8.1 | 8.2 | 8.0 | -| 16 | 1 | 1996.0 | 0.1 | 0.3 | 0.1 | 0.1 | 7.4 | 0.0 | 0.0 | 8.0 | 8.1 | 8.1 | 9.1 | 8.0 | -| 32 | 1 | 3750.4 | 0.1 | 0.4 | 0.1 | 0.1 | 7.8 | 0.0 | 0.0 | 8.5 | 8.6 | 8.7 | 10.3 | 8.5 | -| 64 | 1 | 7179.4 | 0.1 | 0.4 | 0.1 | 0.2 | 7.7 | 0.4 | 0.0 | 8.9 | 9.0 | 9.1 | 9.4 | 8.9 | -| 128 | 1 | 9946.0 | 0.1 | 0.3 | 0.1 | 0.3 | 7.3 | 4.8 | 0.0 | 12.8 | 13.3 | 13.6 | 13.7 | 12.8 | -| 256 | 1 | 11821.5 | 0.0 | 0.2 | 0.0 | 0.6 | 5.0 | 15.8 | 0.0 | 21.6 | 21.8 | 21.8 | 21.8 | 21.6 | -| 512 | 1 | 12825.0 | 0.0 | 0.2 | 0.0 | 0.8 | 5.0 | 33.8 | 0.0 | 40.0 | 40.3 | 40.5 | 40.6 | 39.8 | -| 1024 | 1 | 13284.7 | 0.0 | 0.2 | 0.0 | 1.8 | 5.3 | 69.7 | 0.0 | 77.3 | 77.7 | 77.8 | 77.9 | 77.1 | - -
- - - -#### Offline: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 416.5 | 0.1 | 0.2 | 0.1 | 0.1 | 1.8 | 0.0 | 0.0 | 2.4 | 2.5 | 2.5 | 2.6 | 2.4 | -| 2 | 1 | 770.6 | 0.1 | 0.3 | 0.1 | 0.2 | 1.9 | 0.0 | 0.0 | 2.6 | 2.6 | 2.7 | 2.7 | 2.6 | -| 4 | 1 | 1427.3 | 0.1 | 0.2 | 0.1 | 0.2 | 2.2 | 0.0 | 0.0 | 2.8 | 2.9 | 2.9 | 3.0 | 2.8 | -| 8 | 1 | 2604.0 | 0.1 | 0.3 | 0.1 | 0.2 | 2.4 | 0.0 | 0.0 | 3.1 | 3.2 | 3.2 | 3.3 | 3.1 | -| 16 | 1 | 4480.0 | 0.1 | 0.3 | 0.1 | 0.2 | 2.9 | 0.0 | 0.0 | 3.6 | 3.7 | 3.7 | 3.8 | 3.6 | -| 32 | 1 | 7274.7 | 0.1 | 0.2 | 0.1 | 0.2 | 3.9 | 0.0 | 0.0 | 4.4 | 4.5 | 4.5 | 4.6 | 4.4 | -| 64 | 1 | 10922.7 | 0.1 | 0.2 | 0.1 | 0.2 | 5.3 | 0.0 | 0.0 | 5.8 | 6.0 | 6.0 | 6.1 | 5.8 | -| 128 | 1 | 13744.5 | 0.1 | 0.2 | 0.1 | 0.2 | 8.7 | 0.0 | 0.0 | 9.3 | 9.4 | 9.4 | 9.6 | 9.3 | -| 256 | 1 | 17341.8 | 0.1 | 0.2 | 0.1 | 0.3 | 14.0 | 0.0 | 0.0 | 14.7 | 14.9 | 14.9 | 15.1 | 14.7 | -| 512 | 1 | 20439.0 | 0.1 | 0.2 | 0.1 | 0.5 | 24.1 | 0.0 | 0.0 | 25.0 | 25.1 | 25.2 | 25.6 | 25.0 | -| 1024 | 1 | 23410.2 | 0.1 | 0.3 | 0.1 | 0.7 | 42.5 | 0.0 | 0.0 | 43.6 | 43.8 | 43.9 | 44.6 | 43.7 | - -
- - - -#### Offline: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 406.0 | 0.1 | 0.2 | 0.1 | 0.2 | 1.8 | 0.0 | 0.0 | 2.4 | 2.5 | 2.5 | 2.6 | 2.5 | -| 2 | 1 | 775.0 | 0.1 | 0.2 | 0.1 | 0.2 | 2.0 | 0.0 | 0.0 | 2.6 | 2.7 | 2.7 | 2.8 | 2.6 | -| 4 | 1 | 1431.3 | 0.1 | 0.2 | 0.1 | 0.2 | 2.2 | 0.0 | 0.0 | 2.8 | 3.0 | 3.0 | 3.2 | 2.8 | -| 8 | 1 | 2644.0 | 0.1 | 0.2 | 0.1 | 0.1 | 2.5 | 0.0 | 0.0 | 3.0 | 3.1 | 3.1 | 3.1 | 3.0 | -| 16 | 1 | 4824.0 | 0.1 | 0.2 | 0.1 | 0.2 | 2.7 | 0.0 | 0.0 | 3.3 | 3.4 | 3.4 | 3.5 | 3.3 | -| 32 | 1 | 7637.3 | 0.1 | 0.2 | 0.1 | 0.2 | 3.6 | 0.0 | 0.0 | 4.2 | 4.3 | 4.3 | 4.4 | 4.2 | -| 64 | 1 | 10919.0 | 0.1 | 0.3 | 0.1 | 0.2 | 5.2 | 0.0 | 0.0 | 5.8 | 5.9 | 6.0 | 6.0 | 5.8 | -| 128 | 1 | 13488.5 | 0.1 | 0.2 | 0.1 | 0.2 | 8.8 | 0.0 | 0.0 | 9.4 | 9.7 | 9.8 | 10.0 | 9.5 | -| 256 | 1 | 17216.0 | 0.1 | 0.2 | 0.1 | 0.3 | 14.2 | 0.0 | 0.0 | 14.8 | 15.0 | 15.1 | 15.2 | 14.8 | -| 512 | 1 | 20596.6 | 0.1 | 0.3 | 0.1 | 0.5 | 23.9 | 0.0 | 0.0 | 24.8 | 25.0 | 25.1 | 25.3 | 24.8 | -| 1024 | 1 | 23456.8 | 0.1 | 0.2 | 0.1 | 0.7 | 42.6 | 0.0 | 0.0 | 43.7 | 44.3 | 44.4 | 44.9 | 43.6 | - -
- - - -#### Offline: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 134.2 | 0.1 | 0.3 | 0.1 | 0.1 | 6.9 | 0.0 | 0.0 | 8.1 | 8.3 | 8.4 | 9.1 | 7.4 | -| 2 | 1 | 271.5 | 0.0 | 0.2 | 0.1 | 0.1 | 6.9 | 0.0 | 0.0 | 7.2 | 8.2 | 8.3 | 8.3 | 7.3 | -| 4 | 1 | 524.9 | 0.1 | 0.3 | 0.1 | 0.1 | 7.1 | 0.0 | 0.0 | 8.3 | 8.5 | 8.9 | 9.6 | 7.6 | -| 8 | 1 | 1044.0 | 0.1 | 0.3 | 0.1 | 0.1 | 7.1 | 0.0 | 0.0 | 8.4 | 8.5 | 8.6 | 9.5 | 7.6 | -| 16 | 1 | 2119.5 | 0.1 | 0.3 | 0.1 | 0.1 | 7.0 | 0.0 | 0.0 | 8.2 | 8.4 | 8.5 | 8.8 | 7.5 | -| 32 | 1 | 3775.2 | 0.1 | 0.3 | 0.1 | 0.1 | 7.9 | 0.0 | 0.0 | 9.2 | 9.4 | 9.4 | 9.5 | 8.4 | -| 64 | 1 | 6424.3 | 0.1 | 0.3 | 0.1 | 0.1 | 7.9 | 1.5 | 0.0 | 9.9 | 10.1 | 10.1 | 10.6 | 9.9 | -| 128 | 1 | 8528.0 | 0.1 | 0.2 | 0.1 | 0.2 | 8.0 | 6.4 | 0.0 | 15.1 | 15.2 | 15.3 | 15.4 | 15.0 | -| 256 | 1 | 10644.4 | 0.1 | 0.3 | 0.1 | 0.3 | 8.0 | 15.3 | 0.0 | 24.1 | 24.3 | 24.3 | 24.7 | 24.0 | -| 512 | 1 | 12213.7 | 0.1 | 0.3 | 0.1 | 0.5 | 7.3 | 33.8 | 0.0 | 41.9 | 42.1 | 42.1 | 42.2 | 41.9 | -| 1024 | 1 | 13153.4 | 0.1 | 0.3 | 0.1 | 0.8 | 6.6 | 69.9 | 0.0 | 77.7 | 77.8 | 77.9 | 78.1 | 77.7 | - -
- - - -#### Offline: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 158.0 | 0.1 | 0.2 | 0.1 | 0.1 | 5.9 | 0.0 | 0.0 | 6.4 | 6.5 | 6.6 | 6.7 | 6.3 | -| 2 | 1 | 312.5 | 0.1 | 0.3 | 0.1 | 0.1 | 5.9 | 0.0 | 0.0 | 6.5 | 6.6 | 6.6 | 6.8 | 6.4 | -| 4 | 1 | 608.0 | 0.1 | 0.3 | 0.1 | 0.1 | 6.0 | 0.0 | 0.0 | 6.6 | 6.8 | 6.8 | 7.0 | 6.6 | -| 8 | 1 | 1208.0 | 0.1 | 0.2 | 0.1 | 0.1 | 6.1 | 0.0 | 0.0 | 6.7 | 6.8 | 6.9 | 6.9 | 6.6 | -| 16 | 1 | 2456.0 | 0.1 | 0.3 | 0.1 | 0.1 | 5.9 | 0.0 | 0.0 | 6.5 | 6.6 | 6.7 | 7.3 | 6.5 | -| 32 | 1 | 4352.0 | 0.1 | 0.3 | 0.1 | 0.1 | 6.8 | 0.0 | 0.0 | 7.3 | 7.4 | 7.5 | 8.1 | 7.3 | -| 64 | 1 | 6366.9 | 0.1 | 0.3 | 0.1 | 0.1 | 7.2 | 2.3 | 0.0 | 10.0 | 10.1 | 10.1 | 10.2 | 10.0 | -| 128 | 1 | 8544.0 | 0.1 | 0.3 | 0.1 | 0.2 | 7.3 | 7.0 | 0.0 | 14.9 | 15.1 | 15.1 | 15.3 | 15.0 | -| 256 | 1 | 10687.1 | 0.1 | 0.3 | 0.1 | 0.3 | 7.3 | 15.9 | 0.0 | 23.9 | 24.0 | 24.0 | 24.1 | 23.9 | -| 512 | 1 | 12189.3 | 0.1 | 0.3 | 0.1 | 0.5 | 7.2 | 33.9 | 0.0 | 42.0 | 42.1 | 42.1 | 42.2 | 42.0 | -| 1024 | 1 | 13153.1 | 0.1 | 0.3 | 0.1 | 0.8 | 7.0 | 69.5 | 0.0 | 77.8 | 77.9 | 77.9 | 78.1 | 77.8 | - -
- - - -#### Offline: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 663.0 | 0.0 | 0.1 | 0.0 | 0.1 | 1.3 | 0.0 | 0.0 | 1.4 | 1.6 | 1.6 | 4.7 | 1.5 | -| 2 | 1 | 879.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.1 | 0.0 | 0.0 | 2.3 | 2.4 | 2.4 | 2.4 | 2.3 | -| 4 | 1 | 1638.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.2 | 0.0 | 0.0 | 2.4 | 2.5 | 2.5 | 2.5 | 2.4 | -| 8 | 1 | 3080.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.4 | 0.0 | 0.0 | 2.6 | 2.6 | 2.7 | 2.7 | 2.6 | -| 16 | 1 | 5808.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.5 | 0.0 | 0.0 | 2.7 | 2.8 | 2.8 | 2.9 | 2.8 | -| 32 | 1 | 10688.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.7 | 0.0 | 0.0 | 3.0 | 3.1 | 3.1 | 3.1 | 3.0 | -| 64 | 1 | 17664.0 | 0.0 | 0.1 | 0.0 | 0.1 | 3.4 | 0.0 | 0.0 | 3.6 | 3.8 | 3.9 | 3.9 | 3.6 | -| 128 | 1 | 24362.7 | 0.0 | 0.1 | 0.0 | 0.2 | 4.9 | 0.0 | 0.0 | 5.2 | 5.5 | 5.5 | 5.6 | 5.2 | -| 256 | 1 | 35136.0 | 0.0 | 0.1 | 0.0 | 0.2 | 6.9 | 0.0 | 0.0 | 7.3 | 7.5 | 7.5 | 7.7 | 7.3 | -| 512 | 1 | 49493.3 | 0.0 | 0.1 | 0.0 | 0.2 | 9.9 | 0.0 | 0.0 | 10.2 | 10.4 | 10.5 | 12.9 | 10.3 | -| 1024 | 1 | 54061.8 | 0.0 | 0.1 | 0.0 | 0.5 | 18.2 | 0.1 | 0.0 | 18.8 | 18.9 | 19.0 | 22.3 | 18.9 | - -
- - - -#### Offline: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 716.0 | 0.0 | 0.1 | 0.0 | 0.1 | 1.2 | 0.0 | 0.0 | 1.4 | 1.4 | 1.4 | 2.1 | 1.4 | -| 2 | 1 | 878.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.1 | 0.0 | 0.0 | 2.3 | 2.4 | 2.4 | 2.4 | 2.3 | -| 4 | 1 | 1653.2 | 0.0 | 0.1 | 0.0 | 0.1 | 2.2 | 0.0 | 0.0 | 2.4 | 2.5 | 2.5 | 2.5 | 2.4 | -| 8 | 1 | 3192.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.3 | 0.0 | 0.0 | 2.5 | 2.5 | 2.6 | 2.6 | 2.5 | -| 16 | 1 | 5920.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.5 | 0.0 | 0.0 | 2.7 | 2.8 | 2.8 | 2.8 | 2.7 | -| 32 | 1 | 10624.0 | 0.0 | 0.1 | 0.0 | 0.1 | 2.8 | 0.0 | 0.0 | 3.0 | 3.1 | 3.1 | 3.1 | 3.0 | -| 64 | 1 | 18358.8 | 0.0 | 0.1 | 0.0 | 0.1 | 3.2 | 0.0 | 0.0 | 3.5 | 3.5 | 3.6 | 3.6 | 3.5 | -| 128 | 1 | 24738.4 | 0.0 | 0.1 | 0.0 | 0.2 | 4.8 | 0.0 | 0.0 | 5.2 | 5.3 | 5.3 | 5.4 | 5.2 | -| 256 | 1 | 35776.0 | 0.0 | 0.1 | 0.0 | 0.2 | 6.8 | 0.0 | 0.0 | 7.1 | 7.3 | 7.4 | 7.5 | 7.1 | -| 512 | 1 | 49834.7 | 0.0 | 0.1 | 0.0 | 0.2 | 9.9 | 0.0 | 0.0 | 10.2 | 10.3 | 10.3 | 11.3 | 10.3 | -| 1024 | 1 | 53350.4 | 0.0 | 0.1 | 0.0 | 0.4 | 18.6 | 0.0 | 0.0 | 19.1 | 19.2 | 19.3 | 22.4 | 19.2 | - -
- - - -#### Offline: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 205.0 | 0.0 | 0.1 | 0.0 | 0.1 | 4.6 | 0.0 | 0.0 | 4.8 | 4.9 | 4.9 | 5.3 | 4.9 | -| 2 | 1 | 396.0 | 0.0 | 0.1 | 0.0 | 0.1 | 4.8 | 0.0 | 0.0 | 5.0 | 5.2 | 5.4 | 5.5 | 5.0 | -| 4 | 1 | 788.0 | 0.0 | 0.1 | 0.0 | 0.1 | 4.8 | 0.0 | 0.0 | 5.0 | 5.1 | 5.3 | 5.5 | 5.1 | -| 8 | 1 | 1544.0 | 0.0 | 0.1 | 0.0 | 0.1 | 4.9 | 0.0 | 0.0 | 5.1 | 5.4 | 5.5 | 5.6 | 5.2 | -| 16 | 1 | 3081.6 | 0.0 | 0.1 | 0.0 | 0.1 | 4.9 | 0.0 | 0.0 | 5.1 | 5.4 | 5.5 | 5.6 | 5.2 | -| 32 | 1 | 5802.7 | 0.0 | 0.1 | 0.0 | 0.1 | 5.2 | 0.0 | 0.0 | 5.5 | 5.5 | 5.8 | 5.9 | 5.5 | -| 64 | 1 | 10624.0 | 0.0 | 0.1 | 0.0 | 0.1 | 5.3 | 0.5 | 0.0 | 6.0 | 6.1 | 6.2 | 6.4 | 6.0 | -| 128 | 1 | 15203.4 | 0.0 | 0.1 | 0.0 | 0.2 | 5.3 | 2.8 | 0.0 | 8.4 | 8.6 | 8.7 | 8.9 | 8.4 | -| 256 | 1 | 19821.7 | 0.0 | 0.1 | 0.0 | 0.3 | 5.3 | 7.2 | 0.0 | 13.0 | 13.1 | 13.3 | 13.4 | 12.9 | -| 512 | 1 | 23123.4 | 0.0 | 0.1 | 0.0 | 0.4 | 5.3 | 16.2 | 0.0 | 22.2 | 22.3 | 22.4 | 22.4 | 22.1 | -| 1024 | 1 | 25159.9 | 0.0 | 0.1 | 0.0 | 0.9 | 5.7 | 33.9 | 0.0 | 40.7 | 40.8 | 40.9 | 40.9 | 40.6 | - -
- - - -#### Offline: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 200.3 | 0.0 | 0.1 | 0.0 | 0.1 | 4.7 | 0.0 | 0.0 | 5.0 | 5.1 | 5.3 | 5.4 | 5.0 | -| 2 | 1 | 393.3 | 0.0 | 0.1 | 0.0 | 0.1 | 4.8 | 0.0 | 0.0 | 5.1 | 5.1 | 5.4 | 5.5 | 5.1 | -| 4 | 1 | 774.7 | 0.0 | 0.1 | 0.0 | 0.1 | 4.9 | 0.0 | 0.0 | 5.1 | 5.2 | 5.5 | 5.8 | 5.2 | -| 8 | 1 | 1525.3 | 0.0 | 0.1 | 0.0 | 0.1 | 5.0 | 0.0 | 0.0 | 5.2 | 5.5 | 5.6 | 5.7 | 5.2 | -| 16 | 1 | 3028.3 | 0.0 | 0.1 | 0.0 | 0.1 | 5.0 | 0.0 | 0.0 | 5.2 | 5.6 | 5.7 | 5.7 | 5.3 | -| 32 | 1 | 5696.0 | 0.0 | 0.1 | 0.0 | 0.1 | 5.3 | 0.0 | 0.0 | 5.6 | 5.7 | 5.9 | 6.0 | 5.6 | -| 64 | 1 | 10645.3 | 0.0 | 0.1 | 0.0 | 0.1 | 5.4 | 0.3 | 0.0 | 6.0 | 6.2 | 6.2 | 6.3 | 6.0 | -| 128 | 1 | 15229.0 | 0.0 | 0.2 | 0.0 | 0.2 | 5.4 | 2.6 | 0.0 | 8.4 | 8.6 | 8.7 | 8.8 | 8.4 | -| 256 | 1 | 19965.1 | 0.0 | 0.1 | 0.0 | 0.3 | 5.4 | 7.0 | 0.0 | 12.8 | 13.2 | 13.3 | 13.3 | 12.8 | -| 512 | 1 | 23319.3 | 0.0 | 0.1 | 0.0 | 0.5 | 5.4 | 15.9 | 0.0 | 21.9 | 22.1 | 22.2 | 22.2 | 21.9 | -| 1024 | 1 | 25452.5 | 0.0 | 0.1 | 0.0 | 0.9 | 5.8 | 33.3 | 0.0 | 40.2 | 40.4 | 40.5 | 40.6 | 40.2 | - -
- - - -#### Offline: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 415.0 | 0.1 | 0.4 | 0.1 | 0.2 | 1.6 | 0.0 | 0.0 | 2.4 | 2.5 | 2.5 | 2.5 | 2.4 | -| 2 | 1 | 781.6 | 0.1 | 0.4 | 0.1 | 0.2 | 1.7 | 0.0 | 0.0 | 2.5 | 2.6 | 2.6 | 2.6 | 2.5 | -| 4 | 1 | 1617.2 | 0.1 | 0.3 | 0.1 | 0.2 | 1.8 | 0.0 | 0.0 | 2.5 | 2.5 | 2.5 | 2.6 | 2.5 | -| 8 | 1 | 2998.5 | 0.1 | 0.3 | 0.1 | 0.2 | 2.0 | 0.0 | 0.0 | 2.7 | 2.7 | 2.7 | 2.7 | 2.6 | -| 16 | 1 | 4504.0 | 0.1 | 0.5 | 0.1 | 0.2 | 2.7 | 0.0 | 0.0 | 3.5 | 3.6 | 3.6 | 3.6 | 3.5 | -| 32 | 1 | 6483.2 | 0.1 | 0.5 | 0.1 | 0.2 | 4.0 | 0.0 | 0.0 | 4.9 | 5.0 | 5.0 | 5.0 | 4.9 | -| 64 | 1 | 9197.7 | 0.1 | 0.5 | 0.0 | 0.2 | 6.1 | 0.0 | 0.0 | 6.9 | 7.0 | 7.0 | 7.0 | 6.9 | -| 128 | 1 | 11136.0 | 0.0 | 0.3 | 0.1 | 0.2 | 10.8 | 0.0 | 0.0 | 11.5 | 11.6 | 11.6 | 11.6 | 11.5 | -| 256 | 1 | 12682.5 | 0.1 | 0.5 | 0.1 | 0.2 | 19.2 | 0.0 | 0.0 | 20.1 | 20.2 | 20.3 | 20.3 | 20.1 | -| 512 | 1 | 12628.1 | 0.1 | 0.5 | 0.1 | 0.4 | 39.5 | 0.0 | 0.0 | 40.5 | 40.7 | 40.7 | 40.8 | 40.5 | -| 1024 | 1 | 13054.4 | 0.1 | 0.5 | 0.1 | 0.6 | 77.1 | 0.0 | 0.0 | 78.4 | 78.9 | 79.0 | 79.2 | 78.4 | - -
- - - -#### Offline: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 455.5 | 0.1 | 0.3 | 0.0 | 0.1 | 1.6 | 0.0 | 0.0 | 2.2 | 2.3 | 2.3 | 2.3 | 2.2 | -| 2 | 1 | 872.0 | 0.1 | 0.3 | 0.1 | 0.1 | 1.7 | 0.0 | 0.0 | 2.3 | 2.4 | 2.4 | 2.4 | 2.3 | -| 4 | 1 | 1622.0 | 0.1 | 0.2 | 0.1 | 0.1 | 1.9 | 0.0 | 0.0 | 2.5 | 2.5 | 2.5 | 2.6 | 2.4 | -| 8 | 1 | 2882.6 | 0.1 | 0.4 | 0.1 | 0.1 | 2.0 | 0.0 | 0.0 | 2.8 | 2.9 | 2.9 | 2.9 | 2.8 | -| 16 | 1 | 4488.0 | 0.1 | 0.5 | 0.1 | 0.1 | 2.8 | 0.0 | 0.0 | 3.6 | 3.6 | 3.6 | 3.6 | 3.5 | -| 32 | 1 | 6592.0 | 0.1 | 0.5 | 0.1 | 0.1 | 4.1 | 0.0 | 0.0 | 4.8 | 4.9 | 4.9 | 4.9 | 4.8 | -| 64 | 1 | 9341.7 | 0.1 | 0.4 | 0.1 | 0.1 | 6.1 | 0.0 | 0.0 | 6.8 | 6.9 | 6.9 | 7.0 | 6.8 | -| 128 | 1 | 10899.5 | 0.1 | 0.5 | 0.1 | 0.1 | 10.9 | 0.0 | 0.0 | 11.7 | 11.8 | 11.8 | 11.8 | 11.7 | -| 256 | 1 | 12681.3 | 0.1 | 0.4 | 0.1 | 0.2 | 19.3 | 0.0 | 0.0 | 20.1 | 20.3 | 20.3 | 20.4 | 20.1 | -| 512 | 1 | 12651.9 | 0.1 | 0.5 | 0.1 | 0.3 | 39.5 | 0.0 | 0.0 | 40.4 | 40.6 | 40.7 | 40.8 | 40.4 | -| 1024 | 1 | 13003.2 | 0.1 | 0.4 | 0.1 | 0.6 | 77.3 | 0.0 | 0.0 | 78.6 | 79.0 | 79.2 | 79.3 | 78.6 | - -
- - - -#### Offline: NVIDIA T4, PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 127.8 | 0.1 | 0.6 | 0.2 | 0.1 | 6.8 | 0.0 | 0.0 | 7.7 | 8.6 | 8.9 | 9.4 | 7.8 | -| 2 | 1 | 251.0 | 0.1 | 0.6 | 0.1 | 0.1 | 6.9 | 0.0 | 0.0 | 7.8 | 8.8 | 9.2 | 9.6 | 7.9 | -| 4 | 1 | 498.9 | 0.1 | 0.6 | 0.2 | 0.1 | 7.0 | 0.0 | 0.0 | 8.0 | 8.5 | 9.1 | 9.3 | 8.0 | -| 8 | 1 | 975.8 | 0.1 | 0.6 | 0.2 | 0.1 | 7.1 | 0.0 | 0.0 | 8.1 | 8.7 | 8.8 | 9.4 | 8.2 | -| 16 | 1 | 1913.6 | 0.1 | 0.6 | 0.2 | 0.2 | 7.2 | 0.1 | 0.0 | 8.3 | 8.8 | 8.9 | 9.2 | 8.3 | -| 32 | 1 | 2820.9 | 0.1 | 0.6 | 0.1 | 0.2 | 7.5 | 2.8 | 0.0 | 11.3 | 11.6 | 11.6 | 11.8 | 11.3 | -| 64 | 1 | 3366.1 | 0.1 | 0.6 | 0.1 | 0.2 | 8.1 | 9.9 | 0.0 | 18.9 | 19.3 | 19.4 | 19.7 | 19.0 | -| 128 | 1 | 3786.8 | 0.1 | 0.6 | 0.1 | 0.1 | 4.5 | 28.4 | 0.0 | 33.8 | 34.1 | 34.1 | 34.3 | 33.8 | -| 256 | 1 | 3948.1 | 0.1 | 0.6 | 0.1 | 0.2 | 4.4 | 59.4 | 0.0 | 64.7 | 65.5 | 65.8 | 66.0 | 64.7 | -| 512 | 1 | 4079.3 | 0.1 | 0.6 | 0.1 | 0.4 | 4.5 | 119.7 | 0.0 | 125.2 | 127.1 | 127.6 | 128.3 | 125.3 | -| 1024 | 1 | 4095.5 | 0.1 | 0.6 | 0.1 | 0.8 | 4.5 | 243.8 | 0.0 | 250.0 | 251.7 | 252.0 | 252.6 | 249.9 | - -
- - - -#### Offline: NVIDIA T4, PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 1 | 1 | 136.0 | 0.1 | 0.5 | 0.1 | 0.1 | 6.6 | 0.0 | 0.0 | 7.3 | 7.9 | 8.1 | 8.5 | 7.3 | -| 2 | 1 | 242.8 | 0.1 | 0.6 | 0.1 | 0.1 | 7.2 | 0.0 | 0.0 | 8.1 | 8.7 | 9.0 | 9.4 | 8.2 | -| 4 | 1 | 479.9 | 0.1 | 0.6 | 0.2 | 0.1 | 7.3 | 0.0 | 0.0 | 8.2 | 8.9 | 9.2 | 9.6 | 8.3 | -| 8 | 1 | 943.8 | 0.1 | 0.6 | 0.2 | 0.2 | 7.4 | 0.0 | 0.0 | 8.4 | 9.1 | 9.2 | 9.5 | 8.4 | -| 16 | 1 | 2239.4 | 0.1 | 0.5 | 0.1 | 0.1 | 4.2 | 2.1 | 0.0 | 7.1 | 7.2 | 7.2 | 7.3 | 7.1 | -| 32 | 1 | 2975.5 | 0.1 | 0.5 | 0.1 | 0.1 | 4.5 | 5.5 | 0.0 | 10.7 | 10.9 | 10.9 | 10.9 | 10.7 | -| 64 | 1 | 3436.1 | 0.1 | 0.5 | 0.1 | 0.1 | 5.7 | 12.0 | 0.0 | 18.6 | 19.1 | 19.3 | 19.5 | 18.6 | -| 128 | 1 | 3786.8 | 0.1 | 0.5 | 0.1 | 0.2 | 5.7 | 27.1 | 0.0 | 33.7 | 34.0 | 34.1 | 34.2 | 33.7 | -| 256 | 1 | 3963.6 | 0.1 | 0.6 | 0.1 | 0.3 | 7.0 | 56.4 | 0.0 | 64.5 | 65.2 | 65.4 | 65.8 | 64.5 | -| 512 | 1 | 4103.6 | 0.1 | 0.6 | 0.1 | 0.4 | 6.1 | 117.4 | 0.0 | 124.6 | 126.3 | 126.6 | 127.1 | 124.7 | -| 1024 | 1 | 4120.2 | 0.1 | 0.4 | 0.1 | 1.0 | 7.1 | 239.7 | 0.0 | 248.3 | 250.3 | 250.9 | 251.8 | 248.3 | - -
- - - - -### Online scenario - -The online scenario assumes the client and server are located on different hosts. The tests uses: -- tensors are passed through HTTP from client to server -- concurrent requests are send from client to server, the final batch is created on server side - - -#### Online: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 15360.0 | 0.1 | 0.3 | 3.6 | 0.1 | 4.0 | 0.0 | 0.0 | 8.2 | 8.3 | 8.4 | 8.7 | 8.2 | -| 16 | 16 | 15696.0 | 0.1 | 0.5 | 8.5 | 0.2 | 6.9 | 0.1 | 0.0 | 16.4 | 20.2 | 20.4 | 22.2 | 16.2 | -| 16 | 24 | 17072.0 | 0.1 | 0.8 | 10.8 | 0.2 | 10.2 | 0.1 | 0.0 | 22.3 | 30.5 | 31.9 | 33.4 | 22.2 | -| 16 | 32 | 16640.0 | 0.1 | 1.0 | 14.5 | 0.3 | 14.4 | 0.1 | 0.0 | 32.0 | 36.1 | 36.6 | 39.2 | 30.3 | -| 16 | 40 | 19120.0 | 0.1 | 1.6 | 13.8 | 0.3 | 17.2 | 0.1 | 0.0 | 34.9 | 43.8 | 46.3 | 48.5 | 33.1 | -| 16 | 48 | 15984.0 | 0.1 | 1.7 | 16.1 | 0.4 | 27.9 | 0.1 | 0.0 | 49.2 | 52.5 | 53.0 | 53.5 | 46.2 | -| 16 | 56 | 16528.0 | 0.1 | 1.9 | 21.7 | 0.4 | 26.3 | 0.0 | 0.0 | 52.6 | 56.2 | 56.4 | 57.0 | 50.4 | -| 16 | 64 | 16256.0 | 0.1 | 2.2 | 30.6 | 0.3 | 27.0 | 0.0 | 0.0 | 63.8 | 66.2 | 66.5 | 66.9 | 60.3 | -| 16 | 72 | 17696.0 | 0.1 | 2.5 | 34.4 | 0.4 | 25.8 | 0.0 | 0.0 | 65.5 | 68.9 | 69.6 | 70.3 | 63.3 | -| 16 | 80 | 16976.0 | 0.1 | 2.1 | 38.8 | 0.4 | 32.0 | 0.1 | 0.0 | 78.7 | 82.1 | 82.6 | 82.9 | 73.4 | -| 16 | 88 | 20464.0 | 0.1 | 2.7 | 32.0 | 0.6 | 30.5 | 0.0 | 0.0 | 62.7 | 79.0 | 80.0 | 80.8 | 66.0 | -| 16 | 96 | 20064.0 | 0.1 | 2.9 | 39.5 | 0.6 | 31.3 | 0.1 | 0.0 | 75.6 | 79.8 | 80.6 | 81.0 | 74.3 | -| 16 | 104 | 20768.0 | 0.1 | 3.9 | 38.1 | 0.7 | 34.1 | 0.1 | 0.0 | 79.3 | 82.7 | 83.3 | 83.7 | 77.0 | -| 16 | 112 | 22032.0 | 0.1 | 3.5 | 43.1 | 0.7 | 33.1 | 0.1 | 0.0 | 83.0 | 84.1 | 84.3 | 84.5 | 80.5 | -| 16 | 120 | 21584.0 | 0.1 | 3.4 | 49.9 | 0.8 | 33.0 | 0.1 | 0.0 | 92.2 | 93.1 | 93.2 | 94.2 | 87.3 | -| 16 | 128 | 23280.0 | 0.1 | 2.4 | 41.9 | 0.7 | 37.3 | 0.1 | 0.0 | 84.4 | 94.2 | 103.3 | 104.8 | 82.5 | -| 16 | 136 | 23232.0 | 0.1 | 3.6 | 52.6 | 0.7 | 32.7 | 0.1 | 0.0 | 92.4 | 93.4 | 93.7 | 94.4 | 89.7 | -| 16 | 144 | 24224.0 | 0.1 | 3.7 | 50.7 | 0.8 | 34.6 | 0.1 | 0.0 | 92.8 | 95.0 | 96.1 | 102.7 | 90.0 | -| 16 | 152 | 23232.0 | 0.1 | 2.7 | 64.5 | 0.7 | 33.4 | 0.1 | 0.0 | 102.5 | 112.5 | 117.3 | 123.3 | 101.6 | -| 16 | 160 | 21040.0 | 0.1 | 4.6 | 72.2 | 0.8 | 38.0 | 0.1 | 0.0 | 127.8 | 130.2 | 130.8 | 150.9 | 115.8 | -| 16 | 168 | 23848.2 | 0.1 | 4.5 | 66.3 | 0.9 | 35.8 | 0.1 | 0.0 | 109.8 | 111.1 | 111.3 | 111.7 | 107.7 | -| 16 | 176 | 23280.0 | 0.1 | 4.8 | 60.5 | 0.8 | 40.5 | 0.1 | 0.0 | 109.4 | 117.4 | 130.9 | 133.3 | 106.8 | -| 16 | 184 | 21594.4 | 0.3 | 2.8 | 87.2 | 0.9 | 36.6 | 0.1 | 0.0 | 130.0 | 145.0 | 145.2 | 146.6 | 127.8 | -| 16 | 192 | 20816.0 | 0.3 | 3.5 | 99.0 | 0.9 | 36.5 | 0.1 | 0.0 | 145.1 | 147.1 | 148.0 | 165.5 | 140.3 | -| 16 | 200 | 20224.0 | 0.3 | 3.5 | 104.1 | 0.8 | 37.4 | 0.1 | 0.0 | 145.7 | 147.6 | 148.1 | 165.8 | 146.1 | -| 16 | 208 | 21744.0 | 0.2 | 3.9 | 98.5 | 1.0 | 39.0 | 0.2 | 0.0 | 145.8 | 150.7 | 166.3 | 168.3 | 142.8 | -| 16 | 216 | 20112.0 | 0.4 | 2.7 | 117.8 | 0.8 | 34.0 | 0.2 | 0.0 | 156.1 | 157.2 | 157.4 | 157.8 | 156.0 | -| 16 | 224 | 23504.0 | 0.4 | 5.2 | 99.3 | 0.9 | 39.3 | 0.2 | 0.0 | 147.0 | 151.3 | 167.6 | 168.0 | 145.3 | -| 16 | 232 | 24352.0 | 0.5 | 3.6 | 93.6 | 1.0 | 41.3 | 0.2 | 0.0 | 144.9 | 148.2 | 167.3 | 169.5 | 140.2 | -| 16 | 240 | 25760.0 | 0.4 | 2.8 | 89.5 | 0.9 | 45.9 | 0.1 | 0.0 | 140.8 | 159.9 | 171.6 | 181.1 | 139.7 | -| 16 | 248 | 23872.0 | 0.5 | 2.5 | 114.7 | 1.0 | 34.7 | 0.1 | 0.0 | 156.6 | 158.2 | 158.8 | 164.2 | 153.4 | -| 16 | 256 | 24960.0 | 0.5 | 3.4 | 105.6 | 1.1 | 40.0 | 0.1 | 0.0 | 152.3 | 173.8 | 182.2 | 188.4 | 150.8 | - -
- - - - -#### Online: NVIDIA A30, NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 15104.0 | 0.1 | 0.5 | 3.6 | 0.1 | 4.0 | 0.1 | 0.0 | 8.4 | 8.4 | 8.5 | 8.5 | 8.4 | -| 16 | 16 | 15328.0 | 0.1 | 0.7 | 8.5 | 0.2 | 7.1 | 0.1 | 0.0 | 16.8 | 20.8 | 21.1 | 23.1 | 16.6 | -| 16 | 24 | 17072.0 | 0.1 | 1.2 | 10.4 | 0.3 | 10.2 | 0.1 | 0.0 | 23.6 | 30.2 | 30.6 | 32.2 | 22.3 | -| 16 | 32 | 16176.0 | 0.1 | 1.8 | 14.0 | 0.3 | 14.4 | 0.1 | 0.0 | 33.5 | 35.9 | 36.0 | 36.5 | 30.6 | -| 16 | 40 | 18288.0 | 0.1 | 1.7 | 17.3 | 0.3 | 14.5 | 0.1 | 0.0 | 35.8 | 39.6 | 39.9 | 41.3 | 34.0 | -| 16 | 48 | 17136.0 | 0.1 | 2.0 | 18.0 | 0.4 | 22.8 | 0.1 | 0.0 | 45.6 | 51.5 | 52.5 | 53.9 | 43.4 | -| 16 | 56 | 16992.0 | 0.1 | 2.9 | 22.3 | 0.5 | 26.1 | 0.1 | 0.0 | 55.4 | 56.8 | 57.2 | 57.5 | 51.9 | -| 16 | 64 | 17552.0 | 0.1 | 2.8 | 25.2 | 0.5 | 26.7 | 0.1 | 0.0 | 56.2 | 65.9 | 66.3 | 66.6 | 55.4 | -| 16 | 72 | 19552.0 | 0.1 | 3.3 | 28.8 | 0.6 | 25.4 | 0.1 | 0.0 | 65.2 | 66.6 | 67.0 | 69.4 | 58.3 | -| 16 | 80 | 21072.0 | 0.1 | 3.2 | 26.2 | 0.7 | 29.3 | 0.2 | 0.0 | 62.3 | 65.4 | 66.0 | 66.3 | 59.7 | -| 16 | 88 | 19392.0 | 0.1 | 2.3 | 36.0 | 0.8 | 30.6 | 0.1 | 0.0 | 68.1 | 82.9 | 83.7 | 84.1 | 69.9 | -| 16 | 96 | 19168.0 | 0.1 | 3.5 | 38.0 | 0.7 | 33.9 | 0.2 | 0.0 | 79.2 | 80.2 | 80.6 | 83.3 | 76.3 | -| 16 | 104 | 17920.0 | 0.1 | 3.1 | 51.8 | 0.8 | 32.2 | 0.2 | 0.0 | 92.5 | 93.4 | 93.8 | 94.3 | 88.2 | -| 16 | 112 | 21296.0 | 0.1 | 3.8 | 39.7 | 1.0 | 34.7 | 0.2 | 0.0 | 83.4 | 84.3 | 84.8 | 104.0 | 79.4 | -| 16 | 120 | 22032.0 | 0.1 | 3.1 | 45.0 | 0.8 | 33.0 | 0.2 | 0.0 | 82.9 | 93.0 | 93.5 | 94.7 | 82.2 | -| 16 | 128 | 21882.1 | 0.1 | 3.1 | 53.6 | 0.9 | 32.5 | 0.2 | 0.0 | 93.0 | 93.6 | 93.8 | 94.4 | 90.4 | -| 16 | 136 | 25552.0 | 0.1 | 3.8 | 41.3 | 1.0 | 37.3 | 0.2 | 0.0 | 83.9 | 93.7 | 105.3 | 108.0 | 83.7 | -| 16 | 144 | 21904.0 | 0.1 | 5.5 | 60.9 | 0.8 | 33.6 | 0.2 | 0.0 | 103.9 | 113.3 | 113.4 | 132.9 | 101.1 | -| 16 | 152 | 21456.0 | 0.1 | 3.6 | 66.5 | 0.8 | 35.6 | 0.2 | 0.0 | 109.4 | 110.0 | 110.2 | 110.5 | 106.8 | -| 16 | 160 | 23040.0 | 0.2 | 3.3 | 59.4 | 0.9 | 40.4 | 0.2 | 0.0 | 109.7 | 129.7 | 130.1 | 130.9 | 104.3 | -| 16 | 168 | 19600.0 | 0.2 | 0.9 | 88.8 | 0.8 | 34.2 | 0.1 | 0.0 | 128.7 | 131.4 | 144.9 | 145.6 | 125.0 | -| 16 | 176 | 20880.0 | 0.2 | 4.6 | 84.9 | 0.9 | 34.9 | 0.1 | 0.0 | 129.2 | 130.0 | 130.6 | 133.1 | 125.6 | -| 16 | 184 | 22409.6 | 0.2 | 6.5 | 78.3 | 1.1 | 40.1 | 0.1 | 0.0 | 129.6 | 146.7 | 147.9 | 149.9 | 126.2 | -| 16 | 192 | 19456.0 | 0.2 | 3.9 | 101.8 | 0.9 | 35.5 | 0.2 | 0.0 | 145.9 | 147.1 | 147.3 | 147.7 | 142.4 | -| 16 | 200 | 20155.8 | 0.2 | 3.7 | 105.2 | 1.0 | 35.6 | 0.1 | 0.0 | 146.6 | 147.3 | 147.7 | 148.3 | 145.9 | -| 16 | 208 | 21040.0 | 0.3 | 3.8 | 100.1 | 0.8 | 40.2 | 0.1 | 0.0 | 145.7 | 165.6 | 166.2 | 172.1 | 145.4 | -| 16 | 216 | 20784.0 | 0.4 | 2.7 | 117.4 | 0.8 | 34.0 | 0.1 | 0.0 | 155.5 | 156.4 | 156.6 | 156.9 | 155.3 | -| 16 | 224 | 23344.0 | 0.5 | 3.6 | 99.0 | 0.8 | 41.6 | 0.1 | 0.0 | 149.9 | 157.3 | 173.8 | 190.6 | 145.7 | -| 16 | 232 | 21760.0 | 0.4 | 3.2 | 117.4 | 0.9 | 34.2 | 0.2 | 0.0 | 156.7 | 157.3 | 157.5 | 158.1 | 156.3 | -| 16 | 240 | 20784.0 | 0.2 | 4.4 | 126.7 | 1.0 | 34.1 | 0.1 | 0.0 | 166.6 | 169.1 | 169.5 | 169.8 | 166.6 | -| 16 | 248 | 26352.0 | 0.3 | 3.7 | 107.7 | 1.1 | 32.3 | 0.1 | 0.0 | 146.9 | 149.2 | 163.2 | 169.4 | 145.3 | -| 16 | 256 | 23408.0 | 0.4 | 4.9 | 116.1 | 1.1 | 42.3 | 0.1 | 0.0 | 163.0 | 197.6 | 201.1 | 204.3 | 164.9 | - -
- - - - -#### Online: NVIDIA A30, PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 5528.0 | 0.1 | 0.8 | 8.1 | 0.5 | 13.1 | 0.3 | 0.0 | 26.2 | 28.1 | 28.7 | 30.3 | 22.8 | -| 16 | 16 | 9120.0 | 0.1 | 0.6 | 10.3 | 0.7 | 10.5 | 5.3 | 0.0 | 30.8 | 33.5 | 34.7 | 35.8 | 27.5 | -| 16 | 24 | 10384.0 | 0.1 | 0.8 | 14.0 | 1.1 | 10.6 | 9.3 | 0.0 | 39.3 | 42.4 | 43.1 | 46.0 | 35.8 | -| 16 | 32 | 11076.9 | 0.1 | 1.2 | 18.8 | 1.4 | 10.2 | 13.2 | 0.0 | 48.5 | 51.1 | 51.5 | 54.6 | 44.9 | -| 16 | 40 | 11328.0 | 0.1 | 2.0 | 21.6 | 2.3 | 10.7 | 18.4 | 0.0 | 58.8 | 62.0 | 63.2 | 67.5 | 55.1 | -| 16 | 48 | 11296.0 | 0.1 | 3.2 | 25.3 | 5.1 | 9.3 | 22.1 | 0.0 | 67.7 | 73.3 | 76.0 | 79.1 | 65.1 | -| 16 | 56 | 11440.0 | 0.1 | 3.3 | 29.6 | 5.0 | 9.9 | 26.1 | 0.0 | 77.3 | 82.5 | 83.9 | 92.3 | 74.0 | -| 16 | 64 | 11600.0 | 0.1 | 2.9 | 35.5 | 7.6 | 9.3 | 29.0 | 0.0 | 88.5 | 95.2 | 98.9 | 113.5 | 84.4 | -| 16 | 72 | 11316.7 | 0.1 | 4.3 | 38.1 | 16.0 | 7.7 | 29.3 | 0.0 | 99.4 | 103.1 | 123.0 | 125.8 | 95.5 | -| 16 | 80 | 11664.0 | 0.1 | 4.0 | 46.0 | 18.0 | 7.5 | 28.0 | 0.0 | 108.4 | 112.7 | 116.1 | 126.0 | 103.7 | -| 16 | 88 | 11472.0 | 0.1 | 3.0 | 47.8 | 19.8 | 8.2 | 34.4 | 0.0 | 119.7 | 128.6 | 131.9 | 135.5 | 113.3 | -| 16 | 96 | 11760.0 | 0.1 | 4.4 | 53.1 | 22.1 | 7.3 | 36.1 | 0.0 | 128.7 | 131.5 | 132.1 | 133.3 | 123.1 | -| 16 | 104 | 11840.0 | 0.1 | 5.4 | 59.4 | 5.7 | 9.8 | 51.0 | 0.0 | 132.7 | 138.7 | 138.9 | 175.8 | 131.5 | -| 16 | 112 | 11728.0 | 0.1 | 4.2 | 59.1 | 16.9 | 8.8 | 51.3 | 0.0 | 146.7 | 162.7 | 164.0 | 168.4 | 140.3 | -| 16 | 120 | 11796.2 | 0.1 | 5.3 | 54.2 | 20.6 | 7.6 | 61.4 | 0.0 | 155.3 | 164.2 | 172.6 | 173.1 | 149.2 | -| 16 | 128 | 12272.0 | 0.1 | 6.3 | 64.6 | 16.7 | 7.6 | 61.5 | 0.0 | 165.7 | 175.9 | 194.4 | 197.7 | 156.8 | -| 16 | 136 | 11680.0 | 0.1 | 6.0 | 74.7 | 33.5 | 6.6 | 48.7 | 0.0 | 178.5 | 183.0 | 183.9 | 186.4 | 169.5 | -| 16 | 144 | 11408.0 | 0.1 | 5.5 | 76.6 | 33.3 | 7.1 | 55.4 | 0.0 | 190.7 | 198.8 | 203.2 | 204.6 | 178.0 | -| 16 | 152 | 11456.0 | 0.1 | 4.7 | 87.4 | 28.8 | 7.2 | 60.8 | 0.0 | 193.9 | 199.5 | 200.2 | 201.1 | 189.0 | -| 16 | 160 | 11444.6 | 0.2 | 4.7 | 94.3 | 24.3 | 7.0 | 67.1 | 0.0 | 198.0 | 199.4 | 199.5 | 199.6 | 197.5 | -| 16 | 168 | 11040.0 | 0.1 | 7.5 | 89.1 | 35.2 | 6.8 | 70.2 | 0.0 | 214.2 | 220.1 | 222.9 | 225.2 | 208.9 | -| 16 | 176 | 11536.0 | 0.2 | 4.7 | 97.1 | 39.1 | 7.0 | 67.9 | 0.0 | 221.9 | 239.7 | 242.6 | 255.8 | 216.0 | -| 16 | 184 | 11136.0 | 0.1 | 6.5 | 101.3 | 41.8 | 7.1 | 67.2 | 0.0 | 231.3 | 236.7 | 240.0 | 240.4 | 224.1 | -| 16 | 192 | 11376.0 | 0.2 | 6.4 | 106.9 | 47.0 | 7.6 | 68.9 | 0.0 | 245.5 | 252.9 | 256.1 | 265.9 | 237.1 | -| 16 | 200 | 11840.0 | 0.3 | 5.0 | 110.3 | 46.4 | 7.0 | 72.7 | 0.0 | 255.0 | 262.0 | 267.0 | 267.9 | 241.8 | -| 16 | 208 | 11680.0 | 0.2 | 5.3 | 122.0 | 37.8 | 7.6 | 78.0 | 0.0 | 252.1 | 254.0 | 309.6 | 311.0 | 250.9 | -| 16 | 216 | 11280.0 | 0.2 | 6.0 | 151.5 | 41.8 | 6.9 | 59.4 | 0.0 | 270.5 | 279.9 | 283.2 | 283.9 | 265.8 | -| 16 | 224 | 11152.0 | 0.4 | 5.9 | 127.1 | 51.8 | 7.0 | 79.1 | 0.0 | 280.9 | 283.7 | 284.6 | 285.1 | 271.3 | -| 16 | 232 | 10848.0 | 0.2 | 5.0 | 158.1 | 41.7 | 7.8 | 72.7 | 0.0 | 287.4 | 306.0 | 315.8 | 316.9 | 285.5 | -| 16 | 240 | 11088.0 | 0.2 | 10.1 | 166.0 | 34.4 | 7.2 | 78.0 | 0.0 | 296.1 | 318.6 | 348.7 | 354.4 | 295.8 | -| 16 | 248 | 10485.5 | 0.3 | 5.8 | 174.3 | 40.1 | 7.2 | 75.4 | 0.0 | 307.6 | 316.7 | 322.0 | 323.7 | 303.2 | -| 16 | 256 | 11168.0 | 0.4 | 4.5 | 178.3 | 45.8 | 7.1 | 77.2 | 0.0 | 320.5 | 341.6 | 342.6 | 348.6 | 313.2 | - -
- - - - -#### Online: NVIDIA A30, PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA A30 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 6544.0 | 0.1 | 0.5 | 7.0 | 0.4 | 8.8 | 2.6 | 0.0 | 22.1 | 23.9 | 24.5 | 25.8 | 19.3 | -| 16 | 16 | 9456.0 | 0.1 | 0.6 | 9.7 | 0.8 | 8.7 | 6.9 | 0.0 | 30.5 | 32.8 | 33.4 | 34.2 | 26.6 | -| 16 | 24 | 10704.0 | 0.1 | 0.8 | 13.8 | 0.9 | 8.5 | 11.3 | 0.0 | 39.0 | 41.9 | 42.2 | 42.7 | 35.4 | -| 16 | 32 | 11472.0 | 0.1 | 0.9 | 18.3 | 1.3 | 8.4 | 15.0 | 0.0 | 48.1 | 50.2 | 51.1 | 51.9 | 44.0 | -| 16 | 40 | 11568.0 | 0.1 | 1.3 | 21.8 | 1.5 | 8.6 | 20.1 | 0.0 | 57.7 | 60.4 | 60.8 | 62.3 | 53.4 | -| 16 | 48 | 12000.0 | 0.1 | 2.8 | 24.6 | 1.3 | 8.7 | 25.6 | 0.0 | 66.3 | 68.3 | 68.6 | 69.3 | 63.1 | -| 16 | 56 | 12048.0 | 0.1 | 3.1 | 20.9 | 1.6 | 8.3 | 37.6 | 0.0 | 75.2 | 77.2 | 77.9 | 78.8 | 71.5 | -| 16 | 64 | 11824.0 | 0.1 | 2.8 | 29.1 | 1.8 | 8.5 | 38.8 | 0.0 | 85.2 | 87.8 | 88.4 | 89.3 | 81.0 | -| 16 | 72 | 11888.0 | 0.1 | 2.2 | 36.1 | 2.0 | 8.8 | 40.8 | 0.0 | 93.9 | 96.0 | 96.5 | 101.8 | 90.0 | -| 16 | 80 | 11712.0 | 0.1 | 3.7 | 44.4 | 10.6 | 8.1 | 36.3 | 0.0 | 107.1 | 119.0 | 121.6 | 128.2 | 103.3 | -| 16 | 88 | 12240.0 | 0.1 | 4.5 | 44.7 | 5.7 | 7.9 | 48.6 | 0.0 | 115.8 | 119.8 | 130.2 | 153.3 | 111.5 | -| 16 | 96 | 11888.0 | 0.1 | 3.0 | 48.8 | 10.6 | 7.8 | 50.0 | 0.0 | 127.1 | 135.0 | 152.9 | 179.4 | 120.3 | -| 16 | 104 | 12096.0 | 0.1 | 3.4 | 59.4 | 10.2 | 7.4 | 48.6 | 0.0 | 134.8 | 139.1 | 146.7 | 158.2 | 129.1 | -| 16 | 112 | 11408.0 | 0.1 | 5.3 | 57.8 | 27.2 | 5.8 | 46.0 | 0.0 | 146.4 | 147.8 | 149.7 | 155.4 | 142.2 | -| 16 | 120 | 11812.2 | 0.1 | 6.7 | 63.8 | 14.0 | 6.8 | 57.3 | 0.0 | 153.3 | 157.9 | 160.4 | 161.9 | 148.7 | -| 16 | 128 | 11632.0 | 0.1 | 4.9 | 69.6 | 15.9 | 7.3 | 59.2 | 0.0 | 163.6 | 177.1 | 180.0 | 205.3 | 157.0 | -| 16 | 136 | 11620.4 | 0.1 | 3.5 | 76.0 | 9.8 | 8.2 | 68.3 | 0.0 | 172.9 | 182.9 | 195.5 | 196.8 | 166.0 | -| 16 | 144 | 11824.0 | 0.1 | 3.3 | 81.3 | 24.9 | 7.0 | 60.9 | 0.0 | 181.9 | 187.9 | 210.9 | 211.8 | 177.5 | -| 16 | 152 | 12032.0 | 0.1 | 3.8 | 85.9 | 22.9 | 7.1 | 67.1 | 0.0 | 192.9 | 219.2 | 239.1 | 252.4 | 187.0 | -| 16 | 160 | 12048.0 | 0.1 | 4.0 | 89.0 | 21.3 | 6.5 | 72.7 | 0.0 | 199.7 | 206.4 | 230.8 | 246.6 | 193.7 | -| 16 | 168 | 11456.0 | 0.1 | 4.4 | 93.2 | 30.2 | 5.7 | 70.5 | 0.0 | 208.4 | 209.8 | 211.8 | 212.0 | 204.3 | -| 16 | 176 | 11584.0 | 0.2 | 5.7 | 100.5 | 38.5 | 6.5 | 64.0 | 0.0 | 219.8 | 221.4 | 222.1 | 223.7 | 215.4 | -| 16 | 184 | 12096.0 | 0.2 | 5.6 | 103.2 | 40.9 | 6.0 | 69.2 | 0.0 | 230.2 | 233.5 | 233.8 | 233.9 | 225.0 | -| 16 | 192 | 11200.0 | 0.2 | 6.2 | 107.5 | 35.4 | 6.5 | 79.3 | 0.0 | 241.6 | 251.3 | 254.8 | 255.0 | 235.0 | -| 16 | 200 | 10880.0 | 0.3 | 5.0 | 113.9 | 31.7 | 7.0 | 88.9 | 0.0 | 255.2 | 267.0 | 294.9 | 296.2 | 246.8 | -| 16 | 208 | 11984.0 | 0.1 | 6.4 | 116.5 | 45.0 | 6.2 | 78.1 | 0.0 | 261.3 | 267.0 | 268.0 | 268.4 | 252.3 | -| 16 | 216 | 11632.0 | 0.2 | 6.9 | 121.8 | 39.8 | 6.8 | 90.8 | 0.0 | 275.9 | 280.9 | 282.2 | 282.5 | 266.4 | -| 16 | 224 | 11140.9 | 0.3 | 6.6 | 128.6 | 49.4 | 6.8 | 84.3 | 0.0 | 284.0 | 288.6 | 294.6 | 295.2 | 275.8 | -| 16 | 232 | 11568.0 | 0.2 | 5.2 | 162.0 | 15.2 | 8.1 | 89.0 | 0.0 | 285.6 | 312.9 | 315.5 | 335.5 | 279.7 | -| 16 | 240 | 11696.0 | 0.3 | 5.3 | 167.3 | 40.9 | 6.2 | 75.4 | 0.0 | 300.4 | 309.2 | 317.6 | 318.4 | 295.3 | -| 16 | 248 | 11040.0 | 0.2 | 8.0 | 174.9 | 32.4 | 7.1 | 82.8 | 0.0 | 307.4 | 327.0 | 370.7 | 371.9 | 305.6 | -| 16 | 256 | 10528.0 | 0.5 | 4.0 | 179.5 | 42.6 | 6.8 | 80.8 | 0.0 | 321.4 | 325.7 | 326.0 | 327.2 | 314.2 | - -
- - - - -#### Online: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 11776.0 | 0.1 | 0.5 | 4.7 | 0.2 | 5.3 | 0.0 | 0.0 | 10.8 | 10.9 | 11.0 | 11.0 | 10.7 | -| 16 | 16 | 11360.0 | 0.1 | 0.7 | 11.7 | 0.2 | 9.4 | 0.0 | 0.0 | 23.1 | 28.6 | 32.0 | 32.2 | 22.1 | -| 16 | 24 | 12656.0 | 0.1 | 1.0 | 15.8 | 0.3 | 12.8 | 0.0 | 0.0 | 33.8 | 34.3 | 34.4 | 37.7 | 30.1 | -| 16 | 32 | 11968.0 | 0.1 | 1.6 | 20.9 | 0.4 | 18.8 | 0.0 | 0.0 | 44.2 | 48.0 | 48.1 | 48.7 | 41.8 | -| 16 | 40 | 14640.0 | 0.1 | 1.5 | 20.9 | 0.4 | 19.6 | 0.0 | 0.0 | 47.6 | 48.0 | 48.0 | 48.1 | 42.6 | -| 16 | 48 | 13280.0 | 0.1 | 1.6 | 32.8 | 0.4 | 21.3 | 0.0 | 0.0 | 62.9 | 63.4 | 63.5 | 63.6 | 56.3 | -| 16 | 56 | 13232.0 | 0.1 | 1.9 | 28.4 | 0.6 | 33.8 | 0.0 | 0.0 | 66.9 | 71.8 | 72.2 | 72.3 | 64.8 | -| 16 | 64 | 12656.0 | 0.1 | 1.9 | 42.4 | 0.6 | 32.3 | 0.0 | 0.0 | 82.2 | 83.0 | 83.6 | 83.8 | 77.3 | -| 16 | 72 | 16671.3 | 0.1 | 2.0 | 40.8 | 0.5 | 24.0 | 0.0 | 0.0 | 73.4 | 74.0 | 83.6 | 84.0 | 67.5 | -| 16 | 80 | 16384.0 | 0.1 | 2.1 | 36.3 | 0.6 | 34.6 | 0.1 | 0.0 | 76.8 | 77.3 | 77.4 | 77.6 | 73.7 | -| 16 | 88 | 13728.0 | 0.1 | 2.3 | 53.4 | 0.6 | 38.5 | 0.0 | 0.0 | 100.5 | 101.3 | 101.5 | 101.7 | 95.0 | -| 16 | 96 | 15104.0 | 0.1 | 3.0 | 53.7 | 0.7 | 39.6 | 0.1 | 0.0 | 101.2 | 101.8 | 102.0 | 102.2 | 97.1 | -| 16 | 104 | 14512.0 | 0.1 | 2.0 | 66.6 | 0.7 | 38.5 | 0.1 | 0.0 | 111.1 | 111.5 | 111.7 | 111.9 | 107.9 | -| 16 | 112 | 18464.0 | 0.1 | 3.0 | 49.7 | 1.0 | 40.8 | 0.1 | 0.0 | 96.6 | 101.7 | 101.9 | 102.2 | 94.7 | -| 16 | 120 | 17760.0 | 0.1 | 2.9 | 63.4 | 1.2 | 37.7 | 0.1 | 0.0 | 112.1 | 113.4 | 113.8 | 113.9 | 105.4 | -| 16 | 128 | 17808.0 | 0.1 | 3.9 | 64.6 | 0.9 | 39.5 | 0.1 | 0.0 | 111.7 | 112.3 | 112.5 | 112.5 | 109.0 | -| 16 | 136 | 16848.0 | 0.1 | 2.7 | 74.9 | 0.8 | 41.1 | 0.1 | 0.0 | 129.9 | 130.6 | 130.7 | 130.7 | 119.7 | -| 16 | 144 | 19216.0 | 0.1 | 3.7 | 66.2 | 1.0 | 38.9 | 0.1 | 0.0 | 112.5 | 113.3 | 113.5 | 114.1 | 110.1 | -| 16 | 152 | 20864.0 | 0.1 | 4.3 | 65.4 | 1.0 | 39.1 | 0.2 | 0.0 | 112.3 | 113.4 | 113.7 | 114.9 | 110.2 | -| 16 | 160 | 18288.0 | 0.1 | 3.8 | 81.3 | 1.2 | 42.7 | 0.1 | 0.0 | 131.4 | 133.1 | 134.3 | 135.1 | 129.2 | -| 16 | 168 | 19152.0 | 0.2 | 3.1 | 81.6 | 1.1 | 42.6 | 0.1 | 0.0 | 131.2 | 131.6 | 131.7 | 131.8 | 128.7 | -| 16 | 176 | 15152.0 | 0.2 | 2.5 | 127.3 | 0.9 | 42.8 | 0.1 | 0.0 | 174.9 | 175.3 | 175.4 | 175.4 | 173.9 | -| 16 | 184 | 15824.0 | 0.1 | 3.9 | 126.7 | 1.0 | 42.8 | 0.1 | 0.0 | 175.5 | 176.1 | 176.3 | 176.4 | 174.6 | -| 16 | 192 | 18096.0 | 0.2 | 3.0 | 113.1 | 1.0 | 40.2 | 0.1 | 0.0 | 155.7 | 174.7 | 174.9 | 175.0 | 157.6 | -| 16 | 200 | 18128.0 | 0.2 | 3.1 | 121.0 | 1.1 | 39.1 | 0.1 | 0.0 | 165.0 | 165.9 | 166.2 | 166.6 | 164.7 | -| 16 | 208 | 16720.0 | 0.3 | 3.1 | 127.9 | 1.2 | 42.9 | 0.2 | 0.0 | 176.3 | 178.0 | 178.9 | 179.2 | 175.5 | -| 16 | 216 | 18221.8 | 0.4 | 2.4 | 127.4 | 1.1 | 42.6 | 0.1 | 0.0 | 174.9 | 175.2 | 175.3 | 175.4 | 174.0 | -| 16 | 224 | 18944.0 | 0.3 | 3.1 | 127.4 | 1.1 | 42.8 | 0.1 | 0.0 | 175.8 | 176.3 | 176.4 | 176.5 | 174.9 | -| 16 | 232 | 19484.5 | 0.4 | 3.3 | 126.9 | 1.2 | 42.7 | 0.1 | 0.0 | 175.2 | 176.5 | 176.8 | 177.2 | 174.7 | -| 16 | 240 | 17696.0 | 0.5 | 2.1 | 147.7 | 1.2 | 40.8 | 0.1 | 0.0 | 199.8 | 200.7 | 200.8 | 201.1 | 192.3 | -| 16 | 248 | 17856.0 | 0.5 | 3.0 | 150.1 | 1.1 | 41.3 | 0.1 | 0.0 | 199.8 | 201.0 | 201.2 | 201.5 | 196.1 | -| 16 | 256 | 17712.0 | 0.6 | 2.6 | 155.2 | 1.2 | 41.4 | 0.2 | 0.0 | 201.5 | 202.3 | 202.6 | 202.7 | 201.2 | - -
- - - - -#### Online: NVIDIA DGX-1 (1x V100 32GB), NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 12083.9 | 0.1 | 0.4 | 4.6 | 0.2 | 5.1 | 0.0 | 0.0 | 10.5 | 10.7 | 10.7 | 10.8 | 10.5 | -| 16 | 16 | 11248.0 | 0.1 | 0.7 | 11.3 | 0.2 | 10.1 | 0.0 | 0.0 | 23.6 | 28.8 | 32.4 | 32.7 | 22.5 | -| 16 | 24 | 12048.0 | 0.1 | 0.8 | 15.3 | 0.3 | 14.0 | 0.0 | 0.0 | 32.5 | 38.9 | 42.4 | 42.7 | 30.6 | -| 16 | 32 | 13808.0 | 0.1 | 1.0 | 14.8 | 0.3 | 19.3 | 0.1 | 0.0 | 38.6 | 42.5 | 42.6 | 44.0 | 35.5 | -| 16 | 40 | 14160.0 | 0.1 | 1.8 | 22.2 | 0.4 | 19.7 | 0.0 | 0.0 | 44.3 | 53.9 | 54.1 | 57.7 | 44.1 | -| 16 | 48 | 13664.0 | 0.1 | 2.1 | 25.4 | 0.6 | 27.1 | 0.0 | 0.0 | 58.5 | 67.6 | 68.2 | 68.3 | 55.3 | -| 16 | 56 | 14624.0 | 0.1 | 1.4 | 34.6 | 0.5 | 22.1 | 0.0 | 0.0 | 63.5 | 63.8 | 63.8 | 74.0 | 58.8 | -| 16 | 64 | 18784.0 | 0.1 | 1.7 | 27.6 | 0.5 | 22.9 | 0.0 | 0.0 | 53.9 | 58.2 | 58.5 | 63.6 | 52.7 | -| 16 | 72 | 15584.0 | 0.1 | 2.8 | 33.5 | 0.6 | 34.3 | 0.0 | 0.0 | 76.2 | 77.3 | 77.4 | 77.6 | 71.3 | -| 16 | 80 | 14000.0 | 0.1 | 2.2 | 52.8 | 0.6 | 32.8 | 0.0 | 0.0 | 91.7 | 92.7 | 92.8 | 92.8 | 88.4 | -| 16 | 88 | 13760.0 | 0.1 | 2.4 | 55.0 | 0.6 | 38.9 | 0.1 | 0.0 | 100.5 | 101.6 | 101.7 | 102.0 | 96.9 | -| 16 | 96 | 18864.0 | 0.1 | 2.8 | 41.3 | 0.8 | 33.8 | 0.1 | 0.0 | 82.1 | 83.0 | 83.3 | 83.4 | 78.8 | -| 16 | 104 | 18000.0 | 0.1 | 3.0 | 52.9 | 0.7 | 32.7 | 0.1 | 0.0 | 91.9 | 92.8 | 92.9 | 93.0 | 89.4 | -| 16 | 112 | 16896.0 | 0.1 | 3.3 | 56.5 | 0.9 | 39.1 | 0.1 | 0.0 | 102.0 | 103.7 | 111.8 | 112.4 | 100.0 | -| 16 | 120 | 20144.0 | 0.1 | 3.2 | 52.5 | 0.8 | 33.6 | 0.1 | 0.0 | 92.7 | 93.7 | 93.8 | 93.9 | 90.3 | -| 16 | 128 | 19024.0 | 0.1 | 2.9 | 55.0 | 1.0 | 40.4 | 0.1 | 0.0 | 101.8 | 102.9 | 103.1 | 103.2 | 99.5 | -| 16 | 136 | 20560.0 | 0.1 | 3.8 | 55.1 | 1.0 | 39.4 | 0.1 | 0.0 | 101.8 | 102.9 | 103.0 | 103.2 | 99.5 | -| 16 | 144 | 17264.0 | 0.2 | 2.7 | 81.1 | 1.0 | 42.5 | 0.1 | 0.0 | 130.5 | 131.2 | 131.3 | 131.7 | 127.6 | -| 16 | 152 | 18352.0 | 0.2 | 2.8 | 82.8 | 0.9 | 37.6 | 0.1 | 0.0 | 125.2 | 125.5 | 125.6 | 125.7 | 124.4 | -| 16 | 160 | 16016.0 | 0.1 | 1.0 | 99.0 | 0.8 | 37.6 | 0.1 | 0.0 | 135.9 | 154.3 | 154.3 | 154.4 | 138.7 | -| 16 | 168 | 19200.0 | 0.1 | 3.7 | 81.0 | 1.1 | 42.6 | 0.2 | 0.0 | 131.1 | 132.0 | 132.2 | 132.3 | 128.7 | -| 16 | 176 | 16480.0 | 0.1 | 2.5 | 112.7 | 0.9 | 40.8 | 0.1 | 0.0 | 156.3 | 174.0 | 174.2 | 174.3 | 157.1 | -| 16 | 184 | 16528.0 | 0.2 | 4.1 | 120.3 | 1.0 | 41.3 | 0.1 | 0.0 | 174.3 | 174.9 | 175.1 | 175.6 | 167.1 | -| 16 | 192 | 18512.0 | 0.3 | 2.3 | 109.9 | 1.1 | 40.8 | 0.1 | 0.0 | 156.5 | 158.0 | 158.5 | 158.7 | 154.6 | -| 16 | 200 | 16735.3 | 0.2 | 3.0 | 126.4 | 1.0 | 42.7 | 0.1 | 0.0 | 174.2 | 174.9 | 175.1 | 175.2 | 173.5 | -| 16 | 208 | 17584.0 | 0.3 | 2.9 | 126.9 | 1.1 | 42.5 | 0.1 | 0.0 | 175.0 | 175.4 | 175.5 | 176.0 | 173.9 | -| 16 | 216 | 18301.7 | 0.4 | 2.6 | 127.2 | 1.1 | 42.5 | 0.1 | 0.0 | 174.8 | 175.1 | 175.2 | 175.4 | 174.0 | -| 16 | 224 | 19952.0 | 0.4 | 2.6 | 127.2 | 1.1 | 39.1 | 0.1 | 0.0 | 170.7 | 172.2 | 172.5 | 173.2 | 170.6 | -| 16 | 232 | 19536.0 | 0.5 | 2.6 | 127.0 | 1.2 | 42.5 | 0.1 | 0.0 | 174.8 | 175.4 | 175.5 | 175.7 | 173.9 | -| 16 | 240 | 18592.0 | 0.4 | 2.9 | 144.2 | 1.3 | 41.5 | 0.1 | 0.0 | 190.5 | 191.6 | 191.8 | 192.1 | 190.3 | -| 16 | 248 | 17952.0 | 0.3 | 3.3 | 154.6 | 1.1 | 40.2 | 0.1 | 0.0 | 200.4 | 201.1 | 201.4 | 202.0 | 199.8 | -| 16 | 256 | 19616.0 | 0.5 | 2.8 | 144.7 | 1.3 | 41.3 | 0.1 | 0.0 | 190.8 | 192.4 | 192.6 | 193.2 | 190.6 | - -
- - - - -#### Online: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 5008.0 | 0.1 | 0.6 | 9.4 | 0.4 | 11.3 | 3.7 | 0.0 | 29.2 | 30.5 | 31.3 | 32.9 | 25.5 | -| 16 | 16 | 7016.0 | 0.1 | 0.7 | 13.5 | 0.8 | 11.7 | 8.9 | 0.0 | 41.2 | 42.9 | 43.4 | 44.2 | 35.7 | -| 16 | 24 | 8560.0 | 0.1 | 1.0 | 17.5 | 1.0 | 11.9 | 12.7 | 0.0 | 49.4 | 51.3 | 51.9 | 53.1 | 44.2 | -| 16 | 32 | 9264.0 | 0.1 | 1.1 | 21.4 | 1.4 | 11.9 | 17.0 | 0.0 | 57.9 | 59.1 | 59.3 | 59.6 | 52.9 | -| 16 | 40 | 10336.0 | 0.1 | 1.9 | 23.2 | 1.5 | 12.0 | 22.3 | 0.0 | 65.8 | 67.6 | 67.9 | 68.2 | 60.9 | -| 16 | 48 | 10064.0 | 0.1 | 2.6 | 22.0 | 1.7 | 11.8 | 32.6 | 0.0 | 75.7 | 76.6 | 76.7 | 77.4 | 70.8 | -| 16 | 56 | 10512.0 | 0.1 | 2.5 | 20.1 | 1.8 | 11.6 | 44.8 | 0.0 | 85.6 | 86.8 | 87.8 | 88.0 | 80.9 | -| 16 | 64 | 10848.0 | 0.1 | 3.1 | 30.1 | 1.9 | 11.7 | 42.2 | 0.0 | 93.8 | 95.9 | 96.0 | 99.7 | 89.2 | -| 16 | 72 | 10800.0 | 0.1 | 2.9 | 22.0 | 2.0 | 11.3 | 61.7 | 0.0 | 104.0 | 104.8 | 105.6 | 107.4 | 99.8 | -| 16 | 80 | 10976.0 | 0.1 | 2.8 | 38.7 | 2.2 | 11.3 | 52.2 | 0.0 | 111.6 | 112.5 | 113.3 | 116.0 | 107.3 | -| 16 | 88 | 11200.0 | 0.1 | 3.4 | 47.7 | 3.1 | 11.7 | 50.9 | 0.0 | 120.7 | 122.2 | 124.2 | 124.7 | 116.8 | -| 16 | 96 | 11152.0 | 0.1 | 2.8 | 54.7 | 3.3 | 11.0 | 54.2 | 0.0 | 130.4 | 132.2 | 133.0 | 133.9 | 126.1 | -| 16 | 104 | 11312.0 | 0.1 | 4.2 | 60.6 | 7.2 | 12.2 | 51.5 | 0.0 | 138.5 | 144.9 | 161.8 | 173.3 | 135.8 | -| 16 | 112 | 11216.0 | 0.1 | 4.6 | 67.1 | 3.2 | 10.5 | 60.7 | 0.0 | 150.1 | 151.5 | 152.3 | 154.1 | 146.2 | -| 16 | 120 | 10736.0 | 0.1 | 4.6 | 73.0 | 10.8 | 10.3 | 58.1 | 0.0 | 161.5 | 162.4 | 166.4 | 173.6 | 157.0 | -| 16 | 128 | 11504.0 | 0.1 | 3.5 | 77.2 | 7.0 | 9.8 | 66.2 | 0.0 | 168.8 | 171.6 | 172.7 | 186.1 | 163.8 | -| 16 | 136 | 11120.0 | 0.1 | 4.5 | 81.4 | 8.8 | 10.3 | 68.5 | 0.0 | 177.7 | 179.5 | 181.3 | 191.2 | 173.5 | -| 16 | 144 | 11808.0 | 0.1 | 4.7 | 84.3 | 8.4 | 10.7 | 73.0 | 0.0 | 185.0 | 193.4 | 196.4 | 202.1 | 181.2 | -| 16 | 152 | 11168.0 | 0.1 | 3.7 | 91.8 | 28.3 | 8.6 | 63.1 | 0.0 | 199.6 | 203.2 | 203.3 | 209.8 | 195.7 | -| 16 | 160 | 11392.0 | 0.1 | 5.2 | 84.7 | 21.9 | 9.6 | 81.9 | 0.0 | 205.7 | 220.0 | 248.4 | 248.8 | 203.4 | -| 16 | 168 | 11696.0 | 0.1 | 4.9 | 103.6 | 10.9 | 10.1 | 82.6 | 0.0 | 216.4 | 224.8 | 269.6 | 270.7 | 212.1 | -| 16 | 176 | 10912.0 | 0.1 | 5.9 | 105.3 | 30.6 | 9.9 | 73.6 | 0.0 | 230.7 | 235.1 | 235.4 | 235.7 | 225.3 | -| 16 | 184 | 11312.0 | 0.2 | 4.2 | 110.4 | 28.5 | 9.5 | 82.6 | 0.0 | 239.8 | 248.2 | 271.9 | 272.2 | 235.3 | -| 16 | 192 | 10992.0 | 0.1 | 5.4 | 113.3 | 43.4 | 8.6 | 70.0 | 0.0 | 246.1 | 248.0 | 248.3 | 248.8 | 241.0 | -| 16 | 200 | 11360.0 | 0.1 | 5.8 | 116.5 | 36.6 | 9.9 | 77.5 | 0.0 | 251.4 | 259.3 | 272.8 | 273.2 | 246.4 | -| 16 | 208 | 11360.0 | 0.1 | 6.1 | 122.2 | 43.4 | 8.5 | 77.2 | 0.0 | 259.1 | 263.0 | 265.2 | 265.9 | 257.6 | -| 16 | 216 | 11296.0 | 0.3 | 3.3 | 129.2 | 37.6 | 8.7 | 88.9 | 0.0 | 272.2 | 275.7 | 275.9 | 276.3 | 267.9 | -| 16 | 224 | 10800.0 | 0.2 | 5.2 | 132.7 | 43.4 | 8.3 | 86.3 | 0.0 | 277.4 | 281.9 | 282.2 | 282.9 | 276.1 | -| 16 | 232 | 11184.0 | 0.4 | 3.2 | 170.0 | 12.8 | 10.5 | 91.9 | 0.0 | 276.9 | 334.5 | 335.1 | 335.5 | 288.8 | -| 16 | 240 | 10992.0 | 0.4 | 6.2 | 175.9 | 27.0 | 9.4 | 84.9 | 0.0 | 301.9 | 342.6 | 348.0 | 348.2 | 303.8 | -| 16 | 248 | 10432.0 | 0.4 | 3.8 | 179.2 | 12.9 | 10.8 | 98.1 | 0.0 | 314.7 | 356.4 | 376.4 | 377.8 | 305.2 | -| 16 | 256 | 10896.0 | 0.5 | 3.7 | 185.5 | 38.1 | 8.6 | 83.4 | 0.0 | 323.5 | 329.8 | 332.4 | 332.7 | 319.6 | - -
- - - - -#### Online: NVIDIA DGX-1 (1x V100 32GB), PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX-1 (1x V100 32GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 4992.0 | 0.1 | 0.6 | 9.5 | 0.4 | 11.2 | 3.6 | 0.0 | 28.9 | 29.9 | 30.2 | 32.2 | 25.3 | -| 16 | 16 | 7192.0 | 0.1 | 0.7 | 12.8 | 0.9 | 11.8 | 8.9 | 0.0 | 41.1 | 43.1 | 43.5 | 44.2 | 35.2 | -| 16 | 24 | 8496.0 | 0.1 | 0.9 | 16.1 | 1.1 | 11.7 | 13.7 | 0.0 | 49.2 | 51.3 | 52.5 | 53.4 | 43.6 | -| 16 | 32 | 9264.0 | 0.1 | 1.1 | 19.2 | 1.8 | 13.1 | 17.0 | 0.0 | 57.4 | 58.9 | 59.0 | 60.7 | 52.2 | -| 16 | 40 | 9808.0 | 0.1 | 1.4 | 21.5 | 1.8 | 13.1 | 23.5 | 0.0 | 66.0 | 66.4 | 66.5 | 66.6 | 61.4 | -| 16 | 48 | 10528.0 | 0.1 | 3.2 | 18.6 | 1.6 | 11.6 | 36.3 | 0.0 | 75.6 | 77.1 | 78.3 | 78.6 | 71.3 | -| 16 | 56 | 10480.0 | 0.1 | 2.9 | 20.1 | 1.7 | 11.5 | 44.5 | 0.0 | 85.7 | 86.5 | 86.6 | 87.4 | 80.8 | -| 16 | 64 | 10352.0 | 0.1 | 2.7 | 21.9 | 2.0 | 11.3 | 51.6 | 0.0 | 94.4 | 95.7 | 96.5 | 97.0 | 89.6 | -| 16 | 72 | 10864.0 | 0.1 | 3.3 | 24.1 | 2.2 | 11.6 | 58.0 | 0.0 | 103.6 | 105.6 | 106.1 | 107.1 | 99.4 | -| 16 | 80 | 10992.0 | 0.1 | 2.7 | 35.9 | 2.3 | 11.2 | 54.2 | 0.0 | 111.0 | 111.9 | 112.8 | 115.5 | 106.3 | -| 16 | 88 | 11648.0 | 0.1 | 3.1 | 46.1 | 2.3 | 11.4 | 53.5 | 0.0 | 120.3 | 121.4 | 122.1 | 125.9 | 116.5 | -| 16 | 96 | 11140.9 | 0.1 | 3.7 | 55.3 | 2.6 | 11.3 | 52.6 | 0.0 | 129.6 | 131.3 | 133.1 | 138.9 | 125.6 | -| 16 | 104 | 11280.0 | 0.1 | 3.2 | 61.2 | 3.1 | 10.5 | 57.0 | 0.0 | 138.8 | 140.7 | 140.7 | 144.1 | 135.1 | -| 16 | 112 | 11824.0 | 0.1 | 3.9 | 65.2 | 3.6 | 11.0 | 60.1 | 0.0 | 147.9 | 149.8 | 150.2 | 154.3 | 143.8 | -| 16 | 120 | 10864.0 | 0.1 | 3.6 | 71.2 | 4.6 | 11.2 | 62.9 | 0.0 | 157.6 | 158.7 | 159.4 | 166.0 | 153.5 | -| 16 | 128 | 11552.0 | 0.1 | 4.7 | 75.8 | 5.0 | 11.0 | 66.6 | 0.0 | 166.2 | 170.8 | 174.3 | 177.3 | 163.0 | -| 16 | 136 | 11152.0 | 0.1 | 5.0 | 81.2 | 12.7 | 9.5 | 66.0 | 0.0 | 177.9 | 181.8 | 187.7 | 194.7 | 174.5 | -| 16 | 144 | 11008.0 | 0.1 | 4.1 | 87.5 | 25.8 | 8.6 | 61.2 | 0.0 | 191.5 | 193.4 | 193.6 | 195.5 | 187.3 | -| 16 | 152 | 10992.0 | 0.1 | 6.1 | 89.5 | 18.9 | 9.0 | 71.5 | 0.0 | 200.3 | 207.5 | 207.7 | 208.1 | 195.1 | -| 16 | 160 | 10656.0 | 0.1 | 5.5 | 91.2 | 30.9 | 8.8 | 68.7 | 0.0 | 210.2 | 215.1 | 215.6 | 221.5 | 205.3 | -| 16 | 168 | 11024.0 | 0.1 | 4.8 | 96.1 | 34.5 | 8.6 | 70.2 | 0.0 | 219.3 | 224.1 | 224.8 | 225.3 | 214.3 | -| 16 | 176 | 10864.0 | 0.1 | 4.7 | 101.8 | 36.7 | 8.4 | 70.7 | 0.0 | 227.6 | 229.0 | 229.2 | 229.3 | 222.4 | -| 16 | 184 | 10896.0 | 0.1 | 5.4 | 107.4 | 38.1 | 8.5 | 73.6 | 0.0 | 237.6 | 242.9 | 243.1 | 244.1 | 233.2 | -| 16 | 192 | 10992.0 | 0.1 | 3.2 | 115.2 | 20.8 | 10.0 | 93.2 | 0.0 | 244.9 | 257.2 | 280.7 | 280.9 | 242.5 | -| 16 | 200 | 11552.0 | 0.2 | 4.9 | 118.6 | 44.4 | 8.5 | 73.4 | 0.0 | 254.1 | 257.2 | 257.2 | 257.6 | 250.0 | -| 16 | 208 | 11236.8 | 0.2 | 1.9 | 124.8 | 21.1 | 10.8 | 101.0 | 0.0 | 263.9 | 281.4 | 287.4 | 288.0 | 259.8 | -| 16 | 216 | 11504.0 | 0.2 | 4.4 | 126.3 | 48.3 | 8.4 | 79.7 | 0.0 | 273.0 | 275.6 | 275.9 | 276.0 | 267.3 | -| 16 | 224 | 11056.0 | 0.4 | 4.7 | 131.6 | 28.3 | 9.9 | 102.3 | 0.0 | 285.1 | 290.2 | 304.5 | 304.8 | 277.3 | -| 16 | 232 | 10528.0 | 0.3 | 4.2 | 169.8 | 36.7 | 9.1 | 73.4 | 0.0 | 295.4 | 317.8 | 318.4 | 319.0 | 293.5 | -| 16 | 240 | 10485.5 | 0.2 | 4.6 | 173.9 | 38.0 | 8.4 | 76.7 | 0.0 | 302.6 | 303.9 | 304.2 | 304.7 | 301.8 | -| 16 | 248 | 11168.0 | 0.3 | 6.6 | 175.1 | 32.5 | 9.0 | 88.1 | 0.0 | 314.0 | 331.7 | 333.7 | 334.1 | 311.6 | -| 16 | 256 | 10384.0 | 0.4 | 3.3 | 184.6 | 40.0 | 8.4 | 82.2 | 0.0 | 318.6 | 321.9 | 322.1 | 322.4 | 318.8 | - -
- - - - -#### Online: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 18304.0 | 0.0 | 0.3 | 3.1 | 0.1 | 3.3 | 0.0 | 0.0 | 6.9 | 7.0 | 7.1 | 7.4 | 6.9 | -| 16 | 16 | 20448.0 | 0.0 | 0.5 | 6.6 | 0.1 | 5.2 | 0.0 | 0.0 | 12.5 | 15.5 | 15.6 | 17.1 | 12.4 | -| 16 | 24 | 24448.0 | 0.0 | 0.7 | 8.3 | 0.2 | 6.3 | 0.1 | 0.0 | 17.4 | 17.6 | 17.7 | 17.8 | 15.5 | -| 16 | 32 | 25312.0 | 0.0 | 0.8 | 10.2 | 0.2 | 8.5 | 0.1 | 0.0 | 22.8 | 24.4 | 24.7 | 24.9 | 19.8 | -| 16 | 40 | 23232.0 | 0.0 | 1.2 | 14.2 | 0.4 | 11.3 | 0.1 | 0.0 | 28.7 | 30.3 | 30.4 | 30.5 | 27.1 | -| 16 | 48 | 25296.0 | 0.0 | 1.4 | 9.1 | 0.4 | 18.6 | 0.1 | 0.0 | 31.0 | 32.7 | 32.7 | 33.0 | 29.7 | -| 16 | 56 | 26560.0 | 0.0 | 1.4 | 16.2 | 0.4 | 14.8 | 0.1 | 0.0 | 34.4 | 40.2 | 40.4 | 40.6 | 32.9 | -| 16 | 64 | 26848.0 | 0.0 | 2.0 | 16.6 | 0.4 | 17.8 | 0.1 | 0.0 | 38.6 | 39.0 | 39.1 | 39.2 | 36.9 | -| 16 | 72 | 27632.0 | 0.0 | 1.8 | 22.4 | 0.5 | 16.6 | 0.1 | 0.0 | 42.2 | 47.5 | 47.7 | 48.2 | 41.4 | -| 16 | 80 | 27808.0 | 0.0 | 1.9 | 25.7 | 0.5 | 16.9 | 0.1 | 0.0 | 47.9 | 48.2 | 48.4 | 48.8 | 45.2 | -| 16 | 88 | 29152.0 | 0.0 | 2.5 | 22.8 | 0.6 | 21.1 | 0.1 | 0.0 | 48.7 | 49.4 | 50.4 | 50.6 | 47.2 | -| 16 | 96 | 26352.0 | 0.0 | 2.0 | 33.5 | 0.6 | 20.1 | 0.2 | 0.0 | 58.2 | 58.8 | 58.9 | 59.1 | 56.5 | -| 16 | 104 | 31824.0 | 0.0 | 2.1 | 27.9 | 0.8 | 20.5 | 0.2 | 0.0 | 53.0 | 53.5 | 53.6 | 53.7 | 51.6 | -| 16 | 112 | 34992.0 | 0.0 | 3.2 | 24.8 | 0.9 | 21.8 | 0.2 | 0.0 | 51.8 | 59.5 | 61.5 | 67.9 | 50.9 | -| 16 | 120 | 34496.0 | 0.0 | 1.9 | 29.8 | 0.9 | 22.3 | 0.2 | 0.0 | 58.8 | 66.3 | 66.7 | 72.2 | 55.2 | -| 16 | 128 | 36784.0 | 0.0 | 2.7 | 30.6 | 1.1 | 20.0 | 0.2 | 0.0 | 54.4 | 59.0 | 59.1 | 59.6 | 54.5 | -| 16 | 136 | 36912.0 | 0.0 | 2.3 | 33.8 | 0.9 | 20.4 | 0.2 | 0.0 | 59.0 | 59.3 | 59.5 | 59.6 | 57.7 | -| 16 | 144 | 32672.0 | 0.1 | 2.7 | 42.2 | 1.1 | 21.9 | 0.2 | 0.0 | 69.1 | 71.4 | 72.9 | 73.8 | 68.2 | -| 16 | 152 | 36576.0 | 0.1 | 1.6 | 37.4 | 1.3 | 23.4 | 0.2 | 0.0 | 66.4 | 70.2 | 77.5 | 78.2 | 63.9 | -| 16 | 160 | 37824.0 | 0.1 | 2.2 | 42.0 | 0.9 | 20.9 | 0.2 | 0.0 | 67.1 | 72.1 | 77.5 | 81.7 | 66.3 | -| 16 | 168 | 35536.0 | 0.1 | 1.8 | 49.0 | 0.8 | 21.1 | 0.2 | 0.0 | 77.4 | 81.7 | 81.9 | 82.0 | 72.9 | -| 16 | 176 | 35488.0 | 0.1 | 2.6 | 51.3 | 0.8 | 21.5 | 0.2 | 0.0 | 81.6 | 82.2 | 82.4 | 90.9 | 76.5 | -| 16 | 184 | 33744.0 | 0.1 | 3.7 | 56.2 | 0.8 | 22.4 | 0.2 | 0.0 | 81.8 | 91.8 | 92.1 | 99.1 | 83.3 | -| 16 | 192 | 38032.0 | 0.1 | 2.4 | 51.4 | 1.1 | 22.4 | 0.2 | 0.0 | 82.5 | 83.2 | 88.0 | 92.1 | 77.7 | -| 16 | 200 | 39632.0 | 0.1 | 2.5 | 49.4 | 0.9 | 23.9 | 0.2 | 0.0 | 78.3 | 83.0 | 83.3 | 90.1 | 76.9 | -| 16 | 208 | 34400.0 | 0.1 | 2.1 | 66.7 | 1.1 | 21.9 | 0.2 | 0.0 | 92.5 | 93.1 | 93.3 | 93.5 | 92.2 | -| 16 | 216 | 31712.0 | 0.1 | 2.3 | 80.2 | 0.9 | 20.9 | 0.2 | 0.0 | 104.7 | 105.1 | 105.2 | 105.7 | 104.5 | -| 16 | 224 | 38016.0 | 0.1 | 2.4 | 65.3 | 1.2 | 21.4 | 0.2 | 0.0 | 90.2 | 93.1 | 93.2 | 93.3 | 90.7 | -| 16 | 232 | 37168.0 | 0.1 | 1.8 | 72.2 | 1.1 | 19.7 | 0.2 | 0.0 | 95.2 | 95.8 | 95.9 | 96.0 | 95.1 | -| 16 | 240 | 40832.0 | 0.1 | 2.1 | 60.9 | 0.9 | 24.6 | 0.2 | 0.0 | 87.7 | 105.3 | 108.2 | 112.9 | 88.8 | -| 16 | 248 | 38272.0 | 0.1 | 2.4 | 71.3 | 1.3 | 23.1 | 0.2 | 0.0 | 99.2 | 102.3 | 110.3 | 110.8 | 98.5 | -| 16 | 256 | 33472.0 | 0.1 | 2.4 | 90.1 | 1.1 | 21.9 | 0.2 | 0.0 | 115.9 | 116.9 | 117.4 | 117.8 | 115.9 | - -
- - - - -#### Online: NVIDIA DGX A100 (1x A100 80GB), NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 18816.0 | 0.0 | 0.2 | 3.1 | 0.1 | 3.3 | 0.0 | 0.0 | 6.8 | 6.8 | 6.9 | 6.9 | 6.8 | -| 16 | 16 | 20720.0 | 0.0 | 0.4 | 6.5 | 0.2 | 5.0 | 0.1 | 0.0 | 12.4 | 15.6 | 15.9 | 17.1 | 12.2 | -| 16 | 24 | 23424.0 | 0.0 | 0.6 | 8.9 | 0.2 | 6.4 | 0.1 | 0.0 | 17.6 | 19.5 | 19.6 | 19.8 | 16.2 | -| 16 | 32 | 23840.0 | 0.0 | 1.2 | 10.4 | 0.4 | 9.2 | 0.1 | 0.0 | 23.1 | 23.4 | 23.5 | 23.6 | 21.3 | -| 16 | 40 | 27972.0 | 0.0 | 1.3 | 11.2 | 0.4 | 9.6 | 0.1 | 0.0 | 23.8 | 25.2 | 25.3 | 25.5 | 22.6 | -| 16 | 48 | 28704.0 | 0.0 | 1.5 | 13.3 | 0.4 | 11.2 | 0.1 | 0.0 | 28.6 | 29.0 | 29.1 | 30.6 | 26.5 | -| 16 | 56 | 26464.0 | 0.0 | 1.8 | 17.3 | 0.7 | 13.1 | 0.1 | 0.0 | 32.6 | 40.4 | 40.6 | 40.8 | 33.1 | -| 16 | 64 | 27536.0 | 0.0 | 1.4 | 21.8 | 0.3 | 12.5 | 0.1 | 0.0 | 37.9 | 38.3 | 38.7 | 40.7 | 36.2 | -| 16 | 72 | 33680.0 | 0.0 | 1.5 | 13.5 | 0.8 | 17.8 | 0.1 | 0.0 | 35.0 | 38.4 | 38.8 | 40.4 | 33.7 | -| 16 | 80 | 27984.0 | 0.0 | 1.6 | 25.5 | 0.5 | 16.6 | 0.1 | 0.0 | 47.7 | 48.2 | 48.3 | 48.6 | 44.4 | -| 16 | 88 | 36464.0 | 0.0 | 1.9 | 16.8 | 0.9 | 18.2 | 0.2 | 0.0 | 39.0 | 40.7 | 40.9 | 41.1 | 37.9 | -| 16 | 96 | 35792.0 | 0.0 | 1.9 | 21.1 | 0.7 | 17.4 | 0.1 | 0.0 | 42.7 | 43.0 | 43.1 | 43.2 | 41.4 | -| 16 | 104 | 35536.0 | 0.0 | 2.1 | 25.9 | 0.7 | 17.6 | 0.1 | 0.0 | 48.0 | 48.2 | 48.4 | 48.6 | 46.4 | -| 16 | 112 | 30448.0 | 0.0 | 2.0 | 33.5 | 0.9 | 20.1 | 0.1 | 0.0 | 58.2 | 58.7 | 58.9 | 59.0 | 56.8 | -| 16 | 120 | 32480.0 | 0.0 | 2.9 | 32.9 | 0.8 | 20.3 | 0.2 | 0.0 | 58.6 | 59.0 | 59.2 | 60.4 | 57.2 | -| 16 | 128 | 34528.0 | 0.0 | 2.7 | 33.1 | 1.0 | 20.4 | 0.2 | 0.0 | 58.7 | 59.1 | 59.2 | 59.3 | 57.4 | -| 16 | 136 | 37424.0 | 0.1 | 1.8 | 34.3 | 0.9 | 19.9 | 0.2 | 0.0 | 58.9 | 59.4 | 60.0 | 60.3 | 57.1 | -| 16 | 144 | 33552.0 | 0.0 | 2.5 | 41.1 | 0.9 | 21.8 | 0.2 | 0.0 | 68.9 | 69.2 | 69.3 | 69.5 | 66.6 | -| 16 | 152 | 35104.0 | 0.1 | 2.2 | 43.0 | 1.0 | 21.4 | 0.2 | 0.0 | 69.2 | 72.3 | 76.7 | 81.6 | 67.7 | -| 16 | 160 | 31984.0 | 0.1 | 2.3 | 52.8 | 0.9 | 20.4 | 0.2 | 0.0 | 81.4 | 82.0 | 91.3 | 91.4 | 76.7 | -| 16 | 168 | 35456.0 | 0.1 | 2.4 | 49.3 | 0.9 | 20.9 | 0.2 | 0.0 | 71.3 | 91.3 | 91.6 | 92.1 | 73.8 | -| 16 | 176 | 33200.0 | 0.1 | 2.2 | 57.0 | 1.0 | 20.8 | 0.2 | 0.0 | 82.1 | 84.1 | 91.7 | 92.2 | 81.2 | -| 16 | 184 | 32752.0 | 0.1 | 1.6 | 60.2 | 0.9 | 21.0 | 0.2 | 0.0 | 81.8 | 92.0 | 92.3 | 92.4 | 84.1 | -| 16 | 192 | 36192.0 | 0.1 | 2.4 | 54.7 | 1.1 | 23.1 | 0.2 | 0.0 | 84.2 | 92.2 | 92.3 | 93.0 | 81.7 | -| 16 | 200 | 37424.0 | 0.1 | 2.8 | 56.8 | 0.9 | 20.8 | 0.2 | 0.0 | 82.0 | 82.2 | 82.3 | 82.4 | 81.6 | -| 16 | 208 | 35616.0 | 0.1 | 2.1 | 63.3 | 0.9 | 22.8 | 0.2 | 0.0 | 91.7 | 100.4 | 104.0 | 104.6 | 89.3 | -| 16 | 216 | 37200.0 | 0.1 | 2.6 | 63.9 | 1.1 | 21.0 | 0.2 | 0.0 | 89.2 | 89.5 | 89.6 | 89.7 | 88.8 | -| 16 | 224 | 32512.0 | 0.1 | 2.1 | 80.5 | 0.9 | 20.7 | 0.2 | 0.0 | 104.6 | 105.0 | 105.1 | 105.6 | 104.5 | -| 16 | 232 | 40944.0 | 0.1 | 2.0 | 59.3 | 1.0 | 24.4 | 0.2 | 0.0 | 89.3 | 93.4 | 100.7 | 101.8 | 87.0 | -| 16 | 240 | 37952.0 | 0.1 | 2.2 | 74.6 | 1.0 | 17.7 | 0.2 | 0.0 | 94.0 | 101.3 | 101.6 | 103.8 | 95.7 | -| 16 | 248 | 37744.0 | 0.2 | 2.2 | 74.6 | 1.0 | 23.0 | 0.2 | 0.0 | 101.8 | 113.0 | 113.4 | 114.6 | 101.1 | -| 16 | 256 | 31120.0 | 0.1 | 2.0 | 100.8 | 0.9 | 20.1 | 0.1 | 0.0 | 124.2 | 124.9 | 125.1 | 125.5 | 124.2 | - -
- - - - -#### Online: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 8080.0 | 0.0 | 0.2 | 5.0 | 0.2 | 10.1 | 0.1 | 0.0 | 19.3 | 20.4 | 20.5 | 20.9 | 15.6 | -| 16 | 16 | 12275.7 | 0.0 | 0.4 | 7.8 | 0.4 | 10.1 | 1.7 | 0.0 | 23.3 | 25.3 | 25.9 | 26.3 | 20.4 | -| 16 | 24 | 15072.0 | 0.0 | 0.6 | 10.2 | 0.5 | 10.5 | 2.9 | 0.0 | 27.3 | 28.4 | 28.8 | 29.6 | 24.8 | -| 16 | 32 | 17616.0 | 0.0 | 1.0 | 11.7 | 0.6 | 12.0 | 3.1 | 0.0 | 30.9 | 32.0 | 32.3 | 32.6 | 28.5 | -| 16 | 40 | 19024.0 | 0.0 | 0.9 | 14.2 | 0.8 | 11.7 | 5.3 | 0.0 | 34.9 | 36.7 | 37.4 | 47.0 | 32.9 | -| 16 | 48 | 19312.0 | 0.1 | 2.1 | 12.1 | 1.1 | 11.8 | 12.2 | 0.0 | 39.9 | 46.1 | 49.0 | 54.4 | 39.2 | -| 16 | 56 | 20848.0 | 0.0 | 1.4 | 17.9 | 1.1 | 10.0 | 11.1 | 0.0 | 43.6 | 44.9 | 46.0 | 50.8 | 41.6 | -| 16 | 64 | 21456.0 | 0.0 | 1.9 | 14.9 | 1.4 | 9.7 | 18.6 | 0.0 | 48.2 | 50.1 | 51.0 | 51.3 | 46.5 | -| 16 | 72 | 21600.0 | 0.0 | 4.1 | 19.6 | 1.1 | 10.4 | 16.9 | 0.0 | 53.9 | 54.5 | 54.7 | 55.8 | 52.0 | -| 16 | 80 | 22192.0 | 0.1 | 2.1 | 24.1 | 2.2 | 9.5 | 18.0 | 0.0 | 57.9 | 60.0 | 61.5 | 63.2 | 56.0 | -| 16 | 88 | 22304.0 | 0.0 | 2.1 | 27.6 | 3.2 | 8.8 | 19.4 | 0.0 | 63.5 | 66.0 | 66.1 | 77.3 | 61.2 | -| 16 | 96 | 22176.0 | 0.0 | 2.6 | 29.3 | 4.1 | 8.7 | 21.6 | 0.0 | 68.6 | 71.9 | 76.1 | 79.0 | 66.3 | -| 16 | 104 | 22416.0 | 0.0 | 4.4 | 30.2 | 1.6 | 10.8 | 24.1 | 0.0 | 73.4 | 75.0 | 75.9 | 76.5 | 71.1 | -| 16 | 112 | 22096.0 | 0.1 | 2.9 | 33.8 | 10.6 | 7.4 | 23.1 | 0.0 | 81.6 | 83.9 | 84.4 | 90.5 | 77.8 | -| 16 | 120 | 22320.0 | 0.1 | 3.0 | 34.8 | 10.2 | 7.9 | 25.9 | 0.0 | 85.6 | 90.2 | 102.7 | 116.7 | 81.9 | -| 16 | 128 | 22544.0 | 0.1 | 2.9 | 38.9 | 12.9 | 7.1 | 25.4 | 0.0 | 91.8 | 95.3 | 103.6 | 105.4 | 87.3 | -| 16 | 136 | 22704.0 | 0.1 | 3.8 | 40.5 | 13.9 | 7.1 | 25.9 | 0.0 | 95.4 | 97.8 | 98.6 | 114.4 | 91.3 | -| 16 | 144 | 22224.0 | 0.1 | 2.3 | 42.4 | 18.0 | 6.8 | 26.6 | 0.0 | 101.8 | 107.1 | 108.3 | 108.4 | 96.1 | -| 16 | 152 | 22992.0 | 0.1 | 3.3 | 45.4 | 19.0 | 6.8 | 26.6 | 0.0 | 105.8 | 107.6 | 108.0 | 108.8 | 101.2 | -| 16 | 160 | 23328.0 | 0.1 | 2.5 | 47.8 | 11.5 | 7.6 | 34.7 | 0.0 | 106.5 | 121.2 | 123.0 | 140.4 | 104.2 | -| 16 | 168 | 22448.0 | 0.1 | 3.7 | 50.4 | 15.0 | 8.8 | 32.7 | 0.0 | 112.6 | 123.8 | 126.9 | 131.8 | 110.6 | -| 16 | 176 | 22640.0 | 0.1 | 3.6 | 53.3 | 14.9 | 7.7 | 35.1 | 0.0 | 118.0 | 124.1 | 128.9 | 144.0 | 114.7 | -| 16 | 184 | 22937.1 | 0.1 | 4.0 | 52.5 | 23.3 | 7.1 | 32.7 | 0.0 | 124.3 | 126.2 | 127.4 | 128.0 | 119.6 | -| 16 | 192 | 23768.2 | 0.1 | 3.6 | 56.4 | 20.6 | 7.1 | 36.2 | 0.0 | 127.9 | 130.7 | 136.4 | 139.0 | 124.0 | -| 16 | 200 | 23584.0 | 0.1 | 3.9 | 57.8 | 24.4 | 7.2 | 35.5 | 0.0 | 136.1 | 139.0 | 140.3 | 140.7 | 128.7 | -| 16 | 208 | 23192.8 | 0.1 | 4.8 | 62.0 | 20.9 | 7.8 | 38.9 | 0.0 | 140.9 | 145.3 | 170.9 | 187.7 | 134.5 | -| 16 | 216 | 22873.1 | 0.1 | 3.6 | 80.7 | 17.8 | 7.4 | 32.5 | 0.0 | 145.1 | 152.1 | 158.8 | 159.7 | 142.0 | -| 16 | 224 | 23360.0 | 0.1 | 3.7 | 76.7 | 19.9 | 7.4 | 36.1 | 0.0 | 145.4 | 153.1 | 166.4 | 168.8 | 144.0 | -| 16 | 232 | 23152.0 | 0.1 | 3.8 | 83.3 | 17.8 | 7.8 | 38.2 | 0.0 | 151.2 | 162.3 | 176.8 | 185.3 | 150.9 | -| 16 | 240 | 22384.0 | 0.1 | 4.1 | 88.6 | 21.1 | 7.1 | 34.2 | 0.0 | 157.6 | 161.1 | 166.3 | 170.4 | 155.1 | -| 16 | 248 | 22608.0 | 0.2 | 4.5 | 93.4 | 18.5 | 9.3 | 34.8 | 0.0 | 163.3 | 172.8 | 186.2 | 199.5 | 160.8 | -| 16 | 256 | 22320.0 | 0.1 | 3.0 | 94.1 | 16.6 | 8.1 | 41.7 | 0.0 | 165.4 | 178.2 | 188.9 | 202.4 | 163.7 | - -
- - - - -#### Online: NVIDIA DGX A100 (1x A100 80GB), PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA DGX A100 (1x A100 80GB) | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 8032.0 | 0.0 | 0.3 | 5.0 | 0.2 | 10.0 | 0.1 | 0.0 | 19.3 | 20.2 | 20.4 | 21.0 | 15.6 | -| 16 | 16 | 12784.0 | 0.0 | 0.4 | 7.5 | 0.4 | 9.8 | 1.6 | 0.0 | 22.8 | 23.6 | 23.8 | 24.3 | 19.8 | -| 16 | 24 | 15888.0 | 0.0 | 0.7 | 9.3 | 0.5 | 9.8 | 3.6 | 0.0 | 26.5 | 27.3 | 27.5 | 27.7 | 23.9 | -| 16 | 32 | 17952.0 | 0.0 | 0.7 | 10.8 | 0.6 | 9.8 | 6.1 | 0.0 | 30.5 | 31.1 | 31.4 | 31.6 | 28.0 | -| 16 | 40 | 19376.0 | 0.0 | 1.0 | 12.6 | 0.7 | 9.7 | 8.1 | 0.0 | 34.5 | 35.3 | 35.5 | 35.7 | 32.2 | -| 16 | 48 | 20528.0 | 0.0 | 1.4 | 15.9 | 0.9 | 9.6 | 8.6 | 0.0 | 38.7 | 39.5 | 39.8 | 40.1 | 36.4 | -| 16 | 56 | 20848.0 | 0.0 | 1.2 | 18.5 | 0.9 | 10.3 | 10.7 | 0.0 | 43.8 | 45.2 | 45.6 | 46.3 | 41.7 | -| 16 | 64 | 21968.0 | 0.0 | 1.6 | 20.6 | 0.9 | 10.2 | 12.5 | 0.0 | 48.0 | 48.7 | 48.9 | 49.3 | 45.9 | -| 16 | 72 | 22144.0 | 0.1 | 1.7 | 20.8 | 1.2 | 9.8 | 16.7 | 0.0 | 52.5 | 53.6 | 54.1 | 54.7 | 50.3 | -| 16 | 80 | 22656.0 | 0.0 | 2.2 | 23.2 | 2.6 | 9.0 | 18.4 | 0.0 | 57.6 | 59.4 | 59.8 | 62.7 | 55.5 | -| 16 | 88 | 23208.8 | 0.0 | 2.6 | 26.3 | 2.0 | 9.9 | 18.7 | 0.0 | 61.5 | 62.6 | 62.9 | 68.4 | 59.5 | -| 16 | 96 | 22464.0 | 0.0 | 2.6 | 27.4 | 2.6 | 9.0 | 23.7 | 0.0 | 67.3 | 69.6 | 73.2 | 79.3 | 65.4 | -| 16 | 104 | 22752.0 | 0.0 | 2.9 | 31.8 | 3.7 | 8.7 | 22.9 | 0.0 | 72.4 | 76.1 | 78.1 | 85.2 | 70.0 | -| 16 | 112 | 23352.6 | 0.1 | 3.6 | 31.8 | 1.5 | 10.6 | 27.3 | 0.0 | 76.3 | 80.4 | 82.2 | 87.4 | 74.9 | -| 16 | 120 | 22592.0 | 0.1 | 3.7 | 34.0 | 7.5 | 8.1 | 28.6 | 0.0 | 83.8 | 86.1 | 88.0 | 107.9 | 81.9 | -| 16 | 128 | 22288.0 | 0.1 | 3.7 | 38.1 | 8.8 | 8.1 | 26.6 | 0.0 | 87.9 | 99.0 | 100.6 | 113.3 | 85.4 | -| 16 | 136 | 23440.0 | 0.1 | 3.1 | 38.2 | 16.5 | 6.7 | 25.4 | 0.0 | 94.0 | 99.6 | 100.7 | 102.5 | 90.1 | -| 16 | 144 | 22864.0 | 0.1 | 2.8 | 43.7 | 14.4 | 7.3 | 27.5 | 0.0 | 99.4 | 102.7 | 104.8 | 121.1 | 95.7 | -| 16 | 152 | 23224.8 | 0.1 | 3.9 | 45.5 | 11.7 | 7.6 | 31.4 | 0.0 | 103.0 | 108.4 | 116.6 | 128.1 | 100.2 | -| 16 | 160 | 22496.0 | 0.1 | 4.3 | 46.8 | 13.1 | 7.7 | 34.3 | 0.0 | 110.5 | 115.9 | 125.3 | 136.9 | 106.2 | -| 16 | 168 | 23760.0 | 0.1 | 3.4 | 49.5 | 18.7 | 7.2 | 29.3 | 0.0 | 111.9 | 113.3 | 113.8 | 135.5 | 108.1 | -| 16 | 176 | 23328.0 | 0.1 | 3.9 | 51.5 | 21.3 | 7.6 | 29.1 | 0.0 | 116.8 | 120.4 | 121.2 | 124.7 | 113.5 | -| 16 | 184 | 23440.0 | 0.1 | 4.1 | 52.6 | 21.0 | 6.9 | 34.0 | 0.0 | 123.0 | 127.5 | 128.1 | 129.3 | 118.6 | -| 16 | 192 | 23728.0 | 0.1 | 3.7 | 56.8 | 19.4 | 7.0 | 35.9 | 0.0 | 122.8 | 123.1 | 123.2 | 123.3 | 122.8 | -| 16 | 200 | 23808.0 | 0.1 | 4.8 | 57.8 | 23.0 | 7.0 | 33.6 | 0.0 | 128.3 | 132.6 | 133.2 | 136.8 | 126.3 | -| 16 | 208 | 23856.0 | 0.1 | 4.2 | 59.0 | 25.7 | 7.2 | 35.1 | 0.0 | 138.1 | 140.9 | 141.2 | 141.6 | 131.2 | -| 16 | 216 | 23200.0 | 0.1 | 3.6 | 64.5 | 23.8 | 6.9 | 36.7 | 0.0 | 135.5 | 136.1 | 136.6 | 136.7 | 135.6 | -| 16 | 224 | 24384.0 | 0.1 | 4.8 | 67.1 | 24.7 | 6.7 | 36.5 | 0.0 | 139.9 | 140.9 | 141.1 | 142.8 | 139.9 | -| 16 | 232 | 23040.0 | 0.1 | 4.1 | 83.9 | 20.1 | 7.0 | 33.5 | 0.0 | 152.9 | 158.9 | 168.2 | 169.6 | 148.6 | -| 16 | 240 | 23496.5 | 0.1 | 3.1 | 87.0 | 20.9 | 7.1 | 35.2 | 0.0 | 156.1 | 159.9 | 168.7 | 171.1 | 153.3 | -| 16 | 248 | 23072.0 | 0.1 | 4.1 | 95.5 | 13.4 | 8.5 | 38.0 | 0.0 | 161.2 | 178.6 | 179.7 | 193.0 | 159.5 | -| 16 | 256 | 21952.0 | 0.1 | 4.0 | 97.0 | 15.3 | 7.7 | 38.3 | 0.0 | 164.7 | 186.0 | 192.8 | 194.8 | 162.4 | - -
- - - - -#### Online: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 10048.0 | 0.1 | 0.7 | 5.3 | 0.1 | 6.3 | 0.0 | 0.0 | 12.6 | 12.7 | 12.7 | 12.8 | 12.6 | -| 16 | 16 | 8464.0 | 0.1 | 1.0 | 15.6 | 0.2 | 13.0 | 0.0 | 0.0 | 30.5 | 41.0 | 41.5 | 41.7 | 29.9 | -| 16 | 24 | 9472.0 | 0.1 | 1.4 | 19.2 | 0.2 | 17.9 | 0.0 | 0.0 | 41.4 | 57.5 | 57.8 | 62.8 | 38.9 | -| 16 | 32 | 9568.0 | 0.1 | 2.0 | 20.2 | 0.3 | 30.3 | 0.0 | 0.0 | 57.4 | 61.5 | 61.6 | 61.7 | 53.1 | -| 16 | 40 | 9616.0 | 0.1 | 2.4 | 31.6 | 0.3 | 29.4 | 0.0 | 0.0 | 70.4 | 71.3 | 71.6 | 72.0 | 63.9 | -| 16 | 48 | 9872.0 | 0.1 | 3.8 | 34.9 | 0.5 | 35.9 | 0.1 | 0.0 | 71.1 | 108.0 | 108.8 | 109.3 | 75.3 | -| 16 | 56 | 9024.0 | 0.1 | 2.8 | 54.7 | 0.3 | 36.5 | 0.0 | 0.0 | 100.7 | 101.2 | 101.7 | 101.8 | 94.5 | -| 16 | 64 | 9536.0 | 0.1 | 4.1 | 37.6 | 0.6 | 61.2 | 0.1 | 0.0 | 108.4 | 109.0 | 109.3 | 109.5 | 103.7 | -| 16 | 72 | 8016.0 | 0.1 | 3.7 | 74.4 | 0.5 | 53.0 | 0.0 | 0.0 | 137.2 | 138.0 | 138.3 | 138.5 | 131.7 | -| 16 | 80 | 9328.0 | 0.1 | 3.8 | 71.0 | 0.6 | 57.2 | 0.1 | 0.0 | 137.5 | 138.6 | 139.6 | 139.8 | 132.7 | -| 16 | 88 | 8240.0 | 0.1 | 3.0 | 85.8 | 0.6 | 61.5 | 0.0 | 0.0 | 158.5 | 175.1 | 176.1 | 176.9 | 151.0 | -| 16 | 96 | 9504.0 | 0.1 | 3.8 | 91.9 | 0.6 | 57.2 | 0.0 | 0.0 | 158.4 | 159.8 | 160.6 | 196.6 | 153.7 | -| 16 | 104 | 9526.5 | 0.2 | 3.6 | 96.2 | 0.8 | 69.6 | 0.0 | 0.0 | 175.4 | 176.3 | 176.3 | 176.6 | 170.4 | -| 16 | 112 | 9424.0 | 0.2 | 3.8 | 94.8 | 0.9 | 70.9 | 0.1 | 0.0 | 175.9 | 176.9 | 177.0 | 177.1 | 170.6 | -| 16 | 120 | 9280.0 | 0.2 | 4.0 | 116.7 | 0.9 | 69.5 | 0.1 | 0.0 | 196.2 | 196.8 | 196.9 | 197.2 | 191.4 | -| 16 | 128 | 9552.0 | 0.2 | 4.3 | 116.8 | 0.9 | 69.3 | 0.1 | 0.0 | 196.4 | 197.2 | 197.4 | 197.6 | 191.5 | -| 16 | 136 | 10165.8 | 0.3 | 3.3 | 117.3 | 1.0 | 69.4 | 0.1 | 0.0 | 196.9 | 197.4 | 197.6 | 197.8 | 191.4 | -| 16 | 144 | 10400.0 | 0.3 | 4.6 | 115.3 | 1.0 | 70.9 | 0.1 | 0.0 | 196.6 | 197.2 | 197.4 | 197.7 | 192.1 | -| 16 | 152 | 9350.6 | 0.3 | 5.1 | 146.4 | 1.0 | 77.2 | 0.1 | 0.0 | 234.6 | 235.3 | 235.6 | 236.0 | 230.1 | -| 16 | 160 | 9744.0 | 0.3 | 4.8 | 145.9 | 1.1 | 77.0 | 0.1 | 0.0 | 234.1 | 234.9 | 235.3 | 235.6 | 229.2 | -| 16 | 168 | 7520.0 | 0.5 | 2.7 | 220.8 | 0.9 | 77.2 | 0.1 | 0.0 | 311.0 | 312.4 | 312.5 | 312.8 | 301.9 | -| 16 | 176 | 7880.1 | 0.5 | 4.0 | 227.3 | 0.9 | 77.0 | 0.1 | 0.0 | 311.6 | 312.7 | 312.8 | 313.1 | 309.8 | -| 16 | 184 | 9760.0 | 0.8 | 5.3 | 183.3 | 1.0 | 73.3 | 0.1 | 0.0 | 256.0 | 275.9 | 276.2 | 276.4 | 263.9 | -| 16 | 192 | 9312.0 | 0.8 | 3.8 | 197.8 | 0.9 | 70.4 | 0.1 | 0.0 | 275.1 | 275.9 | 276.0 | 276.5 | 273.9 | -| 16 | 200 | 8880.0 | 0.9 | 3.5 | 229.1 | 1.0 | 77.2 | 0.1 | 0.0 | 312.8 | 313.9 | 314.0 | 314.2 | 311.7 | -| 16 | 208 | 10992.0 | 1.1 | 3.4 | 188.8 | 1.1 | 71.6 | 0.2 | 0.0 | 266.3 | 266.9 | 267.1 | 267.5 | 266.1 | -| 16 | 216 | 9600.0 | 0.8 | 4.8 | 228.0 | 1.1 | 77.2 | 0.1 | 0.0 | 313.0 | 314.2 | 314.5 | 315.4 | 311.9 | -| 16 | 224 | 9776.0 | 1.1 | 3.8 | 228.5 | 1.1 | 77.2 | 0.1 | 0.0 | 313.0 | 313.7 | 313.8 | 314.0 | 311.9 | -| 16 | 232 | 10928.0 | 1.1 | 3.5 | 220.3 | 1.1 | 69.4 | 0.1 | 0.0 | 296.0 | 296.9 | 297.0 | 297.4 | 295.5 | -| 16 | 240 | 10752.0 | 1.3 | 4.2 | 228.7 | 1.1 | 77.2 | 0.2 | 0.0 | 313.3 | 314.0 | 314.1 | 314.3 | 312.8 | -| 16 | 248 | 9878.1 | 1.4 | 5.1 | 249.7 | 1.2 | 74.8 | 0.2 | 0.0 | 332.9 | 334.1 | 334.3 | 334.6 | 332.4 | -| 16 | 256 | 10368.0 | 1.2 | 4.7 | 251.1 | 1.1 | 74.9 | 0.2 | 0.0 | 333.6 | 334.4 | 334.6 | 335.3 | 333.2 | - -
- - - - -#### Online: NVIDIA T4, NVIDIA TensorRT with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |NVIDIA TensorRT | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |NVIDIA TensorRT | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| NVIDIA TensorRT Capture CUDA Graph | Disabled | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 10176.0 | 0.1 | 0.7 | 5.2 | 0.1 | 6.2 | 0.0 | 0.0 | 12.4 | 12.5 | 12.6 | 12.6 | 12.4 | -| 16 | 16 | 8880.0 | 0.1 | 0.9 | 14.6 | 0.1 | 12.4 | 0.0 | 0.0 | 28.6 | 37.0 | 41.6 | 41.9 | 28.3 | -| 16 | 24 | 9520.0 | 0.1 | 1.3 | 19.9 | 0.2 | 17.8 | 0.0 | 0.0 | 41.6 | 50.9 | 57.3 | 61.9 | 39.4 | -| 16 | 32 | 9152.0 | 0.1 | 2.1 | 21.0 | 0.3 | 30.8 | 0.0 | 0.0 | 57.9 | 62.3 | 63.1 | 65.2 | 54.3 | -| 16 | 40 | 9712.0 | 0.1 | 2.7 | 30.0 | 0.3 | 31.6 | 0.0 | 0.0 | 70.7 | 71.2 | 71.4 | 71.6 | 64.8 | -| 16 | 48 | 8000.0 | 0.1 | 3.4 | 28.3 | 0.4 | 61.5 | 0.1 | 0.0 | 95.8 | 104.0 | 104.1 | 104.2 | 93.7 | -| 16 | 56 | 9376.0 | 0.1 | 3.9 | 24.7 | 0.6 | 64.1 | 0.1 | 0.0 | 95.4 | 104.5 | 105.3 | 106.0 | 93.4 | -| 16 | 64 | 8192.0 | 0.1 | 3.4 | 55.8 | 0.5 | 58.8 | 0.0 | 0.0 | 124.4 | 124.7 | 125.2 | 125.3 | 118.7 | -| 16 | 72 | 8432.0 | 0.1 | 2.2 | 73.0 | 0.5 | 51.0 | 0.0 | 0.0 | 137.8 | 138.8 | 139.1 | 139.4 | 126.9 | -| 16 | 80 | 8944.0 | 0.1 | 4.3 | 71.9 | 0.5 | 55.9 | 0.1 | 0.0 | 137.2 | 138.6 | 138.8 | 139.0 | 132.7 | -| 16 | 88 | 7936.0 | 0.1 | 3.0 | 93.5 | 0.7 | 72.3 | 0.1 | 0.0 | 175.2 | 176.1 | 176.3 | 176.4 | 169.6 | -| 16 | 96 | 9152.0 | 0.2 | 3.0 | 92.8 | 0.7 | 56.4 | 0.1 | 0.0 | 159.0 | 159.4 | 159.5 | 159.8 | 153.1 | -| 16 | 104 | 9510.5 | 0.1 | 3.5 | 93.2 | 0.7 | 57.0 | 0.1 | 0.0 | 159.3 | 159.9 | 159.9 | 160.1 | 154.6 | -| 16 | 112 | 10709.3 | 0.2 | 2.8 | 91.4 | 0.9 | 61.3 | 0.1 | 0.0 | 159.2 | 160.2 | 160.4 | 196.7 | 156.7 | -| 16 | 120 | 8848.0 | 0.2 | 3.5 | 116.2 | 0.9 | 70.3 | 0.1 | 0.0 | 196.7 | 198.1 | 198.5 | 199.3 | 191.2 | -| 16 | 128 | 9472.0 | 0.2 | 3.8 | 118.7 | 0.8 | 68.4 | 0.1 | 0.0 | 196.6 | 197.2 | 197.3 | 197.4 | 192.0 | -| 16 | 136 | 10208.0 | 0.2 | 4.1 | 117.3 | 0.9 | 69.6 | 0.1 | 0.0 | 196.9 | 197.8 | 198.1 | 199.0 | 192.2 | -| 16 | 144 | 8599.4 | 0.2 | 4.2 | 146.6 | 0.9 | 77.2 | 0.1 | 0.0 | 234.1 | 235.2 | 235.7 | 236.0 | 229.3 | -| 16 | 152 | 9110.9 | 0.3 | 4.2 | 146.5 | 1.0 | 77.3 | 0.1 | 0.0 | 235.0 | 235.6 | 235.7 | 236.0 | 229.4 | -| 16 | 160 | 7680.0 | 0.4 | 3.2 | 196.0 | 0.8 | 72.5 | 0.1 | 0.0 | 274.5 | 275.2 | 275.6 | 276.1 | 273.1 | -| 16 | 168 | 9968.0 | 0.5 | 4.3 | 147.3 | 1.2 | 77.3 | 0.1 | 0.0 | 234.8 | 236.1 | 236.3 | 236.7 | 230.7 | -| 16 | 176 | 9248.0 | 0.6 | 3.4 | 197.3 | 0.9 | 71.7 | 0.1 | 0.0 | 275.6 | 276.8 | 276.9 | 277.1 | 274.0 | -| 16 | 184 | 8871.1 | 0.6 | 4.2 | 203.9 | 1.1 | 70.7 | 0.1 | 0.0 | 275.5 | 313.3 | 313.9 | 314.6 | 280.6 | -| 16 | 192 | 11252.7 | 0.5 | 5.4 | 151.3 | 1.5 | 77.1 | 0.1 | 0.0 | 235.9 | 237.3 | 237.6 | 238.7 | 235.9 | -| 16 | 200 | 10896.0 | 0.8 | 3.9 | 175.2 | 1.2 | 73.2 | 0.2 | 0.0 | 255.9 | 256.5 | 256.6 | 257.4 | 254.4 | -| 16 | 208 | 11040.0 | 1.1 | 3.5 | 195.6 | 1.1 | 73.1 | 0.1 | 0.0 | 275.9 | 276.8 | 276.9 | 277.1 | 274.6 | -| 16 | 216 | 10384.0 | 1.1 | 4.0 | 215.2 | 1.1 | 71.2 | 0.1 | 0.0 | 295.2 | 296.3 | 296.7 | 297.4 | 292.8 | -| 16 | 224 | 10752.0 | 0.9 | 4.5 | 224.8 | 1.4 | 70.8 | 0.1 | 0.0 | 297.4 | 317.0 | 317.4 | 318.4 | 302.5 | -| 16 | 232 | 10144.0 | 1.0 | 3.7 | 244.1 | 1.0 | 75.1 | 0.2 | 0.0 | 324.5 | 332.0 | 332.9 | 333.0 | 325.0 | -| 16 | 240 | 10560.0 | 1.2 | 4.4 | 228.1 | 1.1 | 77.3 | 0.2 | 0.0 | 313.6 | 314.8 | 315.0 | 315.2 | 312.3 | -| 16 | 248 | 10896.0 | 1.5 | 4.0 | 245.3 | 1.2 | 75.3 | 0.2 | 0.0 | 326.0 | 334.1 | 334.5 | 335.4 | 327.5 | -| 16 | 256 | 11264.0 | 1.5 | 4.3 | 230.6 | 1.7 | 77.0 | 0.2 | 0.0 | 315.4 | 316.4 | 316.6 | 317.0 | 315.4 | - -
- - - - -#### Online: NVIDIA T4, PyTorch with FP16, Dataset: electricity - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | electricity | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 3264.0 | 0.1 | 0.6 | 13.9 | 0.8 | 8.9 | 14.2 | 0.0 | 43.8 | 47.8 | 50.1 | 52.1 | 38.5 | -| 16 | 16 | 3669.3 | 0.1 | 1.0 | 26.2 | 2.0 | 9.1 | 30.3 | 0.0 | 76.8 | 82.8 | 84.7 | 86.7 | 68.7 | -| 16 | 24 | 3760.0 | 0.1 | 1.6 | 37.0 | 2.7 | 9.1 | 50.0 | 0.0 | 111.8 | 114.0 | 114.5 | 117.8 | 100.4 | -| 16 | 32 | 3818.7 | 0.1 | 1.3 | 58.1 | 1.9 | 9.0 | 61.7 | 0.0 | 143.8 | 146.6 | 148.1 | 150.5 | 132.2 | -| 16 | 40 | 3801.4 | 0.1 | 3.0 | 69.5 | 2.0 | 8.9 | 80.0 | 0.0 | 175.5 | 180.4 | 180.8 | 181.7 | 163.4 | -| 16 | 48 | 3822.7 | 0.1 | 3.4 | 77.8 | 6.0 | 9.1 | 98.1 | 0.0 | 205.7 | 209.7 | 211.7 | 216.0 | 194.6 | -| 16 | 56 | 3785.4 | 0.1 | 4.7 | 77.8 | 4.2 | 8.8 | 128.9 | 0.0 | 236.4 | 239.9 | 241.8 | 242.0 | 224.5 | -| 16 | 64 | 3669.3 | 0.1 | 4.8 | 65.2 | 10.4 | 8.4 | 169.2 | 0.0 | 270.8 | 277.5 | 278.0 | 278.2 | 258.2 | -| 16 | 72 | 3769.4 | 0.1 | 4.6 | 129.8 | 5.5 | 8.2 | 140.6 | 0.0 | 300.9 | 305.2 | 306.5 | 306.8 | 288.8 | -| 16 | 80 | 3528.0 | 0.1 | 4.7 | 102.8 | 15.8 | 7.3 | 190.4 | 0.0 | 335.5 | 342.8 | 342.9 | 384.7 | 321.2 | -| 16 | 88 | 3594.7 | 0.1 | 4.0 | 158.6 | 15.5 | 9.1 | 163.3 | 0.0 | 363.4 | 369.4 | 370.6 | 420.0 | 350.6 | -| 16 | 96 | 3700.1 | 0.1 | 4.4 | 187.4 | 22.6 | 8.4 | 159.2 | 0.0 | 394.9 | 397.8 | 398.7 | 412.2 | 382.2 | -| 16 | 104 | 3710.8 | 0.1 | 6.4 | 191.4 | 31.9 | 8.7 | 178.8 | 0.0 | 430.1 | 432.2 | 463.7 | 465.9 | 417.4 | -| 16 | 112 | 3680.0 | 0.1 | 6.1 | 213.8 | 33.0 | 8.5 | 187.7 | 0.0 | 461.4 | 464.6 | 465.3 | 465.5 | 449.4 | -| 16 | 120 | 3616.0 | 0.1 | 7.5 | 158.8 | 27.8 | 7.7 | 274.8 | 0.0 | 489.4 | 493.1 | 500.8 | 501.0 | 476.8 | -| 16 | 128 | 3514.7 | 0.2 | 5.2 | 188.4 | 83.0 | 8.0 | 223.8 | 0.0 | 525.3 | 531.1 | 531.6 | 573.8 | 508.6 | -| 16 | 136 | 3716.1 | 0.2 | 5.4 | 243.3 | 67.8 | 8.0 | 210.6 | 0.0 | 547.8 | 551.0 | 551.6 | 552.1 | 535.2 | -| 16 | 144 | 3168.0 | 0.2 | 3.6 | 263.3 | 76.0 | 8.6 | 213.1 | 0.0 | 583.8 | 720.5 | 720.8 | 721.4 | 564.8 | -| 16 | 152 | 3642.7 | 0.2 | 6.6 | 232.6 | 57.1 | 7.4 | 292.4 | 0.0 | 607.9 | 609.5 | 610.0 | 619.0 | 596.4 | -| 16 | 160 | 3512.0 | 0.3 | 3.6 | 280.5 | 119.6 | 7.3 | 221.4 | 0.0 | 647.3 | 650.8 | 651.4 | 666.6 | 632.7 | -| 16 | 168 | 3206.4 | 0.2 | 6.4 | 283.2 | 116.6 | 7.9 | 243.7 | 0.0 | 669.6 | 670.4 | 670.5 | 670.7 | 657.9 | -| 16 | 176 | 3550.8 | 0.4 | 6.3 | 334.8 | 109.5 | 7.0 | 239.9 | 0.0 | 710.4 | 714.1 | 720.1 | 722.4 | 697.9 | -| 16 | 184 | 3462.3 | 0.4 | 5.4 | 334.5 | 141.1 | 6.6 | 235.4 | 0.0 | 739.5 | 741.4 | 755.4 | 755.7 | 723.5 | -| 16 | 192 | 3232.0 | 0.4 | 6.8 | 350.1 | 135.7 | 7.2 | 255.5 | 0.0 | 769.6 | 774.4 | 786.3 | 786.6 | 755.7 | -| 16 | 200 | 3578.7 | 0.5 | 5.9 | 366.7 | 157.9 | 6.5 | 250.9 | 0.0 | 801.4 | 807.8 | 808.4 | 808.8 | 788.3 | -| 16 | 208 | 3384.0 | 0.4 | 5.7 | 384.7 | 134.6 | 7.5 | 283.0 | 0.0 | 827.6 | 832.8 | 836.8 | 837.3 | 816.0 | -| 16 | 216 | 2952.0 | 0.7 | 5.4 | 419.1 | 145.7 | 6.8 | 265.2 | 0.0 | 844.8 | 851.7 | 851.8 | 852.1 | 842.9 | -| 16 | 224 | 3198.4 | 0.8 | 1.5 | 491.9 | 138.6 | 6.9 | 231.5 | 0.0 | 882.4 | 900.1 | 901.0 | 904.3 | 871.1 | -| 16 | 232 | 3370.7 | 1.1 | 6.2 | 436.3 | 169.3 | 7.0 | 281.1 | 0.0 | 900.1 | 906.2 | 906.4 | 906.6 | 900.9 | -| 16 | 240 | 3514.7 | 1.2 | 4.7 | 457.9 | 188.6 | 7.5 | 278.4 | 0.0 | 941.9 | 947.9 | 948.0 | 948.2 | 938.4 | -| 16 | 248 | 3294.9 | 1.1 | 6.2 | 572.9 | 132.5 | 8.2 | 259.2 | 0.0 | 981.8 | 987.8 | 990.1 | 990.2 | 980.0 | -| 16 | 256 | 3144.0 | 0.7 | 8.5 | 602.8 | 120.8 | 7.3 | 269.7 | 0.0 | 1010.5 | 1247.8 | 1248.0 | 1248.8 | 1009.9 | - -
- - - - -#### Online: NVIDIA T4, PyTorch with FP16, Dataset: traffic - -Our results were obtained using the following configuration: - -| Parameter Name | Parameter Value | -|:-----------------------------|:-----------------------------| -| GPU |NVIDIA T4 | -| Backend |PyTorch | -| Backend accelerator |-| -| Precision |FP16 | -| Model format |TorchScript Trace | -| Max batch size |1024 | -| Number of model instances |2| -| Export Precision | FP32 | -| Dataset | traffic | -| Device | gpu | -| Request Count | 500 | - - - - - - - - -
- -
-Results Table - -| Batch | Concurrency | Inferences/Second | Client Send (ms) | Network+Server Send/Recv (ms) | Server Queue (ms) | Server Compute Input (ms) | Server Compute Infer (ms) | Server Compute Output (ms) | Client Recv (ms) | p50 latency (ms) | p90 latency (ms) | p95 latency (ms) | p99 latency (ms) | avg latency (ms) | -|--------:|--------------:|--------------------:|-------------------:|--------------------------------:|--------------------:|----------------------------:|----------------------------:|-----------------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:|-------------------:| -| 16 | 8 | 3486.8 | 0.1 | 0.8 | 10.6 | 1.6 | 10.0 | 13.2 | 0.0 | 43.3 | 47.9 | 48.4 | 49.4 | 36.5 | -| 16 | 16 | 3668.1 | 0.1 | 0.9 | 25.4 | 2.2 | 9.1 | 30.4 | 0.0 | 77.2 | 82.6 | 83.9 | 87.3 | 68.0 | -| 16 | 24 | 3764.1 | 0.1 | 1.4 | 40.4 | 2.2 | 9.1 | 46.5 | 0.0 | 111.1 | 115.9 | 116.9 | 117.6 | 99.7 | -| 16 | 32 | 3822.7 | 0.1 | 2.2 | 56.6 | 1.8 | 8.9 | 61.3 | 0.0 | 142.5 | 145.5 | 147.1 | 151.0 | 130.9 | -| 16 | 40 | 3785.4 | 0.1 | 2.6 | 69.6 | 1.9 | 8.9 | 79.1 | 0.0 | 174.4 | 179.3 | 180.0 | 181.6 | 162.2 | -| 16 | 48 | 3854.7 | 0.1 | 4.3 | 67.3 | 4.2 | 8.9 | 107.5 | 0.0 | 205.1 | 209.3 | 209.5 | 212.6 | 192.4 | -| 16 | 56 | 3786.7 | 0.1 | 3.2 | 99.9 | 5.0 | 8.5 | 108.0 | 0.0 | 236.7 | 240.9 | 242.2 | 242.8 | 224.7 | -| 16 | 64 | 3882.7 | 0.1 | 6.3 | 65.8 | 8.2 | 8.3 | 168.3 | 0.0 | 269.1 | 275.5 | 276.0 | 378.1 | 257.1 | -| 16 | 72 | 3690.7 | 0.1 | 6.5 | 103.0 | 11.5 | 8.0 | 159.3 | 0.0 | 300.2 | 303.5 | 304.8 | 391.1 | 288.5 | -| 16 | 80 | 3669.3 | 0.1 | 6.9 | 95.3 | 19.2 | 7.0 | 193.2 | 0.0 | 333.9 | 338.4 | 338.6 | 339.3 | 321.8 | -| 16 | 88 | 3646.2 | 0.1 | 4.8 | 145.9 | 22.0 | 7.1 | 171.3 | 0.0 | 364.1 | 368.4 | 368.6 | 368.7 | 351.2 | -| 16 | 96 | 3712.0 | 0.1 | 6.3 | 174.7 | 32.3 | 7.0 | 159.8 | 0.0 | 394.4 | 399.8 | 400.2 | 400.6 | 380.1 | -| 16 | 104 | 3701.3 | 0.1 | 5.2 | 192.4 | 39.3 | 7.1 | 169.3 | 0.0 | 427.6 | 434.3 | 434.4 | 435.1 | 413.5 | -| 16 | 112 | 3686.2 | 0.1 | 5.8 | 204.9 | 41.2 | 6.9 | 186.4 | 0.0 | 458.5 | 462.0 | 462.3 | 464.8 | 445.5 | -| 16 | 120 | 3600.0 | 0.2 | 5.6 | 221.5 | 28.2 | 7.2 | 211.1 | 0.0 | 487.2 | 491.1 | 491.7 | 491.9 | 473.7 | -| 16 | 128 | 3656.0 | 0.2 | 9.2 | 157.3 | 27.6 | 6.8 | 307.7 | 0.0 | 518.4 | 525.4 | 525.5 | 526.8 | 508.7 | -| 16 | 136 | 3710.8 | 0.2 | 6.8 | 249.1 | 83.8 | 7.3 | 191.2 | 0.0 | 552.1 | 555.3 | 562.4 | 562.6 | 538.2 | -| 16 | 144 | 3593.5 | 0.2 | 5.3 | 267.5 | 77.6 | 6.8 | 213.9 | 0.0 | 583.8 | 586.1 | 587.0 | 587.8 | 571.3 | -| 16 | 152 | 3630.8 | 0.2 | 6.8 | 258.2 | 98.5 | 7.3 | 230.0 | 0.0 | 613.0 | 618.2 | 621.6 | 622.2 | 600.9 | -| 16 | 160 | 3464.0 | 0.2 | 8.6 | 259.1 | 112.2 | 6.8 | 240.4 | 0.0 | 640.7 | 644.5 | 644.6 | 644.8 | 627.2 | -| 16 | 168 | 3240.0 | 0.3 | 6.4 | 278.2 | 104.2 | 7.2 | 261.6 | 0.0 | 672.9 | 676.3 | 676.5 | 677.1 | 657.9 | -| 16 | 176 | 3376.0 | 0.3 | 6.2 | 298.0 | 126.7 | 6.1 | 254.5 | 0.0 | 701.3 | 706.9 | 707.0 | 707.2 | 691.8 | -| 16 | 184 | 3632.0 | 0.3 | 7.2 | 334.7 | 125.6 | 7.4 | 249.8 | 0.0 | 737.0 | 741.4 | 745.2 | 745.6 | 725.0 | -| 16 | 192 | 3504.0 | 0.5 | 7.5 | 362.4 | 125.7 | 7.2 | 252.9 | 0.0 | 766.8 | 768.9 | 769.1 | 769.3 | 756.1 | -| 16 | 200 | 3246.4 | 0.5 | 5.1 | 360.5 | 161.5 | 6.7 | 247.9 | 0.0 | 794.4 | 797.6 | 797.7 | 798.1 | 782.2 | -| 16 | 208 | 3344.0 | 0.4 | 5.6 | 463.1 | 109.0 | 7.1 | 234.1 | 0.0 | 827.3 | 830.1 | 830.4 | 859.6 | 819.4 | -| 16 | 216 | 3192.0 | 0.4 | 9.0 | 409.4 | 153.2 | 6.9 | 268.5 | 0.0 | 859.0 | 862.5 | 862.6 | 862.8 | 847.3 | -| 16 | 224 | 3312.0 | 0.5 | 6.5 | 424.0 | 179.8 | 6.6 | 257.1 | 0.0 | 888.1 | 893.6 | 900.8 | 901.6 | 874.5 | -| 16 | 232 | 3449.5 | 0.5 | 7.0 | 517.0 | 114.4 | 7.3 | 265.1 | 0.0 | 913.9 | 915.8 | 920.3 | 924.9 | 911.4 | -| 16 | 240 | 3392.0 | 0.7 | 12.9 | 555.7 | 100.4 | 8.9 | 289.1 | 0.0 | 952.8 | 1071.4 | 1138.9 | 1139.4 | 967.6 | -| 16 | 248 | 3321.6 | 0.7 | 6.1 | 474.4 | 132.1 | 8.3 | 339.2 | 0.0 | 959.6 | 967.6 | 968.1 | 968.5 | 960.8 | -| 16 | 256 | 3152.0 | 0.7 | 6.1 | 583.5 | 118.6 | 7.7 | 287.4 | 0.0 | 1008.6 | 1026.3 | 1042.2 | 1042.6 | 1004.0 | - -
- - - - -## Advanced - -| Inference runtime | Mnemonic used in scripts | -|-------------------|--------------------------| -| [TorchScript Tracing](https://pytorch.org/docs/stable/jit.html) | `ts-trace` | -| [TorchScript Scripting](https://pytorch.org/docs/stable/jit.html) | `ts-script` | -| [ONNX](https://onnx.ai) | `onnx` | -| [NVIDIA TensorRT](https://developer.nvidia.com/tensorrt) | `trt` | - -### Step by step deployment process -Commands described below can be used for exporting, converting and profiling the model. - -#### Clone Repository -IMPORTANT: This step is executed on the host computer. -
-Clone Repository Command - -```shell -git clone https://github.com/NVIDIA/DeepLearningExamples.git -cd DeepLearningExamples/PyTorch/Forecasting/TFT -``` -
- -#### Setup Environment -Setup the environment in the host computer and start Triton Inference Server. -
-Setup Environment Command - -```shell -source ./triton/scripts/setup_environment.sh -./triton/scripts/docker/triton_inference_server.sh -``` -
- -#### Prepare Dataset. -Please use the data download from the [Main QSG](https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/Forecasting/TFT#quick-start-guide) - -#### Prepare Checkpoint -Please place a `checkpoint.pt` from TFT trained on electricity in `runner_workspace/checkpoints/electricity_bin/`. Note that the `electricity_bin` -subdirectory may not be created yet. In addition one can download a zip archive of a trained checkpoint -[here](https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip) - -#### Setup Container -Build and run a container that extends the NGC PyTorch container with the Triton Inference Server client libraries and dependencies. -
-Setup Container Command - -```shell -./triton/scripts/docker/build.sh -./triton/scripts/docker/interactive.sh /path/to/your/data/ -``` -
- -#### Prepare configuration -You can use the environment variables to set the parameters of your inference configuration. - -Example values of some key variables in one configuration: -
-Export Variables - -```shell -WORKDIR="${WORKDIR:=$(pwd)}" -export DATASETS_DIR=${WORKDIR}/datasets -export WORKSPACE_DIR=${WORKDIR}/runner_workspace -export CHECKPOINTS_DIR=${WORKSPACE_DIR}/checkpoints -export MODEL_REPOSITORY_PATH=${WORKSPACE_DIR}/model_store -export SHARED_DIR=${WORKSPACE_DIR}/shared_dir -export MODEL_NAME=TFT -export ENSEMBLE_MODEL_NAME= -export TRITON_LOAD_MODEL_METHOD=explicit -export TRITON_INSTANCES=1 -export FORMAT="trt" -export PRECISION="fp16" -export ACCELERATOR="none" -export TRITON_GPU_ENGINE_COUNT="2" -export CAPTURE_CUDA_GRAPH="0" -export BATCH_SIZE="1,2,4,8,16,32,64,128,256,512,1024" -export TRITON_MAX_QUEUE_DELAY="1" -export MAX_BATCH_SIZE="1024" -export BATCH_SIZES="1 2 4 8 16 32 64 128 256 512 1024" -export TRITON_PREFERRED_BATCH_SIZES="512 1024" -export EXPORT_FORMAT="onnx" -export EXPORT_PRECISION="fp32" -export DATASET="electricity_bin" -export DEVICE="gpu" -export REQUEST_COUNT="500" -export CHECKPOINT_VARIANT="electricity_bin" -export CHECKPOINT_DIR=${CHECKPOINTS_DIR}/${CHECKPOINT_VARIANT} -``` - -
- - -#### Export Model -Export model from Python source to desired format (e.g. Savedmodel or TorchScript) -
-Export Model Command - -```shell -if [[ "${EXPORT_FORMAT}" == "ts-trace" || "${EXPORT_FORMAT}" == "ts-script" ]]; then - export FORMAT_SUFFIX="pt" -else - export FORMAT_SUFFIX="${EXPORT_FORMAT}" -fi -python3 triton/export_model.py \ - --input-path triton/model.py \ - --input-type pyt \ - --output-path ${SHARED_DIR}/exported_model.${FORMAT_SUFFIX} \ - --output-type ${EXPORT_FORMAT} \ - --ignore-unknown-parameters \ - --onnx-opset 13 \ - \ - --checkpoint ${CHECKPOINT_DIR}/ \ - --precision ${EXPORT_PRECISION} \ - \ - --dataloader triton/dataloader.py \ - --dataset ${DATASETS_DIR}/${DATASET} \ - --batch-size 1 -``` - -
- - - -#### Convert Model -Convert the model from training to inference format (e.g. TensorRT). -
-Convert Model Command - -```shell -if [[ "${EXPORT_FORMAT}" == "ts-trace" || "${EXPORT_FORMAT}" == "ts-script" ]]; then - export FORMAT_SUFFIX="pt" -else - export FORMAT_SUFFIX="${EXPORT_FORMAT}" -fi -model-navigator convert \ - --model-name ${MODEL_NAME} \ - --model-path ${SHARED_DIR}/exported_model.${FORMAT_SUFFIX} \ - --output-path ${SHARED_DIR}/converted_model \ - --target-formats ${FORMAT} \ - --target-precisions ${PRECISION} \ - --launch-mode local \ - --override-workspace \ - --verbose \ - \ - --onnx-opsets 13 \ - --max-batch-size ${MAX_BATCH_SIZE} \ - --container-version 21.08 \ - --max-workspace-size 10000000000 \ - --atol target__0=100 \ - --rtol target__0=100 -``` - -
- - -#### Deploy Model -Configure the model on Triton Inference Server. -Generate the configuration from your model repository. -
- -Deploy Model Command - -```shell -if [[ "${FORMAT}" == "ts-trace" || "${FORMAT}" == "ts-script" ]]; then - export CONFIG_FORMAT="torchscript" -else - export CONFIG_FORMAT="${FORMAT}" -fi -model-navigator triton-config-model \ - --model-repository ${MODEL_REPOSITORY_PATH} \ - --model-name ${MODEL_NAME} \ - --model-version 1 \ - --model-path ${SHARED_DIR}/converted_model \ - --model-format ${CONFIG_FORMAT} \ - --model-control-mode ${TRITON_LOAD_MODEL_METHOD} \ - --load-model \ - --load-model-timeout-s 100 \ - --verbose \ - \ - --backend-accelerator ${ACCELERATOR} \ - --tensorrt-precision ${PRECISION} \ - --tensorrt-capture-cuda-graph \ - --tensorrt-max-workspace-size 10000000000 \ - --max-batch-size ${MAX_BATCH_SIZE} \ - --batching dynamic \ - --preferred-batch-sizes ${TRITON_PREFERRED_BATCH_SIZES} \ - --max-queue-delay-us ${TRITON_MAX_QUEUE_DELAY} \ - --engine-count-per-device ${DEVICE}=${TRITON_GPU_ENGINE_COUNT} -``` - -
- - -#### Prepare Triton Profiling Data -Prepare data used for profiling on Triton server. -
-Prepare Triton Profiling Data Command - -```shell -mkdir -p ${SHARED_DIR}/input_data - -python triton/prepare_input_data.py \ - --input-data-dir ${SHARED_DIR}/input_data/ \ - --dataset ${DATASETS_DIR}/${DATASET} \ - --checkpoint ${CHECKPOINT_DIR}/ \ -``` - -
- - - -#### Triton Performance Offline Test -We want to maximize throughput. It assumes you have your data available -for inference or that your data saturate to maximum batch size quickly. -Triton Inference Server supports offline scenarios with static batching. -Static batching allows inference requests to be served -as they are received. The largest improvements to throughput come -from increasing the batch size due to efficiency gains in the GPU with larger -batches. -
-Triton Performance Offline Test Command - -```shell -python triton/run_performance_on_triton.py \ - --model-repository ${MODEL_REPOSITORY_PATH} \ - --model-name ${MODEL_NAME} \ - --input-data ${SHARED_DIR}/input_data/data.json \ - --batch-sizes ${BATCH_SIZE} \ - --number-of-triton-instances ${TRITON_INSTANCES} \ - --batching-mode static \ - --evaluation-mode offline \ - --measurement-request-count ${REQUEST_COUNT} \ - --warmup \ - --performance-tool perf_analyzer \ - --result-path ${SHARED_DIR}/triton_performance_offline.csv -``` - -
- - - -#### Triton Performance Online Test -We want to maximize throughput within latency budget constraints. -Dynamic batching is a feature of Triton Inference Server that allows -inference requests to be combined by the server, so that a batch is -created dynamically, resulting in a reduced average latency. -
-Triton Performance Online Test - -```shell -python triton/run_performance_on_triton.py \ - --model-repository ${MODEL_REPOSITORY_PATH} \ - --model-name ${MODEL_NAME} \ - --input-data ${SHARED_DIR}/input_data/data.json \ - --batch-sizes ${BATCH_SIZE} \ - --number-of-triton-instances ${TRITON_INSTANCES} \ - --number-of-model-instances ${TRITON_GPU_ENGINE_COUNT} \ - --batching-mode dynamic \ - --evaluation-mode online \ - --measurement-request-count 500 \ - --warmup \ - --performance-tool perf_analyzer \ - --result-path ${SHARED_DIR}/triton_performance_online.csv -``` - - -
- -### Latency explanation -A typical Triton Inference Server pipeline can be broken down into the following steps: - -1. The client serializes the inference request into a message and sends it to -the server (Client Send). -2. The message travels over the network from the client to the server (Network). -3. The message arrives at the server and is deserialized (Server Receive). -4. The request is placed on the queue (Server Queue). -5. The request is removed from the queue and computed (Server Compute). -6. The completed request is serialized in a message and sent back to -the client (Server Send). -7. The completed message then travels over the network from the server -to the client (Network). -8. The completed message is deserialized by the client and processed as -a completed inference request (Client Receive). - -Generally, for local clients, steps 1-4 and 6-8 will only occupy -a small fraction of time, compared to step 5. As backend deep learning -systems like TFT are rarely exposed directly to end users, but instead -only interfacing with local front-end servers, for the sake of TFT, -we can consider that all clients are local. - - - -## Release Notes -We’re constantly refining and improving our performance on AI -and HPC workloads even on the same hardware with frequent updates -to our software stack. For our latest performance data refer -to these pages for -[AI](https://developer.nvidia.com/deep-learning-performance-training-inference) -and [HPC](https://developer.nvidia.com/hpc-application-performance) benchmarks. - -### Changelog -### Known issues - -- There are no known issues with this model. \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/calculate_metrics.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/calculate_metrics.py deleted file mode 100755 index f20155849..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/calculate_metrics.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -r""" -Using `calculate_metrics.py` script, you can obtain model accuracy/error metrics using defined `MetricsCalculator` class. - -Data provided to `MetricsCalculator` are obtained from dump files -stored in directory pointed by `--dump-dir` argument. -Above files are prepared by `run_inference_on_fw.py` and `run_inference_on_triton.py` scripts. - -Output data is stored in csv file pointed by `--csv` argument. - -Example call: - -```shell script -python ./triton/calculate_metrics.py \ - --dump-dir /results/dump_triton \ - --csv /results/accuracy_results.csv \ - --metrics metrics.py \ - --metric-class-param1 value -``` -""" - -import argparse -import csv -import logging -import string -from pathlib import Path - -# method from PEP-366 to support relative import in executed modules - -if __package__ is None: - __package__ = Path(__file__).parent.name - -from .deployment_toolkit.args import ArgParserGenerator -from .deployment_toolkit.core import BaseMetricsCalculator, load_from_file -from .deployment_toolkit.dump import JsonDumpReader - -LOGGER = logging.getLogger("calculate_metrics") -TOTAL_COLUMN_NAME = "_total_" - - -def main(): - logging.basicConfig(level=logging.INFO) - - parser = argparse.ArgumentParser(description="Run models with given dataloader", allow_abbrev=False) - parser.add_argument("--metrics", help="Path to python module containing metrics calculator", required=True) - parser.add_argument("--csv", help="Path to csv file", required=True) - parser.add_argument("--dump-dir", help="Path to directory with dumped outputs (and labels)", required=True) - - args, *_ = parser.parse_known_args() - - MetricsCalculator = load_from_file(args.metrics, "metrics", "MetricsCalculator") - ArgParserGenerator(MetricsCalculator).update_argparser(parser) - - args = parser.parse_args() - - LOGGER.info("args:") - for key, value in vars(args).items(): - LOGGER.info(f" {key} = {value}") - - MetricsCalculator = load_from_file(args.metrics, "metrics", "MetricsCalculator") - metrics_calculator: BaseMetricsCalculator = ArgParserGenerator(MetricsCalculator).from_args(args) - - reader = JsonDumpReader(args.dump_dir) - for ids, x, y_true, y_pred in reader.iterate_over(["ids", "inputs", "labels", "outputs"]): - ids = list(ids["ids"]) if ids is not None else None - metrics_calculator.update(ids=ids, x=x, y_pred=y_pred, y_real=y_true) - metrics = metrics_calculator.metrics - - metric_names_with_space = [name for name in metrics if any([c in string.whitespace for c in name])] - if metric_names_with_space: - raise ValueError(f"Metric names shall have no spaces; Incorrect names: {', '.join(metric_names_with_space)}") - - csv_path = Path(args.csv) - csv_path.parent.mkdir(parents=True, exist_ok=True) - with csv_path.open("w") as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=list(metrics.keys())) - writer.writeheader() - writer.writerow(metrics) - - -if __name__ == "__main__": - main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/dataloader.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/dataloader.py deleted file mode 100644 index d9813baf2..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/dataloader.py +++ /dev/null @@ -1,31 +0,0 @@ -import os -import numpy as np -import torch -from torch.utils.data import DataLoader -from data_utils import TFTDataset - -def update_argparser(parser): - parser.add_argument("--dataset", type=str, help="Path to dataset to be used", required=True) - parser.add_argument("--checkpoint", type=str, help="Path to checkpoint to be used", required=True) - parser.add_argument("--batch-size", type=int, help="Path to dataset to be used", default=64) - - -def get_dataloader_fn(dataset, checkpoint, batch_size=64): - state_dict = torch.load(os.path.join(checkpoint, "checkpoint.pt")) - config = state_dict['config'] - test_split = TFTDataset(os.path.join(dataset, "test.csv"), config) - data_loader = DataLoader(test_split, batch_size=int(batch_size), num_workers=2) - input_names_dict = {'s_cat': 's_cat__0', 's_cont':'s_cont__1', 'k_cat':'k_cat__2', 'k_cont':'k_cont__3', 'o_cat':'o_cat__4', 'o_cont':'o_cont__5', 'target':'target__6', 'id':'id__7'} - reshaper = [-1] + [1] - - def _get_dataloader(): - for step, batch in enumerate(data_loader): - bs = batch['target'].shape[0] - x = {input_names_dict[key]: tensor.numpy() if tensor.numel() else np.ones([bs]).reshape(reshaper) for key, tensor in batch.items()} - ids = batch['id'][:,0,:].numpy() - # ids = np.arange(step * batch_size, (step + 1) * batch_size) - y_real = {'target__0':np.tile(batch['target'][:,config.encoder_length:,:].numpy(), (1, 1, len(config.quantiles)))} - yield (ids, x, y_real) - - - return _get_dataloader \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/.version b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/.version deleted file mode 100644 index 8fd9b8c37..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/.version +++ /dev/null @@ -1 +0,0 @@ -0.7.11 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/onnx.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/onnx.py deleted file mode 100644 index 2b93b9f06..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/onnx.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -from pathlib import Path -from typing import Dict, Optional, Union - -import numpy as np - -# pytype: disable=import-error -import onnx -import onnx.shape_inference -import onnxruntime -from google.protobuf import text_format -from onnx.mapping import TENSOR_TYPE_TO_NP_TYPE - -from ..core import BaseLoader, BaseRunner, BaseRunnerSession, BaseSaver, Format, Model, Precision, TensorSpec -from ..extensions import loaders, runners, savers -from .utils import infer_precision - -# pytype: enable=import-error - - -LOGGER = logging.getLogger(__name__) - - -def _value_info2tensor_spec(value_info: onnx.ValueInfoProto): - onnx_data_type_map = {"float": "float32", "double": "float64"} - - elem_type_name = onnx.TensorProto.DataType.Name(value_info.type.tensor_type.elem_type).lower() - dtype = onnx_data_type_map.get(elem_type_name, elem_type_name) - - def _get_dim(dim): - which = dim.WhichOneof("value") - if which is not None: # which is None when dim is None - dim = getattr(dim, which) - return None if isinstance(dim, (str, bytes)) else dim - - shape = value_info.type.tensor_type.shape - shape = tuple(_get_dim(d) for d in shape.dim) - return TensorSpec(value_info.name, dtype=dtype, shape=shape) - - -def _infer_graph_precision(onnx_graph: onnx.GraphProto) -> Optional[Precision]: - import networkx as nx - - # build directed graph - nx_graph = nx.DiGraph() - - def _get_dtype(vi): - t = vi.type - if hasattr(t, "tensor_type"): - type_id = t.tensor_type.elem_type - else: - raise NotImplementedError("Not implemented yet") - return TENSOR_TYPE_TO_NP_TYPE[type_id] - - node_output2type = {vi.name: _get_dtype(vi) for vi in onnx_graph.value_info} - - node_outputs2node = {output_name: node for node in onnx_graph.node for output_name in node.output} - node_inputs2node = {input_name: node for node in onnx_graph.node for input_name in node.input} - - for node in onnx_graph.node: - node_dtype = node_output2type.get("+".join(node.output), None) - nx_graph.add_node( - node.name, - op=node.op_type, - attr={a.name: a for a in node.attribute}, - dtype=node_dtype, - ) - for input_name in node.input: - prev_node = node_outputs2node.get(input_name, None) - if prev_node: - nx_graph.add_edge(prev_node.name, node.name) - - for input_node in onnx_graph.input: - input_name = input_node.name - nx_graph.add_node(input_name, op="input", dtype=_get_dtype(input_node)) - next_node = node_inputs2node.get(input_name, None) - if next_node: - nx_graph.add_edge(input_name, next_node.name) - - for output in onnx_graph.output: - output_name = output.name - nx_graph.add_node(output_name, op="output", dtype=_get_dtype(output)) - prev_node = node_outputs2node.get(output_name, None) - if prev_node: - nx_graph.add_edge(prev_node.name, output_name) - else: - LOGGER.warning(f"Could not find previous node for {output_name}") - - input_names = [n.name for n in onnx_graph.input] - output_names = [n.name for n in onnx_graph.output] - most_common_dtype = infer_precision(nx_graph, input_names, output_names, lambda node: node.get("dtype", None)) - if most_common_dtype is not None: - precision = {np.dtype("float32"): Precision.FP32, np.dtype("float16"): Precision.FP16}[most_common_dtype] - else: - precision = None - return precision - - -class OnnxLoader(BaseLoader): - def load(self, model_path: Union[str, Path], **_) -> Model: - if isinstance(model_path, Path): - model_path = model_path.as_posix() - - model = onnx.load(model_path) - onnx.checker.check_model(model) - onnx.helper.strip_doc_string(model) - model = onnx.shape_inference.infer_shapes(model) - - # TODO: probably modification of onnx model ios causes error on optimize - # from onnx.utils import polish_model - # model = polish_model(model) # run checker, docs strip, optimizer and shape inference - - inputs = {vi.name: _value_info2tensor_spec(vi) for vi in model.graph.input} - outputs = {vi.name: _value_info2tensor_spec(vi) for vi in model.graph.output} - - precision = _infer_graph_precision(model.graph) - - return Model(model, precision, inputs, outputs) - - -class OnnxSaver(BaseSaver): - def __init__(self, as_text: bool = False): - self._as_text = as_text - - def save(self, model: Model, model_path: Union[str, Path], dataloader_fn) -> None: - model_path = Path(model_path) - LOGGER.debug(f"Saving ONNX model to {model_path.as_posix()}") - model_path.parent.mkdir(parents=True, exist_ok=True) - - onnx_model: onnx.ModelProto = model.handle - if self._as_text: - with model_path.open("w") as f: - f.write(text_format.MessageToString(onnx_model)) - else: - with model_path.open("wb") as f: - f.write(onnx_model.SerializeToString()) - - -""" -ExecutionProviders on onnxruntime 1.4.0 -['TensorrtExecutionProvider', - 'CUDAExecutionProvider', - 'MIGraphXExecutionProvider', - 'NGRAPHExecutionProvider', - 'OpenVINOExecutionProvider', - 'DnnlExecutionProvider', - 'NupharExecutionProvider', - 'VitisAIExecutionProvider', - 'ArmNNExecutionProvider', - 'ACLExecutionProvider', - 'CPUExecutionProvider'] -""" - - -def _check_providers(providers): - providers = providers or [] - if not isinstance(providers, (list, tuple)): - providers = [providers] - available_providers = onnxruntime.get_available_providers() - unavailable = set(providers) - set(available_providers) - if unavailable: - raise RuntimeError(f"Unavailable providers {unavailable}") - return providers - - -class OnnxRunner(BaseRunner): - def __init__(self, verbose_runtime_logs: bool = False): - self._providers = None - self._verbose_runtime_logs = verbose_runtime_logs - - def init_inference(self, model: Model): - assert isinstance(model.handle, onnx.ModelProto) - return OnnxRunnerSession( - model=model, providers=self._providers, verbose_runtime_logs=self._verbose_runtime_logs - ) - - -class OnnxRunnerSession(BaseRunnerSession): - def __init__(self, model: Model, providers, verbose_runtime_logs: bool = False): - super().__init__(model) - self._input_names = None - self._output_names = None - self._session = None - self._providers = providers - self._verbose_runtime_logs = verbose_runtime_logs - self._old_env_values = {} - - def __enter__(self): - self._old_env_values = self._set_env_variables() - sess_options = onnxruntime.SessionOptions() # default session options - if self._verbose_runtime_logs: - sess_options.log_severity_level = 0 - sess_options.log_verbosity_level = 1 - LOGGER.info( - f"Starting inference session for onnx model providers={self._providers} sess_options={sess_options}" - ) - - self._input_names = list(self._model.inputs) - self._output_names = list(self._model.outputs) - - model_payload = self._model.handle.SerializeToString() - self._session = onnxruntime.InferenceSession( - model_payload, providers=self._providers, sess_options=sess_options - ) - return self - - def __exit__(self, exc_type, exc_value, traceback): - self._input_names = None - self._output_names = None - self._session = None - self._recover_env_variables(self._old_env_values) - - def __call__(self, x: Dict[str, object]): - feed_dict = {k: x[k] for k in self._input_names} - y_pred = self._session.run(self._output_names, feed_dict) - y_pred = dict(zip(self._output_names, y_pred)) - - return y_pred - - -loaders.register_extension(Format.ONNX.value, OnnxLoader) -runners.register_extension(Format.ONNX.value, OnnxRunner) -savers.register_extension(Format.ONNX.value, OnnxSaver) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/pyt.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/pyt.py deleted file mode 100644 index 114b47f69..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/pyt.py +++ /dev/null @@ -1,293 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import typing -from collections import Counter -from pathlib import Path -from typing import Dict, Optional, Union - -import numpy as np -import torch # pytype: disable=import-error -import yaml -from model_navigator.model import ModelSignatureConfig -from model_navigator.tensor import TensorSpec -from model_navigator.utils.config import YamlConfigFile - -from ..core import ( - GET_MODEL_FN_NAME, - BaseLoader, - BaseRunner, - BaseRunnerSession, - BaseSaver, - Format, - Model, - Precision, - load_from_file, -) -from ..extensions import loaders, runners, savers -from .utils import get_dynamic_axes, get_shapes_with_dynamic_axes - -LOGGER = logging.getLogger(__name__) - - -def get_sample_input(dataloader, device): - for batch in dataloader: - _, x, _ = batch - break - if isinstance(x, dict): - sample_input = list(x.values()) - elif isinstance(x, list): - sample_input = x - else: - raise TypeError("The first element (x) of batch returned by dataloader must be a list or a dict") - - for idx, s in enumerate(sample_input): - sample_input[idx] = torch.from_numpy(s).to(device) - - return tuple(sample_input) - - -def get_model_device(torch_model): - if next(torch_model.parameters()).is_cuda: - return "cuda" - else: - return "cpu" - - -def infer_model_precision(model): - counter = Counter() - for param in model.parameters(): - counter[param.dtype] += 1 - if counter[torch.float16] > 0: - return Precision.FP16 - else: - return Precision.FP32 - - -def _get_tensor_dtypes(dataloader, precision): - def _get_dtypes(t): - def _get_dtype(v): - dtype = str(v.dtype) - if dtype == "float64": - dtype = "float32" - if precision == Precision.FP16 and dtype == "float32": - dtype = "float16" - return np.dtype(dtype) - - return {k: _get_dtype(v) for k, v in t.items()} - - batch = next(dataloader) - _, x, y = batch - input_dtypes = _get_dtypes(x) - output_dtypes = _get_dtypes(y) - - return input_dtypes, output_dtypes - - -### TODO assumption: floating point input -### type has same precision as the model -def _get_model_signature( - inputs_names: typing.List[str], - outputs_names: typing.List[str], - precision, - dataloader_fn, - batch_size_dim: typing.Optional[int] = None, -): - dataloader = dataloader_fn() - input_dtypes, output_dtypes = _get_tensor_dtypes(dataloader, precision) - input_shapes, output_shapes = get_shapes_with_dynamic_axes(dataloader, batch_size_dim=batch_size_dim) - - inputs = { - name: TensorSpec(name=name, dtype=input_dtypes[name], shape=tuple(input_shapes[name])) for name in inputs_names - } - outputs = { - name: TensorSpec(name=name, dtype=output_dtypes[name], shape=tuple(output_shapes[name])) - for name in outputs_names - } - - return ModelSignatureConfig(inputs, outputs) - - -class PyTorchModelLoader(BaseLoader): - required_fn_name_for_signature_parsing: Optional[str] = GET_MODEL_FN_NAME - - def __init__(self, **kwargs): - self._model_args = kwargs - - def load(self, model_path: Union[str, Path], **kwargs) -> Model: - if isinstance(model_path, Path): - model_path = model_path.as_posix() - - get_model = load_from_file(model_path, "model", GET_MODEL_FN_NAME) - model, io_names_dict = get_model(**self._model_args) - - dataloader_fn = kwargs.get("dataloader_fn", None) - output_type = kwargs.get("output_type", None) - precision = infer_model_precision(model) - - batch_axis = getattr(model, "bermuda_batch_axis", 0) # by default models supports batching; batch_axis=0 - - model_signature = _get_model_signature( - inputs_names=io_names_dict["inputs"], - outputs_names=io_names_dict["outputs"], - precision=precision, - dataloader_fn=dataloader_fn, - batch_size_dim=batch_axis, - ) - - model = Model(handle=model, precision=precision, inputs=model_signature.inputs, outputs=model_signature.outputs) - - if output_type == Format.TS_TRACE.value: - return self._trace(model, dataloader_fn) - elif output_type == Format.TS_SCRIPT.value: - return self._script(model) - elif output_type == Format.ONNX.value: - return model - else: - raise ValueError(f"Not supported PyTorch format: {output_type}") - - def _trace(self, model: Model, dataloader_fn) -> Model: - device = get_model_device(model.handle) - dummy_input = get_sample_input(dataloader_fn(), device) - traced_model = torch.jit.trace_module(model.handle, {"forward": dummy_input}) - return Model(traced_model, precision=model.precision, inputs=model.inputs, outputs=model.outputs) - - def _script(self, model: Model) -> Model: - scripted_model = torch.jit.script(model.handle) - return Model(scripted_model, precision=model.precision, inputs=model.inputs, outputs=model.outputs) - - -class TorchScriptLoader(BaseLoader): - def __init__(self, tensor_names_path: str = None, **kwargs): - self._model_args = kwargs - self._io_spec = None - if tensor_names_path is not None: - with Path(tensor_names_path).open("r") as fh: - tensor_infos = yaml.load(fh, Loader=yaml.SafeLoader) - self._io_spec = ModelSignatureConfig(tensor_infos["inputs"], tensor_infos["outputs"]) - - def load(self, model_path: Union[str, Path], **_) -> Model: - if not isinstance(model_path, Path): - model_path = Path(model_path) - model = torch.jit.load(model_path.as_posix()) - precision = infer_model_precision(model) - - io_spec = self._io_spec - if not io_spec: - yaml_path = model_path.parent / f"{model_path.name}.yaml" - if not yaml_path.is_file(): - raise ValueError( - f"If `--tensor-names-path is not provided, " - f"TorchScript model loader expects file {yaml_path} with tensor information." - ) - with yaml_path.open("r") as fh: - tensor_info = yaml.load(fh, Loader=yaml.SafeLoader) - io_spec = ModelSignatureConfig(tensor_info["inputs"], tensor_info["outputs"]) - - return Model(handle=model, precision=precision, inputs=io_spec.inputs, outputs=io_spec.outputs) - - -class PYT2ONNXSaver(BaseSaver): - def __init__(self, onnx_opset: int = None): - self._onnx_opset = onnx_opset - - def save(self, model: Model, model_path: Union[str, Path], dataloader_fn) -> Model: - if isinstance(model_path, Path): - model_path = model_path.as_posix() - assert isinstance(model.handle, torch.jit.ScriptModule) or isinstance( - model.handle, torch.nn.Module - ), "The model must be of type 'torch.jit.ScriptModule' or 'torch.nn.Module'. Converter aborted." - dynamic_axes = get_dynamic_axes(dataloader_fn(), batch_size_dim=0) - - device = get_model_device(model.handle) - dummy_input = get_sample_input(dataloader_fn(), device) - with torch.no_grad(): - torch.onnx.export( - model.handle, - dummy_input, - model_path, - do_constant_folding=True, - input_names=list(model.inputs), - output_names=list(model.outputs), - dynamic_axes=dynamic_axes, - opset_version=self._onnx_opset, - ) - - -class TorchScriptSaver(BaseSaver): - def save(self, model: Model, model_path: Union[str, Path], dataloader_fn) -> None: - if not isinstance(model_path, Path): - model_path = Path(model_path) - if isinstance(model.handle, torch.jit.ScriptModule): - torch.jit.save(model.handle, model_path.as_posix()) - else: - raise RuntimeError("The model must be of type 'torch.jit.ScriptModule'. Saving aborted.") - - signature_config = ModelSignatureConfig(inputs=model.inputs, outputs=model.outputs) - annotation_path = model_path.parent / f"{model_path.name}.yaml" - with YamlConfigFile(annotation_path) as config_file: - config_file.save_config(signature_config) - - -class PyTorchRunner(BaseRunner): - def __init__(self): - pass - - def init_inference(self, model: Model): - return PyTorchRunnerSession(model=model) - - -class PyTorchRunnerSession(BaseRunnerSession): - def __init__(self, model: Model): - super().__init__(model) - - assert isinstance(model.handle, torch.jit.ScriptModule) or isinstance( - model.handle, torch.nn.Module - ), "The model must be of type 'torch.jit.ScriptModule' or 'torch.nn.Module'. Runner aborted." - - self._model = model - self._output_names = None - - def __enter__(self): - self._output_names = list(self._model.outputs) - return self - - def __exit__(self, exc_type, exc_value, traceback): - self._output_names = None - self._model = None - - def __call__(self, x: Dict[str, object]): - with torch.no_grad(): - feed_list = [torch.from_numpy(v).cuda() for k, v in x.items()] - y_pred = self._model.handle(*feed_list) - if isinstance(y_pred, torch.Tensor): - y_pred = (y_pred,) - y_pred = [t.cpu().numpy() for t in y_pred] - y_pred = dict(zip(self._output_names, y_pred)) - - return y_pred - - -loaders.register_extension(Format.PYT.value, PyTorchModelLoader) -loaders.register_extension(Format.TS_TRACE.value, TorchScriptLoader) -loaders.register_extension(Format.TS_SCRIPT.value, TorchScriptLoader) - -savers.register_extension(Format.TS_SCRIPT.value, TorchScriptSaver) -savers.register_extension(Format.TS_TRACE.value, TorchScriptSaver) -savers.register_extension(f"{Format.PYT.value}--{Format.ONNX.value}", PYT2ONNXSaver) - -runners.register_extension(Format.PYT.value, PyTorchRunner) -runners.register_extension(Format.TS_SCRIPT.value, PyTorchRunner) -runners.register_extension(Format.TS_TRACE.value, PyTorchRunner) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/tensorrt.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/tensorrt.py deleted file mode 100644 index d6adb6de0..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/tensorrt.py +++ /dev/null @@ -1,232 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import sys -from pathlib import Path -from typing import Dict, NamedTuple, Optional, Union - -import numpy as np - -# pytype: disable=import-error -try: - import pycuda.autoinit - import pycuda.driver as cuda -except Exception as e: - logging.getLogger(__name__).warning(f"Problems with importing pycuda package; {e}") -# pytype: enable=import-error - -import tensorrt as trt # pytype: disable=import-error - -from ..core import BaseLoader, BaseRunner, BaseRunnerSession, Format, Model, TensorSpec -from ..extensions import loaders, runners - -LOGGER = logging.getLogger(__name__) -TRT_LOGGER = trt.Logger(trt.Logger.INFO) - -# documentation: -# https://docs.nvidia.com/deeplearning/tensorrt/api/python_api/index.html -# https://docs.nvidia.com/deeplearning/tensorrt/developer-guide/index.html#python_samples_section - -_NP_DTYPE2TRT_DTYPE = { - np.dtype("float32"): trt.DataType.FLOAT, - np.dtype("float16"): trt.DataType.HALF, - np.dtype("int8"): trt.DataType.INT8, - np.dtype("int32"): trt.DataType.INT32, - np.dtype("bool"): trt.DataType.BOOL, -} - - -class TensorRTLoader(BaseLoader): - def load(self, model_path: Union[str, Path], **_) -> Model: - model_path = Path(model_path) - LOGGER.debug(f"Loading TensorRT engine from {model_path}") - engine = self._load_engine(model_path) - - if engine is None: - LOGGER.debug("Unable to load engine without plugins. Loading plugins.") - trt.init_libnvinfer_plugins(logger=TRT_LOGGER, namespace="") - LOGGER.debug(f"Loading TensorRT engine with plugins from {model_path}") - engine = self._load_engine(model_path) - - if engine is None: - raise RuntimeError(f"Could not load ICudaEngine from {model_path}") - - inputs = {} - outputs = {} - for binding_idx in range(engine.num_bindings): - name = engine.get_binding_name(binding_idx) - is_input = engine.binding_is_input(binding_idx) - dtype = np.dtype(trt.nptype(engine.get_binding_dtype(binding_idx))).name - shape = engine.get_binding_shape(binding_idx) - if is_input: - inputs[name] = TensorSpec(name, dtype, shape) - else: - outputs[name] = TensorSpec(name, dtype, shape) - - return Model(engine, None, inputs, outputs) - - def _load_engine(self, model_path: Path): - with model_path.open("rb") as fh, trt.Runtime(TRT_LOGGER) as runtime: - engine = runtime.deserialize_cuda_engine(fh.read()) - - return engine - - -class TRTBuffers(NamedTuple): - x_host: Optional[Dict[str, object]] - x_dev: Dict[str, object] - y_pred_host: Dict[str, object] - y_pred_dev: Dict[str, object] - - -class TensorRTRunner(BaseRunner): - def __init__(self): - pass - - def init_inference(self, model: Model): - return TensorRTRunnerSession(model=model) - - -class TensorRTRunnerSession(BaseRunnerSession): - def __init__(self, model: Model): - super().__init__(model) - assert isinstance(model.handle, trt.ICudaEngine) - self._model = model - self._has_dynamic_shapes = None - - self._context = None - self._engine: trt.ICudaEngine = self._model.handle - self._cuda_context = pycuda.autoinit.context - - self._input_names = None - self._output_names = None - self._buffers = None - - def __enter__(self): - self._context = self._engine.create_execution_context() - self._context.__enter__() - - self._input_names = [ - self._engine[idx] for idx in range(self._engine.num_bindings) if self._engine.binding_is_input(idx) - ] - self._output_names = [ - self._engine[idx] for idx in range(self._engine.num_bindings) if not self._engine.binding_is_input(idx) - ] - # all_binding_shapes_specified is True for models without dynamic shapes - # so initially this variable is False for models with dynamic shapes - self._has_dynamic_shapes = not self._context.all_binding_shapes_specified - - return self - - def __exit__(self, exc_type, exc_value, traceback): - self._context.__exit__(exc_type, exc_value, traceback) - self._input_names = None - self._output_names = None - - # TODO: are cuda buffers dealloc automatically? - self._buffers = None - - def __call__(self, x): - buffers = self._prepare_buffers_if_needed(x) - bindings = self._update_bindings(buffers) - - for name in self._input_names: - cuda.memcpy_htod(buffers.x_dev[name], buffers.x_host[name]) - self._cuda_context.push() - self._context.execute_v2(bindings=bindings) - self._cuda_context.pop() - for name in self._output_names: - cuda.memcpy_dtoh(buffers.y_pred_host[name], buffers.y_pred_dev[name]) - - return buffers.y_pred_host - - def _update_bindings(self, buffers: TRTBuffers): - bindings = [None] * self._engine.num_bindings - for name in buffers.y_pred_dev: - binding_idx: int = self._engine[name] - bindings[binding_idx] = buffers.y_pred_dev[name] - - for name in buffers.x_dev: - binding_idx: int = self._engine[name] - bindings[binding_idx] = buffers.x_dev[name] - - return bindings - - def _set_dynamic_input_shapes(self, x_host): - def _is_shape_dynamic(input_shape): - return any([dim is None or dim == -1 for dim in input_shape]) - - for name in self._input_names: - bindings_idx = self._engine[name] - data_shape = x_host[name].shape # pytype: disable=attribute-error - if self._engine.is_shape_binding(bindings_idx): - input_shape = self._context.get_shape(bindings_idx) - if _is_shape_dynamic(input_shape): - self._context.set_shape_input(bindings_idx, data_shape) - else: - input_shape = self._engine.get_binding_shape(bindings_idx) - if _is_shape_dynamic(input_shape): - self._context.set_binding_shape(bindings_idx, data_shape) - - assert self._context.all_binding_shapes_specified and self._context.all_shape_inputs_specified - - def _prepare_buffers_if_needed(self, x_host: Dict[str, object]): - # pytype: disable=attribute-error - new_batch_size = list(x_host.values())[0].shape[0] - current_batch_size = list(self._buffers.y_pred_host.values())[0].shape[0] if self._buffers else 0 - # pytype: enable=attribute-error - - if self._has_dynamic_shapes or new_batch_size != current_batch_size: - # TODO: are CUDA buffers dealloc automatically? - - self._set_dynamic_input_shapes(x_host) - - y_pred_host = {} - for name in self._output_names: - shape = self._context.get_binding_shape(self._engine[name]) - binding_idx: int = self._engine[name] - dtype_from_trt_binding = np.dtype(trt.nptype(self._engine.get_binding_dtype(binding_idx))) - dtype_from_model_spec = np.dtype(self._model.outputs[name].dtype) - - assert dtype_from_model_spec == dtype_from_trt_binding - - y_pred_host[name] = np.zeros(shape, dtype=dtype_from_model_spec) - - y_pred_dev = {name: cuda.mem_alloc(data.nbytes) for name, data in y_pred_host.items()} - - # cast host input into binding dtype - def _cast_input(name, data): - binding_idx: int = self._engine[name] - np_dtype = trt.nptype(self._engine.get_binding_dtype(binding_idx)) - return data.astype(np_dtype) - - x_host = {name: _cast_input(name, host_input) for name, host_input in x_host.items()} - - x_dev = { - name: cuda.mem_alloc(host_input.nbytes) - for name, host_input in x_host.items() - if name in self._input_names # pytype: disable=attribute-error - } - - self._buffers = TRTBuffers(None, x_dev, y_pred_host, y_pred_dev) - - return self._buffers._replace(x_host=x_host) - - -if "pycuda.driver" in sys.modules: - loaders.register_extension(Format.TRT.value, TensorRTLoader) - runners.register_extension(Format.TRT.value, TensorRTRunner) -else: - LOGGER.warning("Do not register TensorRT extension due problems with importing pycuda.driver package.") diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/utils.py deleted file mode 100644 index 686f37a8f..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/bermuda/utils.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from collections import Counter -from typing import Callable, Dict, List, Optional - -import networkx as nx - -from ..core import ShapeSpec - - -def infer_precision( - nx_graph: nx.Graph, - input_names: List[str], - output_names: List[str], - get_node_dtype_fn: Callable, -): - node_dtypes = [nx_graph.nodes[node_name].get("dtype", None) for node_name in nx_graph.nodes] - node_dtypes = [dt for dt in node_dtypes if dt is None or dt.kind not in ["i", "b"]] - dtypes_counter = Counter(node_dtypes) - return dtypes_counter.most_common()[0][0] - - -def get_shapes_with_dynamic_axes(dataloader, batch_size_dim: Optional[int] = None): - def _set_dynamic_shapes(t, shapes): - for k, v in t.items(): - shape = list(v.shape) - for dim, s in enumerate(shape): - if shapes[k][dim] != -1 and shapes[k][dim] != s: - shapes[k][dim] = -1 - - def _mark_batch_axis(shape, batch_axis: int): - shape = list(shape) - shape[batch_axis] = -1 - return tuple(shape) - - ## get all shapes from input and output tensors - input_shapes = {} - output_shapes = {} - for batch in dataloader: - _, x, y = batch - for k, v in x.items(): - input_shapes[k] = list(v.shape) - for k, v in y.items(): - output_shapes[k] = list(v.shape) - break - - # based on max iterations, check which - # dimensions differ to determine dynamic_axes - max_num_iters = 100 - for idx, batch in enumerate(dataloader): - if idx >= max_num_iters: - break - - _, x, y = batch - - _set_dynamic_shapes(x, input_shapes) - _set_dynamic_shapes(y, output_shapes) - - if batch_size_dim is not None: - input_shapes = {name: _mark_batch_axis(shape, batch_size_dim) for name, shape in input_shapes.items()} - output_shapes = {name: _mark_batch_axis(shape, batch_size_dim) for name, shape in output_shapes.items()} - - return input_shapes, output_shapes - - -def get_dynamic_axes(dataloader, batch_size_dim: Optional[int] = None): - input_shapes, output_shapes = get_shapes_with_dynamic_axes(dataloader, batch_size_dim=batch_size_dim) - all_shapes = {**input_shapes, **output_shapes} - dynamic_axes = {} - - for k, shape in all_shapes.items(): - for idx, s in enumerate(shape): - if s == -1: - dynamic_axes[k] = {idx: k + "_" + str(idx)} - - for k in all_shapes: - if k in dynamic_axes: - dynamic_axes[k].update({batch_size_dim: "batch_size_" + str(batch_size_dim)}) - else: - dynamic_axes[k] = {batch_size_dim: "batch_size_" + str(batch_size_dim)} - - return dynamic_axes - - -def get_input_shapes(dataloader, max_batch_size=1) -> Dict[str, ShapeSpec]: - def init_counters_and_shapes(x, counters, min_shapes, max_shapes): - for k, v in x.items(): - counters[k] = Counter() - min_shapes[k] = [float("inf")] * v.ndim - max_shapes[k] = [float("-inf")] * v.ndim - - counters = {} - min_shapes: Dict[str, tuple] = {} - max_shapes: Dict[str, tuple] = {} - for idx, batch in enumerate(dataloader): - ids, x, y = batch - - if idx == 0: - init_counters_and_shapes(x, counters, min_shapes, max_shapes) - - for k, v in x.items(): - shape = v.shape - counters[k][shape] += 1 - min_shapes[k] = tuple(min(a, b) for a, b in zip(min_shapes[k], shape)) - max_shapes[k] = tuple(max(a, b) for a, b in zip(max_shapes[k], shape)) - - opt_shapes: Dict[str, tuple] = {} - for k, v in counters.items(): - opt_shapes[k] = v.most_common(1)[0][0] - - shapes = {} - for k in opt_shapes.keys(): # same keys in min_shapes and max_shapes - shapes[k] = ShapeSpec( - min=(1,) + min_shapes[k][1:], - max=(max_batch_size,) + max_shapes[k][1:], - opt=(max_batch_size,) + opt_shapes[k][1:], - ) - return shapes diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/core.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/core.py deleted file mode 100644 index c65617fce..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/core.py +++ /dev/null @@ -1,242 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import abc -import importlib -import logging -import os -from enum import Enum -from pathlib import Path -from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union - -import numpy as np - -LOGGER = logging.getLogger(__name__) -DATALOADER_FN_NAME = "get_dataloader_fn" -GET_MODEL_FN_NAME = "get_model" -GET_SERVING_INPUT_RECEIVER_FN = "get_serving_input_receiver_fn" -GET_ARGPARSER_FN_NAME = "update_argparser" - - -class TensorSpec(NamedTuple): - name: str - dtype: str - shape: Tuple - - -class Parameter(Enum): - def __lt__(self, other: "Parameter") -> bool: - return self.value < other.value - - def __str__(self): - return self.value - - -class Accelerator(Parameter): - NONE = "none" - AMP = "amp" - TRT = "trt" - - CUDA = NONE # backward compatibility - - -class Precision(Parameter): - INT8 = "int8" - FP16 = "fp16" - FP32 = "fp32" - TF32 = "tf32" # Deprecated - - -class Format(Parameter): - TF_GRAPHDEF = "tf-graphdef" - TF_SAVEDMODEL = "tf-savedmodel" - TF_TRT = "tf-trt" - TF_ESTIMATOR = "tf-estimator" - TF_KERAS = "tf-keras" - ONNX = "onnx" - TRT = "trt" - TS_SCRIPT = "ts-script" - TS_TRACE = "ts-trace" - PYT = "pyt" - FASTERTRANSFORMER = "fastertransformer" - - -class Model(NamedTuple): - handle: object - # TODO: precision should be removed - precision: Optional[Precision] - inputs: Dict[str, TensorSpec] - outputs: Dict[str, TensorSpec] - - -def load_from_file(file_path, label, target): - spec = importlib.util.spec_from_file_location(name=label, location=file_path) - my_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(my_module) # pytype: disable=attribute-error - return getattr(my_module, target, None) - - -class BaseLoader(abc.ABC): - required_fn_name_for_signature_parsing: Optional[str] = None - - @abc.abstractmethod - def load(self, model_path: Union[str, Path], **kwargs) -> Model: - """ - Loads and process model from file based on given set of args - """ - pass - - -class BaseSaver(abc.ABC): - required_fn_name_for_signature_parsing: Optional[str] = None - - @abc.abstractmethod - def save(self, model: Model, model_path: Union[str, Path], dataloader_fn) -> None: - """ - Save model to file - """ - pass - - -class BaseRunner(abc.ABC): - required_fn_name_for_signature_parsing: Optional[str] = None - - @abc.abstractmethod - def init_inference(self, model: Model): - raise NotImplementedError - - -class BaseRunnerSession(abc.ABC): - def __init__(self, model: Model): - self._model = model - - @abc.abstractmethod - def __enter__(self): - raise NotImplementedError() - - @abc.abstractmethod - def __exit__(self, exc_type, exc_value, traceback): - raise NotImplementedError() - - @abc.abstractmethod - def __call__(self, x: Dict[str, object]): - raise NotImplementedError() - - def _set_env_variables(self) -> Dict[str, object]: - """this method not remove values; fix it if needed""" - to_set = {} - old_values = {k: os.environ.pop(k, None) for k in to_set} - os.environ.update(to_set) - return old_values - - def _recover_env_variables(self, old_envs: Dict[str, object]): - for name, value in old_envs.items(): - if value is None: - del os.environ[name] - else: - os.environ[name] = str(value) - - -class BaseConverter(abc.ABC): - required_fn_name_for_signature_parsing: Optional[str] = None - - @abc.abstractmethod - def convert(self, model: Model, dataloader_fn) -> Model: - raise NotImplementedError() - - @staticmethod - def required_source_model_precision(requested_model_precision: Precision) -> Precision: - return requested_model_precision - - -class BaseMetricsCalculator(abc.ABC): - required_fn_name_for_signature_parsing: Optional[str] = None - - def calc( - self, - *, - ids: List[Any], - y_pred: Dict[str, np.ndarray], - x: Optional[Dict[str, np.ndarray]], - y_real: Optional[Dict[str, np.ndarray]], - ) -> Dict[str, float]: - """ - Calculates error/accuracy metrics - Args: - ids: List of ids identifying each sample in the batch - y_pred: model output as dict where key is output name and value is output value - x: model input as dict where key is input name and value is input value - y_real: input ground truth as dict where key is output name and value is output value - Returns: - dictionary where key is metric name and value is its value - """ - pass - - @abc.abstractmethod - def update( - self, - ids: List[Any], - y_pred: Dict[str, np.ndarray], - x: Optional[Dict[str, np.ndarray]], - y_real: Optional[Dict[str, np.ndarray]], - ): - pass - - @property - @abc.abstractmethod - def metrics(self) -> Dict[str, Any]: - pass - - -class ShapeSpec(NamedTuple): - min: Tuple - opt: Tuple - max: Tuple - - -class MeasurementMode(Enum): - COUNT_WINDOWS = "count_windows" - TIME_WINDOWS = "time_windows" - - -class PerformanceTool(Enum): - """ - Available performance evaluation tools - """ - - MODEL_ANALYZER = "model_analyzer" - PERF_ANALYZER = "perf_analyzer" - - -class BatchingMode(Enum): - """ - Available batching modes - """ - - STATIC = "static" - DYNAMIC = "dynamic" - - -class EvaluationMode(Enum): - """ - Available evaluation modes - """ - - OFFLINE = "offline" - ONLINE = "online" - - -class OfflineMode(Enum): - SYSTEM = "system" - CUDA = "cuda" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/extensions.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/extensions.py deleted file mode 100644 index c328b64f1..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/extensions.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import importlib -import logging -import os -import re -from pathlib import Path -from typing import List - -LOGGER = logging.getLogger(__name__) - - -class ExtensionManager: - def __init__(self, name: str): - self._name = name - self._registry = {} - - def register_extension(self, extension: str, clazz): - already_registered_class = self._registry.get(extension, None) - if already_registered_class and already_registered_class.__module__ != clazz.__module__: - raise RuntimeError( - f"Conflicting extension {self._name}/{extension}; " - f"{already_registered_class.__module__}.{already_registered_class.__name} " - f"and " - f"{clazz.__module__}.{clazz.__name__}" - ) - elif already_registered_class is None: - clazz_full_name = f"{clazz.__module__}.{clazz.__name__}" if clazz is not None else "None" - LOGGER.debug(f"Registering extension {self._name}/{extension}: {clazz_full_name}") - self._registry[extension] = clazz - - def get(self, extension): - if extension not in self._registry: - raise RuntimeError(f"Missing extension {self._name}/{extension}") - return self._registry[extension] - - @property - def supported_extensions(self): - return list(self._registry) - - @staticmethod - def scan_for_extensions(extension_dirs: List[Path]): - register_pattern = r".*\.register_extension\(.*" - - for extension_dir in extension_dirs: - for python_path in extension_dir.rglob("*.py"): - if not python_path.is_file(): - continue - payload = python_path.read_text() - if re.findall(register_pattern, payload): - import_path = python_path.relative_to(toolkit_root_dir.parent) - package = import_path.parent.as_posix().replace(os.sep, ".") - package_with_module = f"{package}.{import_path.stem}" - spec = importlib.util.spec_from_file_location(name=package_with_module, location=python_path) - my_module = importlib.util.module_from_spec(spec) - my_module.__package__ = package - - try: - spec.loader.exec_module(my_module) # pytype: disable=attribute-error - except ModuleNotFoundError as e: - LOGGER.error( - f"Could not load extensions from {import_path} due to missing python packages; {e}" - ) - - -runners = ExtensionManager("runners") -loaders = ExtensionManager("loaders") -savers = ExtensionManager("savers") -converters = ExtensionManager("converters") -toolkit_root_dir = (Path(__file__).parent / "..").resolve() -ExtensionManager.scan_for_extensions([toolkit_root_dir]) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/model_analyzer.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/model_analyzer.py deleted file mode 100644 index dfdc4dcdd..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/model_analyzer.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import logging -import subprocess -from subprocess import CalledProcessError - -from .exceptions import ModelAnalyzerException - -SERVER_OUTPUT_TIMEOUT_SECS = 5 -LOGGER = logging.getLogger(__name__) - - -class ModelAnalyzerMode: - PROFILE = "profile" - ANALYZE = "analyze" - REPORT = "report" - - -class ModelAnalyzerReportMode: - OFFLINE = "offline" - ONLINE = "online" - - -class ModelAnalyzer: - """ - Concrete Implementation of Model Analyzer interface that runs - analyzer locally as as subprocess. - """ - - _analyzer_path = "model-analyzer" - - def __init__(self, config): - """ - Parameters - ---------- - config : AnalyzerConfig - the config object containing arguments for this server instance - """ - - self._analyzer_process = None - self._analyzer_config = config - self._log = None - - def run(self, mode: str, verbose: bool = False, quiet: bool = False, report_mode: str = None): - """ - Starts the model analyzer locally - """ - - if self._analyzer_path: - - cmd = [self._analyzer_path] - if verbose: - cmd += ["--verbose"] - - if quiet: - cmd += ["--quiet"] - - if report_mode: - cmd += ["-m"] - cmd += [report_mode] - - cmd += [mode] - cmd += self._analyzer_config.to_cli_string().split() - - LOGGER.debug(f"Model Analyze command: {cmd}") - try: - subprocess.run(cmd, check=True, start_new_session=True) - - except CalledProcessError as e: - raise ModelAnalyzerException( - f"Running {self._analyzer_path} with {e.cmd} failed with" - f" exit status {e.returncode} : {e.output}" - ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/model_analyzer_config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/model_analyzer_config.py deleted file mode 100644 index 21dbb9656..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/model_analyzer/model_analyzer_config.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .exceptions import ModelAnalyzerException - - -class ModelAnalyzerConfig: - """ - A config class to set arguments to the Model Analyzer. - An argument set to None will use the default. - """ - - model_analyzer_args = [ - "config-file", - ] - - input_to_options = [ - "config-file", - ] - - def __init__(self): - # Args will be a dict with the string representation as key - self._args = {k: None for k in self.model_analyzer_args} - - self._options = { - "-f": "config.yaml", - } - - self._input_to_options = { - "config-file": "-f", - } - - def to_cli_string(self): - """ - Utility function to convert a config into a - string of arguments to the server with CLI. - Returns - ------- - str - the command consisting of all set arguments to - the model analyzer. - e.g. '--model-repository=/models --verbose=True' - """ - # single dashed options, then verbose flags, then main args - args = [f"{k} {v}" for k, v in self._options.items() if v] - args += [f"--{k}={v}" for k, v in self._args.items() if v] - - return " ".join(args) - - @classmethod - def allowed_keys(cls): - """ - Returns - ------- - list of str - The keys that are allowed to be - passed into model_analyzer - """ - - return list(cls.model_analyzer_args) + list(cls.input_to_options) - - def __getitem__(self, key): - """ - Gets an arguments value in config - Parameters - ---------- - key : str - The name of the argument to the model analyzer - Returns - ------- - The value that the argument is set to in this config - """ - - if key in self._args: - return self._args[key] - elif key in self._input_to_options: - return self._options[self._input_to_options[key]] - else: - raise ModelAnalyzerException(f"'{key}' Key not found in config") - - def __setitem__(self, key, value): - """ - Sets an arguments value in config - after checking if defined/supported. - Parameters - ---------- - key : str - The name of the argument to the model analyzer - value : (any) - The value to which the argument is being set - Raises - ------ - TritonModelAnalyzerException - If key is unsupported or undefined in the - config class - """ - if key in self._args: - self._args[key] = value - elif key in self._input_to_options: - self._options[self._input_to_options[key]] = value - else: - raise ModelAnalyzerException(f"The argument '{key}' to the Model Analyzer is not supported.") diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/exceptions.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/exceptions.py deleted file mode 100644 index d4d7a4b9e..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/perf_analyzer/exceptions.py +++ /dev/null @@ -1,26 +0,0 @@ -class PerfAnalyzerException(Exception): - def __init__(self, message: str): - self._message = message - - def __str__(self): - """ - Get the exception string representation. - - Returns - ------- - str - The message associated with this exception, or None if no message. - """ - return self._message - - @property - def message(self): - """ - Get the exception message. - - Returns - ------- - str - The message associated with this exception, or None if no message. - """ - return self._message diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/warmup.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/warmup.py deleted file mode 100644 index 27ff34eb0..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/deployment_toolkit/warmup.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import logging -import pathlib -from distutils.version import LooseVersion -from importlib.metadata import version -from typing import List - -TRITON_CLIENT_VERSION = LooseVersion(version("tritonclient")) - -# method from PEP-366 to support relative import in executed modules -if __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .core import BatchingMode, EvaluationMode, MeasurementMode, OfflineMode -from .perf_analyzer import PerfAnalyzer, PerfAnalyzerConfig -from .utils import parse_server_url - -LOGGER = logging.getLogger("warmup") - - -def performance_evaluation_warmup( - server_url: str, - model_name: str, - batch_sizes: List[int], - number_of_triton_instances: int, - number_of_model_instances: int, - input_data: str, - input_shapes: List[str], - measurement_mode: MeasurementMode, - measurement_interval: int, - measurement_request_count: int, - batching_mode: BatchingMode, - offline_mode: OfflineMode, - evaluation_mode: EvaluationMode, - output_shared_memory_size: int, -): - protocol, host, port = parse_server_url(http://github.com/server_url) - - measurement_interval = 2 * measurement_interval - measurement_request_count = 2 * measurement_request_count - - if batching_mode == BatchingMode.STATIC: - if len(batch_sizes) == 1: - batch_sizes = {batch_sizes[0]} - else: - batch_sizes = sorted({1, batch_sizes[-1]}) - max_concurrency = 1 - min_concurrency = 1 - step = 1 - elif batching_mode == BatchingMode.DYNAMIC: - max_batch_size = max(batch_sizes) - max_total_requests = 2 * max_batch_size * number_of_triton_instances * number_of_model_instances - max_concurrency = min(256, max_total_requests) - step = max(1, max_concurrency // 2) - min_concurrency = step - batch_sizes = [max(1, max_total_requests // 256)] - else: - raise ValueError(f"Unsupported batching mode: {batching_mode}") - - for batch_size in batch_sizes: - for concurrency in range(min_concurrency, max_concurrency + step, step): - params = { - "model-name": model_name, - "model-version": 1, - "batch-size": batch_size, - "url": f"{host}:{port}", - "protocol": protocol, - "input-data": input_data, - "measurement-interval": measurement_interval, - "concurrency-range": f"{concurrency}:{concurrency}:1", - } - - if TRITON_CLIENT_VERSION >= LooseVersion("2.11.0"): - params["measurement-mode"] = measurement_mode.value - params["measurement-request-count"] = measurement_request_count - - if evaluation_mode == EvaluationMode.OFFLINE: - params["shared-memory"] = offline_mode.value - params["output-shared-memory-size"] = output_shared_memory_size - - config = PerfAnalyzerConfig() - for param, value in params.items(): - config[param] = value - - for shape in input_shapes: - config["shape"] = shape - - perf_analyzer = PerfAnalyzer(config=config) - perf_analyzer.run() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/export_model.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/export_model.py deleted file mode 100755 index 121a046c5..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/export_model.py +++ /dev/null @@ -1,107 +0,0 @@ -import argparse -import logging -import os -from pathlib import Path - -os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" -os.environ["TF_ENABLE_DEPRECATION_WARNINGS"] = "1" - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = Path(__file__).parent.name - -from .deployment_toolkit.args import ArgParserGenerator # noqa: E402 module level import not at top of file -from .deployment_toolkit.core import ( # noqa: E402 module level import not at top of file - DATALOADER_FN_NAME, - BaseLoader, - BaseSaver, - Format, - load_from_file, -) -from .deployment_toolkit.extensions import loaders, savers # noqa: E402 module level import not at top of file - -LOGGER = logging.getLogger("export_model") - -INPUT_MODEL_TYPES = [Format.TF_ESTIMATOR, Format.TF_KERAS, Format.PYT] -OUTPUT_MODEL_TYPES = [Format.TF_SAVEDMODEL, Format.TS_TRACE, Format.TS_SCRIPT, Format.ONNX] - - -def _get_args(): - parser = argparse.ArgumentParser( - description="Script for exporting models from supported frameworks.", allow_abbrev=False - ) - parser.add_argument("--input-path", help="Path to input python module", required=True) - parser.add_argument( - "--input-type", help="Input model type", choices=[f.value for f in INPUT_MODEL_TYPES], required=True - ) - parser.add_argument("--output-path", help="Path to output model file", required=True) - parser.add_argument( - "--output-type", help="Output model type", choices=[f.value for f in OUTPUT_MODEL_TYPES], required=True - ) - parser.add_argument("--dataloader", help="Path to python module containing data loader") - parser.add_argument("-v", "--verbose", help="Verbose logs", action="http://github.com/store_true", default=False) - parser.add_argument( - "--ignore-unknown-parameters", - help="Ignore unknown parameters (argument often used in CI where set of arguments is constant)", - action="http://github.com/store_true", - default=False, - ) - - args, unparsed_args = parser.parse_known_args() - - Loader: BaseLoader = loaders.get(args.input_type) - ArgParserGenerator(Loader, module_path=args.input_path).update_argparser(parser) - - if args.input_type == Format.PYT.value and args.output_type == Format.ONNX.value: - saver_type = f"{Format.PYT.value}--{Format.ONNX.value}" - else: - saver_type = args.output_type - Saver: BaseSaver = savers.get(saver_type) - ArgParserGenerator(Saver).update_argparser(parser) - - if args.dataloader is not None: - get_dataloader_fn = load_from_file(args.dataloader, label="dataloader", target=DATALOADER_FN_NAME) - ArgParserGenerator(get_dataloader_fn).update_argparser(parser) - - if args.ignore_unknown_parameters: - args, unknown_args = parser.parse_known_args() - LOGGER.warning(f"Got additional args {unknown_args}") - else: - args = parser.parse_args() - return args - - -def main(): - args = _get_args() - - log_level = logging.INFO if not args.verbose else logging.DEBUG - log_format = "%(asctime)s %(levelname)s %(name)s %(message)s" - logging.basicConfig(level=log_level, format=log_format) - - LOGGER.info("args:") - for key, value in vars(args).items(): - LOGGER.info(f" {key} = {value}") - - dataloader_fn = None - if args.dataloader is not None: - get_dataloader_fn = load_from_file(args.dataloader, label="dataloader", target=DATALOADER_FN_NAME) - dataloader_fn = ArgParserGenerator(get_dataloader_fn).from_args(args) - - Loader: BaseLoader = loaders.get(args.input_type) - loader = ArgParserGenerator(Loader, module_path=args.input_path).from_args(args) - model = loader.load(args.input_path, dataloader_fn=dataloader_fn, output_type=args.output_type) - - LOGGER.info("inputs: %s", model.inputs) - LOGGER.info("outputs: %s", model.outputs) - - if args.input_type == Format.PYT.value and args.output_type == Format.ONNX.value: - saver_type = f"{Format.PYT.value}--{Format.ONNX.value}" - else: - saver_type = args.output_type - Saver: BaseSaver = savers.get(saver_type) - saver = ArgParserGenerator(Saver).from_args(args) - saver.save(model, args.output_path, dataloader_fn) - - -if __name__ == "__main__": - main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/metrics.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/metrics.py deleted file mode 100644 index f266ea3e6..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/metrics.py +++ /dev/null @@ -1,101 +0,0 @@ -import os -import pandas as pd -import numpy as np -import pickle -import torch -from criterions import QuantileLoss -from triton.deployment_toolkit.core import BaseMetricsCalculator - -def update_argparser(parser): - parser.add_argument("--dataset", type=str, help="Path to dataset to be used", required=True) - parser.add_argument("--checkpoint", type=str, help="Path to checkpoint to be used", required=True) - - - -def _unscale_per_id(config, values, ids, scalers): - # values = values.cpu().numpy() - num_horizons = config.example_length - config.encoder_length + 1 - flat_values = pd.DataFrame( - values, - columns=[f't{j}' for j in range(num_horizons - values.shape[1], num_horizons)] - ) - flat_values['id'] = ids - df_list = [] - for idx, group in flat_values.groupby('id'): - scaler = scalers[idx] - group_copy = group.copy() - for col in group_copy.columns: - if not 'id' in col: - _col = np.expand_dims(group_copy[col].values, -1) - _t_col = scaler.inverse_transform(_col)[:,-1] - group_copy[col] = _t_col - df_list.append(group_copy) - flat_values = pd.concat(df_list, axis=0) - - flat_values = flat_values[[col for col in flat_values if not 'id' in col]] - flat_tensor = torch.from_numpy(flat_values.values) - return flat_tensor -def _unscale(config, values, scaler): - # values = values.cpu().numpy() - num_horizons = config.example_length - config.encoder_length + 1 - flat_values = pd.DataFrame( - values, - columns=[f't{j}' for j in range(num_horizons - values.shape[1], num_horizons)] - ) - for col in flat_values.columns: - if not 'id' in col: - _col = np.expand_dims(flat_values[col].values, -1) - _t_col = scaler.inverse_transform(_col)[:,-1] - flat_values[col] = _t_col - - flat_values = flat_values[[col for col in flat_values if not 'id' in col]] - flat_tensor = torch.from_numpy(flat_values.values) - return flat_tensor - -class MetricsCalculator(BaseMetricsCalculator): - def __init__(self, dataset, checkpoint): - state_dict = torch.load(os.path.join(checkpoint, "checkpoint.pt")) - self.config = state_dict['config'] - self.predictions = [] - self.targets = [] - self.ids = [] - self.scalers = pickle.load(open(os.path.join(dataset, 'tgt_scalers.bin'), 'rb')) - - @property - def metrics(self): - targets = np.concatenate(self.targets, axis=0) - # targets = torch.cat(self.targets, dim=0) - predictions = np.concatenate(self.predictions, axis=0) - # predictions = torch.cat(self.predictions, dim=0) - - ids = np.concatenate(self.ids, axis=0) - if self.config.scale_per_id: - - unscaled_predictions = torch.stack( - [_unscale_per_id(self.config, predictions[:,:,i], ids, self.scalers) for i in range(len(self.config.quantiles))], - dim=-1) - unscaled_targets = _unscale_per_id(self.config, targets[:,:,0], ids, self.scalers).unsqueeze(-1) - else: - ids = None - unscaled_predictions = torch.stack( - [_unscale(self.config, predictions[:,:,i], self.scalers['']) for i in range(len(self.config.quantiles))], - dim=-1) - unscaled_targets = _unscale(self.config, targets[:,:,0], self.scalers['']).unsqueeze(-1) - - losses = QuantileLoss(self.config)(unscaled_predictions, unscaled_targets) - normalizer = unscaled_targets.abs().mean() - q_risk = 2 * losses / normalizer - return {'test_p10': q_risk[0].cpu().numpy(), 'test_p50': q_risk[1].cpu().numpy(), 'test_p90': q_risk[2].cpu().numpy()} - - def update( - self, - ids, - y_pred, - x, - y_real, - ): - #can probably just pass all of this to the evaluator main class - self.predictions.append(y_pred["target__0"]) - self.targets.append(y_real['target__0'][:,:,0][:,:,np.newaxis]) - self.ids.append(ids) - # return self.metrics diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/model.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/model.py deleted file mode 100644 index b964e7b65..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/model.py +++ /dev/null @@ -1,48 +0,0 @@ -import os -import torch -import torch.nn as nn - - -def update_argparser(parser): - parser.add_argument("--checkpoint", type=str, help="Path to checkpoint to be used", required=True) - parser.add_argument("--precision", type=str, choices=['fp16', 'fp32'], required=True) - -class TFTWrapper(nn.Module): - def __init__(self, model): - super().__init__() - self.model = model - - def forward(self, s_cat, s_cont, k_cat, k_cont, o_cat, o_cont, target, id): - # wrapped_input = torch.jit.annotate(Dict[str, Optional[Tensor]], {}) - wrapped_input = {} - input_names = ['s_cat', 's_cont', 'k_cat', 'k_cont', 'o_cat', 'o_cont', 'target', 'id'] - wrapped_input['s_cat'] = s_cat if s_cat.shape[1] != 1 else None - wrapped_input['s_cont'] = s_cont if s_cont.shape[1] != 1 else None - wrapped_input['k_cat'] = k_cat if k_cat.shape[1] != 1 else None - wrapped_input['k_cont'] = k_cont if k_cont.shape[1] != 1 else None - wrapped_input['o_cat'] = o_cat if o_cat.shape[1] != 1 else None - wrapped_input['o_cont'] = o_cont if o_cont.shape[1] != 1 else None - wrapped_input['target'] = target - wrapped_input['id'] = id if id.numel() else None - - return self.model(wrapped_input) - -def get_model(**args): - #get model config - os.environ["TFT_SCRIPTING"] = "True" - from modeling import TemporalFusionTransformer - - state_dict = torch.load(os.path.join(args['checkpoint'], "checkpoint.pt")) - config = state_dict['config'] - #create model - model = TemporalFusionTransformer(config) - #load model - model.load_state_dict(state_dict['model']) - model.eval() - model.cuda() - model = TFTWrapper(model).cuda() - tensor_names = { - "inputs": ['s_cat__0', 's_cont__1', 'k_cat__2', 'k_cont__3', 'o_cat__4', 'o_cont__5', 'target__6', 'id__7'], - "outputs": ["target__0"] - } - return model, tensor_names \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/prepare_input_data.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/prepare_input_data.py deleted file mode 100644 index 441feb2da..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/prepare_input_data.py +++ /dev/null @@ -1,60 +0,0 @@ -import os -import numpy as np -import torch -from torch.utils.data import DataLoader -from configuration import ElectricityConfig -from data_utils import TFTDataset -import argparse -from deployment_toolkit.dump import JsonDumpWriter - -def _verify_and_format_dump(**x): - data = {} - for k, v in x.items(): - temp_data = {} - for i in range(v.shape[1]): - temp_data["INPUT" + str(i)] = v[:,i] - data[k] = temp_data - return data - -def main(): - args = _parse_args() - state_dict = torch.load(os.path.join(args.checkpoint, "checkpoint.pt")) - config = state_dict['config'] - test_split = TFTDataset(os.path.join(args.dataset, "test.csv"), config) - data_loader = DataLoader(test_split, batch_size=args.batch_size, num_workers=2) - input_names_dict = {'s_cat': 's_cat__0', 's_cont':'s_cont__1', 'k_cat':'k_cat__2', 'k_cont':'k_cont__3', 'o_cat':'o_cat__4', 'o_cont':'o_cont__5', 'target':'target__6', 'id':'id__7'} - reshaper = [-1] + [1] - for step, batch in enumerate(data_loader): - bs = batch['target'].shape[0] - x = {input_names_dict[key]: tensor.numpy() if tensor.numel() else np.ones([bs]).reshape(reshaper) for key, tensor in batch.items()} - ids = batch['id'][:,0,:].numpy() - y_real = {'target__0':batch['target'][:,config.encoder_length:,:].numpy()} - break - - - import json - data = {"data": [{k: {"content": v[i].flatten().tolist(), "shape": list(v[i].shape), "dtype": str(v[i].dtype)} for k, v in x.items()} for i in range(args.batch_size)]} - with open(os.path.join(args.input_data_dir, "data.json"), "w") as f: - f.write(json.dumps(data)) - f.close() - # d = json.load(f) - # print(d) - - - -def _parse_args(): - parser = argparse.ArgumentParser() - parser.add_argument("--checkpoint", required=True) - parser.add_argument("--batch-size", required=False, default=1) - parser.add_argument("--dataset", help="Path to dataset", required=True) - parser.add_argument("--input-data-dir", help="Path to output folder", required=True) - - - args, *_ = parser.parse_known_args() - args = parser.parse_args() - - return args - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png deleted file mode 100644 index 0aeb180c7..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png deleted file mode 100644 index 3f0987fba..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png deleted file mode 100644 index 38427b44f..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png deleted file mode 100644 index dcffeebff..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png deleted file mode 100644 index 8c4c7f9a4..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png deleted file mode 100644 index 08f309d08..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png deleted file mode 100644 index fd89aebf2..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png deleted file mode 100644 index 52d2c086d..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png deleted file mode 100644 index a04094232..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png deleted file mode 100644 index a65d901a4..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png deleted file mode 100644 index cbaec5e89..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png deleted file mode 100644 index 35cf7fec0..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png deleted file mode 100644 index 91bcaea03..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png deleted file mode 100644 index 790566e08..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png deleted file mode 100644 index ffbd7fa55..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png deleted file mode 100644 index 1365267ba..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_a30_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png deleted file mode 100644 index 5f19ada83..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png deleted file mode 100644 index 3e414f87e..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png deleted file mode 100644 index 12546e722..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png deleted file mode 100644 index 1802e6ff4..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png deleted file mode 100644 index ed57afbab..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png deleted file mode 100644 index 9cfc13ced..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png deleted file mode 100644 index 77db9d96b..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png deleted file mode 100644 index 5e5fbc82f..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png deleted file mode 100644 index 7b6bd6843..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png deleted file mode 100644 index c8da0782e..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png deleted file mode 100644 index fa101903f..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png deleted file mode 100644 index f9355617e..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png deleted file mode 100644 index 71c204110..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png deleted file mode 100644 index eac17f95a..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png deleted file mode 100644 index 2dae6441f..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png deleted file mode 100644 index 17b85ef71..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx-1_(1x_v100_32gb)_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png deleted file mode 100644 index defc834e3..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png deleted file mode 100644 index 8d1a2d3a7..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png deleted file mode 100644 index d6e6aa3cd..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png deleted file mode 100644 index 00c42a47f..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png deleted file mode 100644 index b3a417d0c..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png deleted file mode 100644 index 6b99a5418..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png deleted file mode 100644 index d46fab9ec..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png deleted file mode 100644 index 6554b7770..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png deleted file mode 100644 index d7049b57d..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png deleted file mode 100644 index 141863fdb..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png deleted file mode 100644 index cf04f6f69..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png deleted file mode 100644 index 04f9fc568..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png deleted file mode 100644 index abd53e4c7..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png deleted file mode 100644 index 4508a7619..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png deleted file mode 100644 index f1fb5aa21..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png deleted file mode 100644 index 26af296bc..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_dgx_a100_(1x_a100_80gb)_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png deleted file mode 100644 index 59857445c..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png deleted file mode 100644 index 989a7361e..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png deleted file mode 100644 index d78dec8e5..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_offline_17/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png deleted file mode 100644 index 8e1ea2625..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_17_triton_performance_online_17/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png deleted file mode 100644 index dfa1be423..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png deleted file mode 100644 index 23af07052..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png deleted file mode 100644 index be8f49627..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_offline_18/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png deleted file mode 100644 index 8308b8ccc..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_18_triton_performance_online_18/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png deleted file mode 100644 index b0bdbb292..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png deleted file mode 100644 index 6782bb1fd..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png deleted file mode 100644 index aff845b84..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_offline_27/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png deleted file mode 100644 index d5d392658..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_27_triton_performance_online_27/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png deleted file mode 100644 index c2e863f31..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/latency_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png deleted file mode 100644 index c20002d5f..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/throughput_vs_batch.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png deleted file mode 100644 index f112d22b9..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_offline_28/plots/throughput_vs_latency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png deleted file mode 100644 index b2fa564d5..000000000 Binary files a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/reports/nvidia_t4_experiment_28_triton_performance_online_28/plots/latency_vs_concurrency.png and /dev/null differ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/requirements.txt b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/requirements.txt deleted file mode 100644 index cb9a44bfa..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/requirements.txt +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# model_navigator[pyt] @ git+https://github.com/triton-inference-server/model_navigator.git@v0.2.3#egg=model_navigator -model_navigator[pyt] @ git+https://github.com/triton-inference-server/model_navigator.git@v0.2.5#egg=model_navigator -natsort>=7.0.0 -networkx==2.5 -numpy -onnx>=1.8.0,<1.9.0 -onnxruntime-gpu==1.8.1 -pycuda>=2019.1.2 -PyYAML>=5.2 -tabulate>=0.8.7 -tqdm>=4.44.1 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_inference_on_fw.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_inference_on_fw.py deleted file mode 100755 index ad33b1fc9..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_inference_on_fw.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -r""" -To infer the model on framework runtime, you can use `run_inference_on_fw.py` script. -It infers data obtained from pointed data loader locally and saves received data into dump files. -Those files are stored in directory pointed by `--output-dir` argument. - -Example call: - -```shell script -python ./triton/run_inference_on_fw.py \ - --input-path /models/exported/model.onnx \ - --input-type onnx \ - --dataloader triton/dataloader.py \ - --data-dir /data/imagenet \ - --batch-size 32 \ - --output-dir /results/dump_local \ - --dump-labels -``` -""" - -import argparse -import logging -import os -from pathlib import Path - -from tqdm import tqdm - -# method from PEP-366 to support relative import in executed modules -if __package__ is None: - __package__ = Path(__file__).parent.name - -os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" -os.environ["TF_ENABLE_DEPRECATION_WARNINGS"] = "0" - - -from .deployment_toolkit.args import ArgParserGenerator # noqa: E402 module level import not at top of file -from .deployment_toolkit.core import ( # noqa: E402 module level import not at top of file - DATALOADER_FN_NAME, - BaseLoader, - BaseRunner, - load_from_file, -) -from .deployment_toolkit.dump import JsonDumpWriter # noqa: E402 module level import not at top of file -from .deployment_toolkit.extensions import loaders, runners # noqa: E402 module level import not at top of file - -LOGGER = logging.getLogger("run_inference_on_fw") - - -def _verify_and_format_dump(args, ids, x, y_pred, y_real): - data = {"outputs": y_pred, "ids": {"ids": ids}} - if args.dump_inputs: - data["inputs"] = x - if args.dump_labels: - if not y_real: - raise ValueError( - "Found empty label values. Please provide labels in dataloader_fn or do not use --dump-labels argument" - ) - data["labels"] = y_real - return data - - -def _parse_and_validate_args(): - supported_inputs = set(runners.supported_extensions) & set(loaders.supported_extensions) - - parser = argparse.ArgumentParser(description="Dump local inference output of given model", allow_abbrev=False) - parser.add_argument("--input-path", help="Path to input model", required=True) - parser.add_argument("--input-type", help="Input model type", choices=supported_inputs, required=True) - parser.add_argument("--dataloader", help="Path to python file containing dataloader.", required=True) - parser.add_argument("--output-dir", help="Path to dir where output files will be stored", required=True) - parser.add_argument("--dump-labels", help="Dump labels to output dir", action="http://github.com/store_true", default=False) - parser.add_argument("--dump-inputs", help="Dump inputs to output dir", action="http://github.com/store_true", default=False) - parser.add_argument("-v", "--verbose", help="Verbose logs", action="http://github.com/store_true", default=False) - - args, *_ = parser.parse_known_args() - - get_dataloader_fn = load_from_file(args.dataloader, label="dataloader", target=DATALOADER_FN_NAME) - ArgParserGenerator(get_dataloader_fn).update_argparser(parser) - - Loader: BaseLoader = loaders.get(args.input_type) - ArgParserGenerator(Loader, module_path=args.input_path).update_argparser(parser) - - Runner: BaseRunner = runners.get(args.input_type) - ArgParserGenerator(Runner).update_argparser(parser) - - args = parser.parse_args() - - types_requiring_io_params = [] - - if args.input_type in types_requiring_io_params and not all(p for p in [args.inputs, args.outptputs]): - parser.error(f"For {args.input_type} input provide --inputs and --outputs parameters") - - return args - - -def main(): - args = _parse_and_validate_args() - - log_level = logging.INFO if not args.verbose else logging.DEBUG - log_format = "%(asctime)s %(levelname)s %(name)s %(message)s" - logging.basicConfig(level=log_level, format=log_format) - - LOGGER.info("args:") - for key, value in vars(args).items(): - LOGGER.info(f" {key} = {value}") - - Loader: BaseLoader = loaders.get(args.input_type) - Runner: BaseRunner = runners.get(args.input_type) - - loader = ArgParserGenerator(Loader, module_path=args.input_path).from_args(args) - runner = ArgParserGenerator(Runner).from_args(args) - LOGGER.info(f"Loading {args.input_path}") - model = loader.load(args.input_path) - with runner.init_inference(model=model) as runner_session, JsonDumpWriter(args.output_dir) as writer: - get_dataloader_fn = load_from_file(args.dataloader, label="dataloader", target=DATALOADER_FN_NAME) - dataloader_fn = ArgParserGenerator(get_dataloader_fn).from_args(args) - LOGGER.info("Data loader initialized; Running inference") - for ids, x, y_real in tqdm(dataloader_fn(), unit="batch", mininterval=10): - y_pred = runner_session(x) - data = _verify_and_format_dump(args, ids=ids, x=x, y_pred=y_pred, y_real=y_real) - writer.write(**data) - LOGGER.info("Inference finished") - - -if __name__ == "__main__": - main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_inference_on_triton.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_inference_on_triton.py deleted file mode 100755 index 869774499..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_inference_on_triton.py +++ /dev/null @@ -1,394 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -r""" -To infer the model deployed on Triton, you can use `run_inference_on_triton.py` script. -It sends a request with data obtained from pointed data loader and dumps received data into dump files. -Those files are stored in directory pointed by `--output-dir` argument. - -Currently, the client communicates with the Triton server asynchronously using GRPC protocol. - -Example call: - -```shell script -python ./triton/run_inference_on_triton.py \ - --server-url localhost:8001 \ - --model-name ResNet50 \ - --model-version 1 \ - --dump-labels \ - --output-dir /results/dump_triton -``` -""" - -import argparse -import functools -import logging -import queue -import threading -import time -import traceback -from pathlib import Path -from typing import Optional - -from tqdm import tqdm - -# pytype: disable=import-error -try: - from tritonclient import utils as client_utils # noqa: F401 - from tritonclient.grpc import InferenceServerClient, InferInput, InferRequestedOutput -except ImportError: - from tritongrpcclient import InferenceServerClient, InferInput, InferRequestedOutput -# pytype: enable=import-error - -# method from PEP-366 to support relative import in executed modules -if __package__ is None: - __package__ = Path(__file__).parent.name - -from .deployment_toolkit.args import ArgParserGenerator -from .deployment_toolkit.core import DATALOADER_FN_NAME, load_from_file -from .deployment_toolkit.dump import JsonDumpWriter - -LOGGER = logging.getLogger("run_inference_on_triton") - - -class SyncGRPCTritonRunner: - DEFAULT_MAX_RESP_WAIT_S = 120 - - def __init__( - self, - server_url: str, - model_name: str, - model_version: str, - *, - dataloader, - verbose=False, - resp_wait_s: Optional[float] = None, - ): - self._server_url = server_url - self._model_name = model_name - self._model_version = model_version - self._dataloader = dataloader - self._verbose = verbose - self._response_wait_t = self.DEFAULT_MAX_RESP_WAIT_S if resp_wait_s is None else resp_wait_s - - def __iter__(self): - client = InferenceServerClient(self._server_url, verbose=self._verbose) - error = self._verify_triton_state(client) - if error: - raise RuntimeError(f"Could not communicate to Triton Server: {error}") - - LOGGER.debug( - f"Triton server {self._server_url} and model {self._model_name}:{self._model_version} " f"are up and ready!" - ) - - model_config = client.get_model_config(self._model_name, self._model_version) - model_metadata = client.get_model_metadata(self._model_name, self._model_version) - LOGGER.info(f"Model config {model_config}") - LOGGER.info(f"Model metadata {model_metadata}") - - inputs = {tm.name: tm for tm in model_metadata.inputs} - outputs = {tm.name: tm for tm in model_metadata.outputs} - output_names = list(outputs) - outputs_req = [InferRequestedOutput(name) for name in outputs] - - for ids, x, y_real in self._dataloader: - infer_inputs = [] - for name in inputs: - data = x[name] - infer_input = InferInput(name, data.shape, inputs[name].datatype) - - target_np_dtype = client_utils.triton_to_np_dtype(inputs[name].datatype) - data = data.astype(target_np_dtype) - - infer_input.set_data_from_numpy(data) - infer_inputs.append(infer_input) - - results = client.infer( - model_name=self._model_name, - model_version=self._model_version, - inputs=infer_inputs, - outputs=outputs_req, - client_timeout=self._response_wait_t, - ) - y_pred = {name: results.as_numpy(name) for name in output_names} - yield ids, x, y_pred, y_real - - def _verify_triton_state(self, triton_client): - if not triton_client.is_server_live(): - return f"Triton server {self._server_url} is not live" - elif not triton_client.is_server_ready(): - return f"Triton server {self._server_url} is not ready" - elif not triton_client.is_model_ready(self._model_name, self._model_version): - return f"Model {self._model_name}:{self._model_version} is not ready" - return None - - -class AsyncGRPCTritonRunner: - DEFAULT_MAX_RESP_WAIT_S = 120 - DEFAULT_MAX_UNRESP_REQS = 128 - DEFAULT_MAX_FINISH_WAIT_S = 900 # 15min - - def __init__( - self, - server_url: str, - model_name: str, - model_version: str, - *, - dataloader, - verbose=False, - resp_wait_s: Optional[float] = None, - max_unresponded_reqs: Optional[int] = None, - ): - self._server_url = server_url - self._model_name = model_name - self._model_version = model_version - self._dataloader = dataloader - self._verbose = verbose - self._response_wait_t = self.DEFAULT_MAX_RESP_WAIT_S if resp_wait_s is None else resp_wait_s - self._max_unresp_reqs = self.DEFAULT_MAX_UNRESP_REQS if max_unresponded_reqs is None else max_unresponded_reqs - - self._results = queue.Queue() - self._processed_all = False - self._errors = [] - self._num_waiting_for = 0 - self._sync = threading.Condition() - self._req_thread = threading.Thread(target=self.req_loop, daemon=True) - - def __iter__(self): - self._req_thread.start() - timeout_s = 0.050 # check flags processed_all and error flags every 50ms - while True: - try: - ids, x, y_pred, y_real = self._results.get(timeout=timeout_s) - yield ids, x, y_pred, y_real - except queue.Empty: - shall_stop = self._processed_all or self._errors - if shall_stop: - break - - LOGGER.debug("Waiting for request thread to stop") - self._req_thread.join() - if self._errors: - error_msg = "\n".join(map(str, self._errors)) - raise RuntimeError(error_msg) - - def _on_result(self, ids, x, y_real, output_names, result, error): - with self._sync: - request_id = str(ids[0]) - NOT_MATCHING_REQUEST_ID_MSG = ( - "Error during processing result - request_id doesn't match. This shouldn't have happened." - ) - if error: - response_id = error.get_response().id - if response_id != request_id: - raise RuntimeError(NOT_MATCHING_REQUEST_ID_MSG) - self._errors.append(error) - else: - response_id = result.get_response().id - if response_id != request_id: - raise RuntimeError(NOT_MATCHING_REQUEST_ID_MSG) - y_pred = {name: result.as_numpy(name) for name in output_names} - self._results.put((ids, x, y_pred, y_real)) - self._num_waiting_for -= 1 - self._sync.notify_all() - - def req_loop(self): - client = InferenceServerClient(self._server_url, verbose=self._verbose) - self._errors = self._verify_triton_state(client) - if self._errors: - return - - LOGGER.debug( - f"Triton server {self._server_url} and model {self._model_name}:{self._model_version} " f"are up and ready!" - ) - - model_config = client.get_model_config(self._model_name, self._model_version) - model_metadata = client.get_model_metadata(self._model_name, self._model_version) - LOGGER.info(f"Model config {model_config}") - LOGGER.info(f"Model metadata {model_metadata}") - - inputs = {tm.name: tm for tm in model_metadata.inputs} - outputs = {tm.name: tm for tm in model_metadata.outputs} - output_names = list(outputs) - - self._num_waiting_for = 0 - - for ids, x, y_real in self._dataloader: - infer_inputs = [] - for name in inputs: - data = x[name] - infer_input = InferInput(name, data.shape, inputs[name].datatype) - - target_np_dtype = client_utils.triton_to_np_dtype(inputs[name].datatype) - data = data.astype(target_np_dtype) - - infer_input.set_data_from_numpy(data) - infer_inputs.append(infer_input) - - outputs_req = [InferRequestedOutput(name) for name in outputs] - - with self._sync: - - def _check_can_send(): - return self._num_waiting_for < self._max_unresp_reqs - - can_send = self._sync.wait_for(_check_can_send, timeout=self._response_wait_t) - if not can_send: - error_msg = f"Runner could not send new requests for {self._response_wait_t}s" - self._errors.append(error_msg) - self._sync.notify_all() - break - - request_id = str(ids[0]) - callback = functools.partial(AsyncGRPCTritonRunner._on_result, self, ids, x, y_real, output_names) - client.async_infer( - model_name=self._model_name, - model_version=self._model_version, - inputs=infer_inputs, - outputs=outputs_req, - callback=callback, - request_id=request_id, - ) - self._num_waiting_for += 1 - self._sync.notify_all() - - # wait till receive all requested data - with self._sync: - - def _all_processed(): - LOGGER.debug(f"wait for {self._num_waiting_for} unprocessed jobs") - return self._num_waiting_for == 0 - - self._processed_all = self._sync.wait_for(_all_processed, self.DEFAULT_MAX_FINISH_WAIT_S) - if not self._processed_all: - error_msg = f"Runner {self._response_wait_t}s timeout received while waiting for results from server" - self._errors.append(error_msg) - - self._sync.notify_all() - - LOGGER.debug("Finished request thread") - - def _verify_triton_state(self, triton_client): - errors = [] - if not triton_client.is_server_live(): - errors.append(f"Triton server {self._server_url} is not live") - elif not triton_client.is_server_ready(): - errors.append(f"Triton server {self._server_url} is not ready") - elif not triton_client.is_model_ready(self._model_name, self._model_version): - errors.append(f"Model {self._model_name}:{self._model_version} is not ready") - return errors - - -def _parse_args(): - parser = argparse.ArgumentParser(description="Infer model on Triton server", allow_abbrev=False) - parser.add_argument( - "--server-url", type=str, default="localhost:8001", help="Inference server URL (default localhost:8001)" - ) - parser.add_argument("--model-name", help="The name of the model used for inference.", required=True) - parser.add_argument("--model-version", help="The version of the model used for inference.", required=True) - parser.add_argument("--dataloader", help="Path to python file containing dataloader.", required=True) - parser.add_argument("--dump-labels", help="Dump labels to output dir", action="http://github.com/store_true", default=False) - parser.add_argument("--dump-inputs", help="Dump inputs to output dir", action="http://github.com/store_true", default=False) - parser.add_argument("-v", "--verbose", help="Verbose logs", action="http://github.com/store_true", default=True) - parser.add_argument("--output-dir", required=True, help="Path to directory where outputs will be saved") - parser.add_argument( - "--response-wait-time", required=False, help="Maximal time to wait for response", default=120, type=float - ) - parser.add_argument( - "--max-unresponded-requests", - required=False, - help="Maximal number of unresponded requests", - default=128, - type=int, - ) - parser.add_argument( - "--synchronous", help="Enable synchronous calls to Triton Server", action="http://github.com/store_true", default=False - ) - - args, *_ = parser.parse_known_args() - - get_dataloader_fn = load_from_file(args.dataloader, label="dataloader", target=DATALOADER_FN_NAME) - ArgParserGenerator(get_dataloader_fn).update_argparser(parser) - args = parser.parse_args() - - return args - - -def main(): - args = _parse_args() - - log_format = "%(asctime)s %(levelname)s %(name)s %(message)s" - log_level = logging.INFO if not args.verbose else logging.DEBUG - logging.basicConfig(level=log_level, format=log_format) - - LOGGER.info("args:") - for key, value in vars(args).items(): - LOGGER.info(f" {key} = {value}") - - get_dataloader_fn = load_from_file(args.dataloader, label="dataloader", target=DATALOADER_FN_NAME) - dataloader_fn = ArgParserGenerator(get_dataloader_fn).from_args(args) - - try: - if args.synchronous: - runner = SyncGRPCTritonRunner( - args.server_url, - args.model_name, - args.model_version, - dataloader=dataloader_fn(), - verbose=False, - resp_wait_s=args.response_wait_time, - ) - else: - runner = AsyncGRPCTritonRunner( - args.server_url, - args.model_name, - args.model_version, - dataloader=dataloader_fn(), - verbose=False, - resp_wait_s=args.response_wait_time, - max_unresponded_reqs=args.max_unresponded_requests, - ) - - except Exception as e: - message = traceback.format_exc() - LOGGER.error(f"Encountered exception \n{message}") - raise e - - with JsonDumpWriter(output_dir=args.output_dir) as writer: - start = time.time() - for ids, x, y_pred, y_real in tqdm(runner, unit="batch", mininterval=10): - data = _verify_and_format_dump(args, ids, x, y_pred, y_real) - writer.write(**data) - stop = time.time() - - LOGGER.info(f"\nThe inference took {stop - start:0.3f}s") - - -def _verify_and_format_dump(args, ids, x, y_pred, y_real): - data = {"outputs": y_pred, "ids": {"ids": ids}} - if args.dump_inputs: - data["inputs"] = x - if args.dump_labels: - if not y_real: - raise ValueError( - "Found empty label values. Please provide labels in dataloader_fn or do not use --dump-labels argument" - ) - data["labels"] = y_real - return data - - -if __name__ == "__main__": - main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_performance_on_triton.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_performance_on_triton.py deleted file mode 100755 index 9c9526331..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/run_performance_on_triton.py +++ /dev/null @@ -1,648 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import csv -import logging -import os -import pathlib -import shutil -import sys -from distutils.version import LooseVersion -from enum import Enum -from typing import Any, Dict, List - -import yaml - -# method from PEP-366 to support relative import in executed modules -if __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .deployment_toolkit.core import BatchingMode, EvaluationMode, MeasurementMode, OfflineMode, PerformanceTool -from .deployment_toolkit.model_analyzer import ModelAnalyzer, ModelAnalyzerConfig, ModelAnalyzerMode -from .deployment_toolkit.perf_analyzer import PerfAnalyzer, PerfAnalyzerConfig -from .deployment_toolkit.report import save_results, show_results, sort_results -from .deployment_toolkit.utils import parse_server_url -from .deployment_toolkit.warmup import performance_evaluation_warmup - -LOGGER = logging.getLogger("run_performance_on_triton") - -if LooseVersion(sys.version) >= LooseVersion("3.8.0"): - from importlib.metadata import version - - TRITON_CLIENT_VERSION = LooseVersion(version("tritonclient")) - TRITON_MODEL_ANALYZER_VERSION = LooseVersion(version("triton-model-analyzer")) -else: - import pkg_resources - - TRITON_CLIENT_VERSION = LooseVersion(pkg_resources.get_distribution("tritonclient").version) - TRITON_MODEL_ANALYZER_VERSION = LooseVersion(pkg_resources.get_distribution("triton-model-analyzer").version) - - -def _log_dict(title: str, dict_: Dict[str, Any]): - LOGGER.info(title) - for key, value in dict_.items(): - LOGGER.info(f"\t{key} = {value}") - - -def _calculate_average_latency(r): - avg_sum_fields = [ - "Client Send", - "Network+Server Send/Recv", - "Server Queue", - "Server Compute", - "Server Compute Input", - "Server Compute Infer", - "Server Compute Output", - "Client Recv", - ] - avg_latency = sum([int(r.get(f, 0)) for f in avg_sum_fields]) - - return avg_latency - - -def _update_performance_data(results: List, batch_size: int, performance_partial_file: str): - row: Dict = {"Batch": batch_size} - with open(performance_partial_file) as csvfile: - reader = csv.DictReader(csvfile) - for r in reader: - avg_latency = _calculate_average_latency(r) - row = {**row, **r, "avg latency": avg_latency} - results.append(row) - - -def _model_analyzer_evaluation( - server_url: str, - model_name: str, - input_data: str, - input_shapes: List[str], - batch_sizes: List[int], - number_of_triton_instances: int, - number_of_model_instances: int, - measurement_mode: MeasurementMode, - measurement_interval: int, - measurement_request_count: int, - concurrency_steps: int, - batching_mode: BatchingMode, - evaluation_mode: EvaluationMode, - offline_mode: OfflineMode, - model_repository: str, - result_path: pathlib.Path, - output_shared_memory_size: int = 102400, - verbose: bool = False, -): - _log_dict( - "Selected configuration", - { - "server_url": server_url, - "model_name": model_name, - "input_data": input_data, - "input_shapes": input_shapes, - "batch_sizes": batch_sizes, - "number_of_triton_instances": number_of_triton_instances, - "number_of_model_instances": number_of_model_instances, - "measurement_mode": measurement_mode, - "measurement_interval": measurement_interval, - "measurement_request_count": measurement_request_count, - "concurrency_steps": concurrency_steps, - "batching_mode": batching_mode, - "evaluation_mode": evaluation_mode, - "offline_mode": offline_mode, - "output_shared_memory_size": output_shared_memory_size, - "model_repository": model_repository, - "result_path": result_path, - "verbose": verbose, - }, - ) - - perf_analyzer_config = { - "measurement-interval": measurement_interval, - } - - if TRITON_MODEL_ANALYZER_VERSION >= LooseVersion("1.8.0"): - perf_analyzer_config["input-data"] = [input_data] - else: - perf_analyzer_config["input-data"] = input_data - - if TRITON_CLIENT_VERSION >= LooseVersion("2.11.0"): - perf_analyzer_config["measurement-mode"] = measurement_mode.value - perf_analyzer_config["measurement-request-count"] = measurement_request_count - - if evaluation_mode == EvaluationMode.OFFLINE: - perf_analyzer_config["shared-memory"] = offline_mode.value - perf_analyzer_config["output-shared-memory-size"] = output_shared_memory_size - - if input_shapes: - if TRITON_MODEL_ANALYZER_VERSION > LooseVersion("1.8.0"): - perf_analyzer_config["shape"] = input_shapes - else: - perf_analyzer_config["shape"] = input_shapes[0] - LOGGER.warning("Model Analyzer <= 1.8.0 support only single shape param for Perf Analyzer.") - - if batching_mode == BatchingMode.STATIC: - batch_sizes = batch_sizes - concurrency = [number_of_triton_instances] - elif batching_mode == BatchingMode.DYNAMIC: - max_batch_size = max(batch_sizes) - max_total_requests = 2 * max_batch_size * number_of_triton_instances * number_of_model_instances - max_concurrency = min(256, max_total_requests) - step = max(1, max_concurrency // concurrency_steps) - min_concurrency = step - - concurrency = {"start": min_concurrency, "stop": max_concurrency, "step": step} - batch_sizes = [max(1, max_total_requests // 256)] - else: - raise ValueError(f"Unsupported batching mode: {batching_mode}") - - protocol, host, port = parse_server_url(http://github.com/server_url) - - checkpoints = pathlib.Path("./checkpoints") - if checkpoints.is_dir(): - shutil.rmtree(checkpoints.as_posix()) - - checkpoints.mkdir(parents=True, exist_ok=True) - - config = { - "model_repository": model_repository, - "triton_launch_mode": "remote", - "run_config_search_disable": True, - "perf_analyzer_flags": perf_analyzer_config, - "perf_analyzer_timeout": 3600, # Workaround for Perf Analyzer timeout - use 1h - "profile_models": [model_name], - "batch_sizes": batch_sizes, - "concurrency": concurrency, - "verbose": verbose, - "checkpoint_directory": checkpoints.as_posix(), - "override_output_model_repository": True, - "client_protocol": protocol, - f"triton_{protocol}_endpoint": f"{host}:{port}", - } - - if verbose: - _log_dict("Model Analyzer profiling configuration", config) - - with open("config.yaml", "w") as file: - yaml.safe_dump(config, file) - - config = ModelAnalyzerConfig() - model_analyzer = ModelAnalyzer(config=config) - model_analyzer.run(mode=ModelAnalyzerMode.PROFILE, verbose=verbose) - - result_path.mkdir(parents=True, exist_ok=True) - - for file in checkpoints.iterdir(): - if not file.is_file() or file.suffix != ".ckpt": - continue - - LOGGER.info(f"Moving checkpoint {file.name} to {result_path}") - shutil.move(file, result_path / file.name) - - inference_output_fields = [ - "batch_size", - "concurrency", - "perf_throughput", - "perf_latency", - "perf_client_send_recv", - "perf_client_response_wait", - "perf_server_queue", - "perf_server_compute_input", - "perf_server_compute_infer", - "perf_server_compute_output", - ] - gpu_output_fields = [ - "gpu_uuid", - "batch_size", - "concurrency", - "gpu_used_memory", - "gpu_free_memory", - "gpu_utilization", - "gpu_power_usage", - ] - - filename_model_inference = "metrics-model-inference.csv" - filename_model_gpu = "metrics-model-gpu.csv" - - config = { - "analysis_models": model_name, - "checkpoint_directory": result_path.as_posix(), - "export_path": "/tmp", - "inference_output_fields": inference_output_fields, - "gpu_output_fields": gpu_output_fields, - "filename_model_inference": filename_model_inference, - "filename_model_gpu": filename_model_gpu, - "summarize": False, - } - - if verbose: - _log_dict("Model Analyzer analysis configuration", config) - - with open("config.yaml", "w") as file: - yaml.safe_dump(config, file) - - config = ModelAnalyzerConfig() - - model_analyzer = ModelAnalyzer(config=config) - model_analyzer.run(mode=ModelAnalyzerMode.ANALYZE, verbose=verbose) - - inference_metrics_file = pathlib.Path("/tmp") / "results" / filename_model_inference - gpu_metrics_file = pathlib.Path("/tmp") / "results" / filename_model_gpu - - for file in [inference_metrics_file, gpu_metrics_file]: - LOGGER.info(f"Moving metrics {file.name} to {result_path}") - shutil.move(file, result_path / file.name) - - -def _perf_analyzer_evaluation( - server_url: str, - model_name: str, - input_data: str, - input_shapes: List[str], - batch_sizes: List[int], - number_of_triton_instances: int, - number_of_model_instances: int, - measurement_mode: MeasurementMode, - measurement_interval: int, - measurement_request_count: int, - concurrency_steps: int, - batching_mode: BatchingMode, - evaluation_mode: EvaluationMode, - offline_mode: OfflineMode, - result_path: pathlib.Path, - output_shared_memory_size: int = 102400, - verbose: bool = False, -): - protocol, host, port = parse_server_url(http://github.com/server_url) - - if batching_mode == BatchingMode.STATIC: - batch_sizes = batch_sizes - max_concurrency = 1 - min_concurrency = 1 - step = 1 - elif batching_mode == BatchingMode.DYNAMIC: - max_batch_size = max(batch_sizes) - max_total_requests = 2 * max_batch_size * number_of_triton_instances * number_of_model_instances - max_concurrency = min(256, max_total_requests) - step = max(1, max_concurrency // concurrency_steps) - min_concurrency = step - batch_sizes = [max(1, max_total_requests // 256)] - else: - raise ValueError(f"Unsupported batching mode: {batching_mode}") - - _log_dict( - "Selected configuration", - { - "server_url": server_url, - "model_name": model_name, - "input_data": input_data, - "input_shapes": input_shapes, - "batch_sizes": batch_sizes, - "number_of_triton_instances": number_of_triton_instances, - "number_of_model_instances": number_of_model_instances, - "measurement_mode": measurement_mode, - "measurement_interval": measurement_interval, - "measurement_request_count": measurement_request_count, - "concurrency_steps": concurrency_steps, - "batching_mode": batching_mode, - "evaluation_mode": evaluation_mode, - "offline_mode": offline_mode, - "output_shared_memory_size": output_shared_memory_size, - "result_path": result_path, - "verbose": verbose, - }, - ) - - results: List[Dict] = list() - for batch_size in batch_sizes: - for concurrency in range(min_concurrency, max_concurrency + step, step): - performance_partial_file = f"triton_performance_{evaluation_mode.value.lower()}_{batching_mode.value.lower()}_partial_{batch_size}_{concurrency}.csv" - - params = { - "model-name": model_name, - "model-version": 1, - "batch-size": batch_size, - "url": f"{host}:{port}", - "protocol": protocol, - "input-data": input_data, - "measurement-interval": measurement_interval, - "concurrency-range": f"{concurrency}:{concurrency}:1", - "latency-report-file": performance_partial_file, - } - - if verbose: - params["extra-verbose"] = True - - if TRITON_CLIENT_VERSION >= LooseVersion("2.11.0"): - params["measurement-mode"] = measurement_mode.value - params["measurement-request-count"] = measurement_request_count - - if evaluation_mode == EvaluationMode.OFFLINE: - params["shared-memory"] = offline_mode.value - params["output-shared-memory-size"] = output_shared_memory_size - - if verbose: - _log_dict(f"Perf Analyzer config for batch_size: {batch_size} and concurrency: {concurrency}", params) - - config = PerfAnalyzerConfig() - for param, value in params.items(): - config[param] = value - - for shape in input_shapes: - config["shape"] = shape - - perf_analyzer = PerfAnalyzer(config=config) - perf_analyzer.run() - _update_performance_data(results, batch_size, performance_partial_file) - os.remove(performance_partial_file) - - results = sort_results(results=results) - - save_results(filename=result_path.as_posix(), data=results) - show_results(results=results) - - -def _run_performance_analysis( - server_url: str, - model_name: str, - input_data: str, - input_shapes: List[str], - batch_sizes: List[int], - number_of_triton_instances: int, - number_of_model_instances: int, - measurement_mode: MeasurementMode, - measurement_interval: int, - measurement_request_count: int, - concurrency_steps: int, - batching_mode: BatchingMode, - evaluation_mode: EvaluationMode, - offline_mode: OfflineMode, - output_shared_memory_size: int, - performance_tool: PerformanceTool, - model_repository: str, - result_path: pathlib.Path, - warmup: bool, - verbose: bool, -): - log_level = logging.INFO if not verbose else logging.DEBUG - log_format = "%(asctime)s %(levelname)s %(name)s %(message)s" - logging.basicConfig(level=log_level, format=log_format) - - if performance_tool == PerformanceTool.MODEL_ANALYZER: - if result_path.suffix: - raise ValueError( - "Results path for Model Analyzer is invalid. Please, provide the directory name. Example: results" - ) - elif performance_tool == PerformanceTool.PERF_ANALYZER: - if result_path.suffix != ".csv": - raise ValueError( - "Results path for Perf Analyzer is invalid. Please, provide the CSV file name. Example: results.csv" - ) - else: - raise ValueError(f"Unsupported performance tool {performance_tool}") - - if warmup: - LOGGER.info("Running warmup before the main test") - performance_evaluation_warmup( - server_url=server_url, - model_name=model_name, - input_data=input_data, - input_shapes=input_shapes, - batch_sizes=batch_sizes, - number_of_triton_instances=number_of_triton_instances, - number_of_model_instances=number_of_model_instances, - measurement_mode=measurement_mode, - measurement_interval=measurement_interval, - measurement_request_count=measurement_request_count, - batching_mode=batching_mode, - evaluation_mode=evaluation_mode, - offline_mode=offline_mode, - output_shared_memory_size=output_shared_memory_size, - ) - - if performance_tool == PerformanceTool.MODEL_ANALYZER: - LOGGER.info("Using Model Analyzer for performance evaluation") - _model_analyzer_evaluation( - server_url=server_url, - model_name=model_name, - input_data=input_data, - input_shapes=input_shapes, - batch_sizes=batch_sizes, - number_of_triton_instances=number_of_triton_instances, - number_of_model_instances=number_of_model_instances, - measurement_mode=measurement_mode, - measurement_interval=measurement_interval, - measurement_request_count=measurement_request_count, - concurrency_steps=concurrency_steps, - batching_mode=batching_mode, - evaluation_mode=evaluation_mode, - offline_mode=offline_mode, - output_shared_memory_size=output_shared_memory_size, - model_repository=model_repository, - result_path=result_path, - verbose=verbose, - ) - elif performance_tool == PerformanceTool.PERF_ANALYZER: - LOGGER.info("Using Perf Analyzer for performance evaluation") - _perf_analyzer_evaluation( - server_url=server_url, - model_name=model_name, - input_data=input_data, - input_shapes=input_shapes, - batch_sizes=batch_sizes, - number_of_triton_instances=number_of_triton_instances, - number_of_model_instances=number_of_model_instances, - measurement_mode=measurement_mode, - measurement_interval=measurement_interval, - measurement_request_count=measurement_request_count, - concurrency_steps=concurrency_steps, - batching_mode=batching_mode, - evaluation_mode=evaluation_mode, - offline_mode=offline_mode, - output_shared_memory_size=output_shared_memory_size, - result_path=result_path, - verbose=verbose, - ) - else: - raise ValueError(f"Unsupported performance tool {performance_tool}") - - -class MeasurementMode(Enum): - """ - Available measurement stabilization modes - """ - - COUNT_WINDOWS = "count_windows" - TIME_WINDOWS = "time_windows" - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument( - "--server-url", - type=str, - required=False, - default="http://127.0.0.1:8000/", - help="Url to Triton server", - ) - parser.add_argument( - "--model-name", - type=str, - required=True, - help="Name of the model to test", - ) - parser.add_argument( - "--input-data", - type=str, - required=False, - default="random", - help="Input data to perform profiling.", - ) - parser.add_argument( - "--input-shapes", - action="http://github.com/append", - required=False, - help="Input data shape in form INPUT_NAME:.", - ) - parser.add_argument( - "--batch-sizes", - type=str, - required=True, - help="List of batch sizes to tests. Comma separated.", - ) - parser.add_argument( - "--number-of-triton-instances", - type=int, - default=1, - help="Number of Triton Server instances", - ) - parser.add_argument( - "--number-of-model-instances", - type=int, - default=1, - help="Number of models instances on Triton Server", - ) - parser.add_argument( - "--measurement-mode", - choices=[item.value for item in MeasurementMode], - default=MeasurementMode.COUNT_WINDOWS.value, - type=str, - help="Select measurement mode " - "'time_windows' stabilize performance on measurement window. " - "'count_windows' stabilize performance on number of samples.", - ) - parser.add_argument( - "--measurement-interval", - required=False, - help="Time window perf_analyzer will wait to stabilize the measurement", - default=5000, - type=int, - ) - parser.add_argument( - "--measurement-request-count", - required=False, - help="Number of samples on which perf_analyzer will stabilize the measurement", - default=50, - type=int, - ) - parser.add_argument( - "--concurrency-steps", - help="Define number of concurrency steps used for dynamic batching tests", - default=32, - type=int, - ) - parser.add_argument( - "--batching-mode", - choices=[item.value for item in BatchingMode], - default=BatchingMode.STATIC.value, - type=str, - help="Select batching mode " - "'static' run static batching scenario. " - "'dynamic' run dynamic batching scenario.", - ) - parser.add_argument( - "--evaluation-mode", - choices=[item.value for item in EvaluationMode], - default=EvaluationMode.OFFLINE.value, - type=str, - help="Select evaluation mode " - "'offline' run offline analysis and use GPU memory to pass tensors. " - "'online' run online analysis and use HTTP protocol.", - ) - parser.add_argument( - "--offline-mode", - choices=[item.value for item in OfflineMode], - default=OfflineMode.SYSTEM.value, - type=str, - help="Select offline mode " - "'system' pass tensors through CPU RAM memory. " - "'cuda' pass tensors through GPU RAM memory.", - ) - parser.add_argument( - "--output-shared-memory-size", - default=100240, - type=int, - help="Size of memory buffer allocated for output with dynamic shapes in bytes. " - "Has to be equal to maximal size of output tensor.", - ) - parser.add_argument( - "--performance-tool", - choices=[item.value for item in PerformanceTool], - default=PerformanceTool.MODEL_ANALYZER.value, - type=str, - help="Select performance tool for measurement mode " - "'model_analyzer' use Model Analyzer " - "'perf_analyzer' use Perf Analyzer", - ) - parser.add_argument( - "--model-repository", - default=None, - type=str, - help="Path to model repository. Valid when using Model Analyzer", - ) - parser.add_argument("--result-path", type=pathlib.Path, required=True, help="Path where results files is stored.") - parser.add_argument( - "--warmup", help="Enable model warmup before performance test", action="http://github.com/store_true", default=False - ) - parser.add_argument("-v", "--verbose", help="Verbose logs", action="http://github.com/store_true", default=False) - - args = parser.parse_args() - - batch_sizes = list(map(lambda x: int(x), args.batch_sizes.split(","))) - _run_performance_analysis( - server_url=args.server_url, - model_name=args.model_name, - input_data=args.input_data, - input_shapes=args.input_shapes or [], - batch_sizes=batch_sizes, - number_of_triton_instances=args.number_of_triton_instances, - number_of_model_instances=args.number_of_model_instances, - measurement_mode=MeasurementMode(args.measurement_mode), - measurement_interval=args.measurement_interval, - measurement_request_count=args.measurement_request_count, - concurrency_steps=args.concurrency_steps, - batching_mode=BatchingMode(args.batching_mode), - evaluation_mode=EvaluationMode(args.evaluation_mode), - offline_mode=OfflineMode(args.offline_mode), - output_shared_memory_size=args.output_shared_memory_size, - performance_tool=PerformanceTool(args.performance_tool), - model_repository=args.model_repository, - result_path=args.result_path, - warmup=args.warmup, - verbose=args.verbose, - ) - - -if __name__ == "__main__": - main() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/__main__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/__main__.py deleted file mode 100644 index 7c18dc396..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/__main__.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import pathlib -from typing import List - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .config import Config -from .executor import Executor -from .finalizer import ExperimentFinalizer -from .maintainer import DockerMaintainer -from .preparer import ExperimentPreparer -from .runner_proxy import RunnerProxy -from .pipeline_impl import pipeline - - -class ExperimentRunner(RunnerProxy): - """ - Experiment Runner proxy for runner wrapper - """ - - maintainer_cls = DockerMaintainer - executor_cls = Executor - preparer_cls = ExperimentPreparer - finalizer_cls = ExperimentFinalizer - - -def execute(config_path: str, devices: List[str]): - if len(devices) == 0: - devices = ["0"] - - config = Config.from_file(config_path) - runner = ExperimentRunner(config=config, pipeline=pipeline, devices=devices) - runner.start() - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--config-path", type=str, required=True, help="Path to configuration file with details.") - parser.add_argument( - "--devices", type=str, nargs="*", required=False, help="Path to configuration file with details." - ) - - args = parser.parse_args() - - config_path = args.config_path - devices = args.devices - - execute(config_path, devices) \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config.py deleted file mode 100644 index 3f1288c68..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pathlib -from typing import Dict, List, Optional, Union - -import yaml - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .configuration import Configuration -from .core import DataObject -from .triton import Triton - - -class Checkpoint(DataObject): - """ - Checkpoint data placeholder - """ - - name: str - url: str - - def __init__(self, name: str, url: str): - self.name = name - self.url = url - - -class Dataset(DataObject): - """ - Dataset data placeholder - """ - - name: str - - def __init__(self, name: str): - self.name = name - - -class Config(DataObject): - """ - Configuration object for runner experiments - """ - - def __init__( - self, - model_name: str, - framework: str, - container_version: str, - configurations: List[Configuration], - datasets_dir: str = "datasets", - datasets: List[Dataset] = None, - checkpoints: List[Checkpoint] = None, - triton_dockerfile: Optional[str] = None, - triton_container_image: Optional[str] = None, - triton_custom_operations: Optional[str] = None, - triton_load_model_method: Optional[str] = Triton.LOAD_MODE.EXPLICIT, - ): - """ - - Args: - model_name: Name of model - framework: Framework used to create model - container_version: Version of Triton Inference Server container used for evaluation - configurations: List of experiments configurations - datasets_dir: Directory where datasets are stored - datasets: Datasets used for conversion/export - checkpoints: Checkpoints with trained model - triton_load_model_method: Triton Inference Server model loading mode - triton_dockerfile: Dockerfile for Triton to build custom image - triton_container_image: Custom image used for Triton Server - leave empty to use default or built from Dockerfile - triton_custom_operations: Path where custom operation library is stored - """ - self.model_name = model_name - self.framework = framework - self.container_version = container_version - self.configurations = configurations - self.datasets_dir = datasets_dir - self.datasets = datasets - self.checkpoints = checkpoints - self.triton_load_model_method = triton_load_model_method - self.triton_dockerfile = triton_dockerfile - self.triton_container_image = triton_container_image - self.triton_custom_operations = triton_custom_operations - - def to_file(self, file_path: Union[pathlib.Path, str]) -> None: - """ - Save config data to file - Args: - file_path: path to file where config data is should be stored - - Returns: - None - """ - data = self.to_dict() - with open(file_path, "w") as f: - yaml.safe_dump(data, f) - - @staticmethod - def from_dict(config_data: Dict): - """ - Create configuration object from data stored in dictionary - - Args: - config_data: dictionary with config data - - Returns: - Config object - """ - configurations = [] - for configuration_data in config_data["configurations"]: - configuration = Configuration(**configuration_data) - configurations.append(configuration) - - checkpoints = [] - for checkpoint_data in config_data.get("checkpoints", []): - checkpoint = Checkpoint( - name=checkpoint_data["name"], - url=checkpoint_data["url"], - ) - checkpoints.append(checkpoint) - - datasets = [] - for dataset_data in config_data.get("datasets", []): - dataset = Dataset(name=dataset_data["name"]) - datasets.append(dataset) - - return Config( - model_name=config_data["model_name"], - framework=config_data["framework"], - container_version=config_data["container_version"], - configurations=configurations, - checkpoints=checkpoints, - datasets=datasets, - datasets_dir=config_data.get("datasets_dir"), - triton_load_model_method=config_data["triton_load_model_method"], - triton_dockerfile=config_data.get("triton_dockerfile"), - triton_container_image=config_data.get("triton_container_image"), - triton_custom_operations=config_data.get("triton_custom_operations"), - ) - - @staticmethod - def from_file(file_path: Union[pathlib.Path, str]): - """ - Load experiment data from file - Args: - file_path: path to file where experiment data is stored - - Returns: - Experiment object - """ - with open(file_path, "r") as f: - config_data = yaml.safe_load(f) - - return Config.from_dict(config_data) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-A30.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-A30.yaml deleted file mode 100644 index b76b17bb8..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-A30.yaml +++ /dev/null @@ -1,125 +0,0 @@ -checkpoints: -- name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip -- name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip -configurations: -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' -datasets: -- name: electricity_bin -- name: traffic_bin -datasets_dir: datasets -framework: PyTorch -model_name: TFT -triton_container_image: null -triton_custom_operations: null -triton_dockerfile: null -triton_load_model_method: explicit diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml deleted file mode 100644 index b76b17bb8..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml +++ /dev/null @@ -1,125 +0,0 @@ -checkpoints: -- name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip -- name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip -configurations: -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' -datasets: -- name: electricity_bin -- name: traffic_bin -datasets_dir: datasets -framework: PyTorch -model_name: TFT -triton_container_image: null -triton_custom_operations: null -triton_dockerfile: null -triton_load_model_method: explicit diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml deleted file mode 100644 index b76b17bb8..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml +++ /dev/null @@ -1,125 +0,0 @@ -checkpoints: -- name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip -- name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip -configurations: -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' -datasets: -- name: electricity_bin -- name: traffic_bin -datasets_dir: datasets -framework: PyTorch -model_name: TFT -triton_container_image: null -triton_custom_operations: null -triton_dockerfile: null -triton_load_model_method: explicit diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-T4.yaml b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-T4.yaml deleted file mode 100644 index b76b17bb8..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/config_NVIDIA-T4.yaml +++ /dev/null @@ -1,125 +0,0 @@ -checkpoints: -- name: electricity_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_eletricity_amp/versions/21.06.0/zip -- name: traffic_bin - url: https://api.ngc.nvidia.com/v2/models/nvidia/tft_pyt_ckpt_base_traffic_amp/versions/21.06.0/zip -configurations: -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: onnx - export_precision: fp32 - format: trt - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: electricity_bin - dataset: electricity_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -- accelerator: none - batch_size: - - 1 - - 2 - - 4 - - 8 - - 16 - - 32 - - 64 - - 128 - - 256 - - 512 - - 1024 - batch_sizes: 1 2 4 8 16 32 64 128 256 512 1024 - capture_cuda_graph: 0 - checkpoint_variant: traffic_bin - dataset: traffic_bin - device: gpu - export_format: ts-trace - export_precision: fp32 - format: ts-trace - max_batch_size: 1024 - precision: fp16 - request_count: 500 - triton_gpu_engine_count: 2 - triton_max_queue_delay: 1 - triton_preferred_batch_sizes: 512 1024 -container_version: '21.12' -datasets: -- name: electricity_bin -- name: traffic_bin -datasets_dir: datasets -framework: PyTorch -model_name: TFT -triton_container_image: null -triton_custom_operations: null -triton_dockerfile: null -triton_load_model_method: explicit diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/configuration.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/configuration.py deleted file mode 100644 index 8c24653fc..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/configuration.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import pathlib -from typing import Any, Dict, List, Union - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .task import DataObject - - -class Configuration(DataObject): - """ - Configuration object - handle single experiment data - """ - - def __init__( - self, - precision: str, - format: str, - batch_size: Union[str, List], - accelerator: str, - triton_gpu_engine_count: int, - triton_max_queue_delay: int, - capture_cuda_graph: int, - checkpoint_variant: str, - triton_preferred_batch_sizes: Union[str, List], - **kwargs: Any, - ): - """ - - Args: - precision: Target model precision - format: Target conversion format - batch_size: Batch sizes to evaluate - accelerator: Triton Backend Accelerator - triton_gpu_engine_count: Number of model instances - triton_max_queue_delay: Maximal queue delay - capture_cuda_graph: Triton Capture CUDA Graph optimization for tensorrt - checkpoint_variant: Checkpoint used for configuration - triton_preferred_batch_sizes: Preferred batch sizes - **kwargs: Additional model arguments - """ - if isinstance(batch_size, str): - batch_size = map(lambda item: int(item), batch_size.split(",")) - - if isinstance(triton_preferred_batch_sizes, str): - triton_preferred_batch_sizes = map(lambda item: int(item), triton_preferred_batch_sizes.split(" ")) - - self.precision = precision - self.format = format - self.batch_size = sorted(batch_size) - self.accelerator = accelerator - self.triton_gpu_engine_count = triton_gpu_engine_count - self.triton_max_queue_delay = triton_max_queue_delay - self.capture_cuda_graph = capture_cuda_graph - self.max_batch_size = max(self.batch_size) - self.checkpoint_variant = checkpoint_variant - self.triton_preferred_batch_sizes = " ".join(map(lambda i: str(i), sorted(triton_preferred_batch_sizes))) - - for key, value in kwargs.items(): - self.__setattr__(key, value) - - @property - def parameters(self) -> Dict: - """ - Return values stored in configuration - - Returns: - Dictionary with configuration parameters - """ - return self.__dict__ diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/core.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/core.py deleted file mode 100644 index cb30e19d2..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/core.py +++ /dev/null @@ -1,148 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import pathlib -from enum import Enum -from typing import Any, Dict, List - -import yaml - - -class CustomDumper(yaml.Dumper): - """ - Custom YAML dumper to avoid craeting aliases - """ - - def ignore_aliases(self, data: Dict) -> bool: - return True - - -class Paths: - """ - Paths mapping inside Triton Container - """ - - MODEL_REPOSITORY_PATH = "/mnt/triton-models" - LIBRARIES_PATH = "/mnt/libs" - - -class Framework(Enum): - """ - Supported frameworks - """ - - TensorFlow1 = "TensorFlow1" - TensorFlow2 = "TensorFlow2" - PyTorch = "PyTorch" - - -class Command: - """Represents wrapper of raw string command""" - - def __init__(self, data: str): - """ - Store command data - Args: - data: string with bash commands to execute - """ - self._data = data - - def __str__(self) -> str: - """ - String object representation - - Returns: - String - """ - return self._data - - -class DataObject(object): - """ - Data object representation handling recursive transformation from object to dict - """ - - READ_ONLY = set() - - def to_dict(self) -> Dict: - """ - Represent object as dictionary - - Returns: - Dict - """ - data = dict() - filtered_data = {key: value for key, value in self.__dict__.items() if key not in self.READ_ONLY} - for key, value in filtered_data.items(): - data[key] = self._convert_value(value) - - return data - - def _convert_value(self, value: Any) -> Any: - """ - Convert value based on its type - - Args: - value: variable to convert - - Returns: - Converted object - """ - if isinstance(value, DataObject): - value = value.to_dict() - elif isinstance(value, dict): - value = self._from_dict(value) - elif isinstance(value, list): - value = self._from_list(value) - elif isinstance(value, Enum): - value = value.value - elif isinstance(value, pathlib.Path): - value = value.as_posix() - - return value - - def _from_dict(self, values: Dict) -> Any: - """ - Convert dictionary values - - Args: - values: dictionary with values - - Returns: - Any - """ - data = dict() - for key, value in values.items(): - data[key] = self._convert_value(value) - - return data - - def _from_list(self, values: List) -> Any: - """ - Convert list of values - - Args: - values: list with values - - Returns: - Any - """ - items = list() - for value in values: - item = self._convert_value(value) - items.append(item) - - return items - - -AVAILABLE_FRAMEWORKS = [f.value for f in Framework] diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/downloader.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/downloader.py deleted file mode 100755 index 192272644..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/downloader.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pathlib -import shutil -import urllib.request -from typing import Any, Callable -from zipfile import ZipFile - -from retrying import retry -from tqdm.auto import tqdm - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .logger import LOGGER -from .exceptions import RunnerException - - -def unzip(checkpoint_path: pathlib.Path, archive_path: pathlib.Path) -> None: - """ - Unzip acrhive to provided path - - Args: - checkpoint_path: Path where archive has to be unpacked - archive_path: Path to archive Archive filename - - Returns: - None - """ - LOGGER.info(f"Creating directory for checkpoint: {checkpoint_path.name}") - checkpoint_path.mkdir(parents=True, exist_ok=True) - - LOGGER.info(f"Unpacking checkpoint files {checkpoint_path}") - with ZipFile(archive_path, "r") as zf: - zf.extractall(path=checkpoint_path) - LOGGER.info("done") - - LOGGER.info(f"Removing zip file: {archive_path}") - archive_path.unlink() - LOGGER.info("done") - - -def download_progress(t: Any) -> Callable: - """ - Progress bar - - Args: - t: progress - - Returns: - Callable - """ - last_b = [0] - - def update_to(b: int = 1, bsize: int = 1, tsize: int = None): - if tsize not in (None, -1): - t.total = tsize - t.update((b - last_b[0]) * bsize) - last_b[0] = b - - return update_to - - -@retry(stop_max_attempt_number=3) -def download(checkpoint_url: str, checkpoint_path: pathlib.Path) -> None: - """ - Download checkpoint from given url to provided path - Args: - checkpoint_url: Url from which checkpoint has to be downloaded - checkpoint_path: Path where checkpoint has to be stored - - Returns: - None - """ - LOGGER.info(f"Downloading checkpoint from {checkpoint_url}") - with tqdm(unit="B") as t: - reporthook = download_progress(t) - result = urllib.request.urlretrieve(checkpoint_url, reporthook=reporthook) - - filename = result[0] - LOGGER.info(f"Checkpoint saved in {filename}") - - file_path = pathlib.Path(filename) - if not file_path.is_file() and not file_path.is_dir(): - raise RunnerException(f"Checkpoint {filename} does not exist") - - LOGGER.info(f"Moving checkpoint to {checkpoint_path.parent}") - shutil.move(file_path, checkpoint_path.parent / file_path.name) - LOGGER.info("done") - - archive_path = checkpoint_path.parent / file_path.name - unzip(checkpoint_path, archive_path) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/executor.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/executor.py deleted file mode 100644 index c4cd55b48..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/executor.py +++ /dev/null @@ -1,394 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import json -import os -import pathlib -import shutil -import traceback -from typing import Dict, List, Optional - -from colorama import Fore - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from ..deployment_toolkit.core import Accelerator, Precision -from .core import Paths -from .exceptions import RunnerException -from .experiment import ExperimentResult, ExperimentStatus, Status -from .exporter import CommandsExporter -from .logger import LOGGER -from .maintainer import Container, Maintainer -from .pipeline import Pipeline -from .stages import Stage -from .task import Experiment, Task -from .triton import Triton -from .utils import clean_directory, exec_command, format_env_key, format_env_value, get_result_path - - -class Executor: - """ - Experiments executor - """ - - def __init__( - self, - workspace: pathlib.Path, - maintainer: Maintainer, - pipeline: Pipeline, - devices: List[str] = None, - ): - """ - Initialize experiments executor - - Args: - workspace: Path to workspace to store artifacts - maintainer: maintainer for running commands - pipeline: pipeline definition - - devices: List of devices on which Triton Inference Server will be executed - """ - self._maintainer = maintainer - self._pipeline = pipeline - self._devices = devices or ["0"] - - self._workspace = workspace - self._executor_workspace = workspace / "executor" - self._shared_dir = self._executor_workspace / "shared" - self._triton_models_repository_dir = self._executor_workspace / "triton_models" - self._scripts_dir = self._executor_workspace / "scripts" - self._libraries_dir = self._executor_workspace / "libs" - - self._exporter = CommandsExporter(self._scripts_dir) - self._triton_container: Optional[Container] = None - - def start(self, task: Task): - """ - Process the task and execute experiments. - """ - self._create_dirs() - total_experiment = len(task.experiments) - LOGGER.info(f"Total experiments to verify: {total_experiment}") - for idx, experiment in enumerate(task.experiments, start=1): - LOGGER.info( - f"{Fore.CYAN}================ Experiment: {idx}/{total_experiment} Started ================{Fore.RESET}" - ) - results = {} - environment = self._prepare_environment(task, experiment.parameters) - LOGGER.info(f"Experiment details") - LOGGER.info(json.dumps(environment, indent=4)) - - self._clean_experiment_artifacts(idx, total_experiment) - self._create_experiment_results_dir(task, experiment) - - experiment.start() - - LOGGER.info("Running Triton Servers:") - log_file = self._workspace / task.logs_dir / f"triton-server-experiment-{idx}.log" - self._triton_container = self._triton_server_container( - triton_container_image=task.triton_container_image, - framework=task.framework, - accelerator=experiment.parameters["accelerator"], - precision=experiment.parameters["precision"], - custom_library=bool(task.triton_custom_operations is not None), - load_model_method=task.triton_load_model_method, - log_file=log_file, - ) - - try: - self._triton_container.start() - - for stage in self._pipeline.stages(): - LOGGER.info( - f"{Fore.GREEN}[Experiment: {idx}/{total_experiment}] ================ Stage {stage.label} Started ================{Fore.RESET}" - ) - experiment_stage = experiment.stages[stage.label] - experiment_stage.start() - - is_ok = self._run_stage(stage=stage) - if not is_ok: - LOGGER.error(f"Stage {stage.label} failed.") - break - - self._save_results(task, experiment, stage.label, results) - experiment_stage.end() - - LOGGER.info( - f"{Fore.GREEN}[Experiment: {idx}/{total_experiment}] ================ Stage {stage.label} Finished ================{Fore.RESET}" - ) - except Exception: - message = traceback.format_exc() - LOGGER.error(f"Error running experiment: {message}") - yield ExperimentResult( - status=Status(state=ExperimentStatus.FAILED, message=message), - experiment=experiment, - results=results, - ) - finally: - self._triton_container.stop() - - experiment.end() - LOGGER.info( - f"{Fore.CYAN}================ Experiment: {idx}/{total_experiment} Finished ================{Fore.RESET}" - ) - yield ExperimentResult( - status=Status(state=ExperimentStatus.SUCCEED, message="Experiment Succeed"), - experiment=experiment, - results=results, - ) - - def stop(self) -> None: - """ - Stop executor - - Returns: - None - """ - if self._triton_container: - self._triton_container.stop() - - def _prepare_environment(self, task: Task, parameters: Dict) -> Dict: - """ - Prepare environment data and export it - - Args: - parameters: Key and values which should be exported to environment - - Returns: - Dictionary with environment data - """ - environment = { - "MODEL_NAME": task.model_name, - "FRAMEWORK": task.framework, - "SHARED_DIR": self._shared_dir.as_posix(), - "MODEL_REPOSITORY_PATH": self._triton_models_repository_dir.as_posix(), - "TRITON_SERVER_URL": "localhost", - "TRITON_INSTANCES": "1", - "TRITON_LOAD_MODEL_METHOD": task.triton_load_model_method, - } - - checkpoint_variant = parameters.get("checkpoint_variant") - if checkpoint_variant: - del parameters["checkpoint_variant"] - environment["CHECKPOINT_DIR"] = task.checkpoints[checkpoint_variant].path.as_posix() - - if task.datasets_dir: - environment["DATASETS_DIR"] = task.datasets_dir.as_posix() - - for key, value in parameters.items(): - key = format_env_key(key) - value = format_env_value(value) - environment[key] = value - - for key, value in environment.items(): - os.environ[key] = value - - return environment - - def _triton_server_container( - self, - triton_container_image: str, - framework: str, - load_model_method: str, - accelerator: str, - precision: str, - log_file: pathlib.Path, - custom_library: bool, - ) -> Container: - """ - Create Triton Inference Server container for experiment - - Args: - triton_container_image: Triton Inference Server container image - framework: Framework used to run model - accelerator: Accelerator used for experiment - precision: Precision used for experiment - load_model_method: Configure how Triton will load model - log_file: File where Triton logs are stored - - Returns: - Container object - """ - volumes = { - self._triton_models_repository_dir: {"bind": Paths.MODEL_REPOSITORY_PATH, "mode": "rw"}, - self._libraries_dir: {"bind": Paths.LIBRARIES_PATH, "mode": "rw"}, - } - - environment = { - "MODEL_REPOSITORY_PATH": Paths.MODEL_REPOSITORY_PATH, - "LIBRARIES_PATH": Paths.LIBRARIES_PATH, - "TRITON_LOAD_MODEL_METHOD": load_model_method, - } - - if custom_library: - library_path = Triton.library_path(framework=framework) - environment["LD_LIBRARY_PATH"] = f"{library_path}:${{LD_LIBRARY_PATH}}" - environment["LD_PRELOAD"] = Triton.custom_library_path_remote() - - if accelerator == Accelerator.TRT.value and precision == Precision.FP16.value: - environment["ORT_TENSORRT_FP16_ENABLE"] = 1 - - strict_mode = False - command = Triton.command( - framework=framework, - repository_path=Paths.MODEL_REPOSITORY_PATH, - strict_mode=strict_mode, - ) - command = f' bash -c "{command}"' - - container = self._maintainer.triton_container( - command=command, - image=triton_container_image, - devices=self._devices, - volumes=volumes, - environment=environment, - log_file=log_file, - ) - - return container - - def _save_results(self, task: Task, experiment: Experiment, stage_name: str, results: Dict) -> None: - """ - Update results for stage - - Args: - task: Task object - experiment: Experiment for which stage has to be updated - stage_name: Name of stage - results: Results path mapping - - Returns: - None - """ - stage = experiment.stages[stage_name] - - if not stage.result_path: - LOGGER.debug(f"No results file to copy for {stage.name}") - return - - if not stage.result_type: - LOGGER.debug(f"No results type provided for {stage.name}") - return - - os.environ["SHARED_DIR"] = self._shared_dir.as_posix() - result_path = get_result_path(result_path=stage.result_path) - result_path = pathlib.Path(result_path) - - if not result_path.is_file() and not result_path.is_dir(): - raise RunnerException(f"Results file {result_path} not found.") - - experiment_dir = self._workspace / task.results_dir / experiment.results_dir - - LOGGER.info(f"Saving {stage.result_type} to {experiment_dir}") - - if result_path.is_dir(): - dst_path = experiment_dir / stage.result_type - shutil.copytree(result_path, dst_path) - elif result_path.is_file(): - suffix = result_path.suffix - dst_path = experiment_dir / f"{stage.result_type}{suffix}" - shutil.copy(result_path, dst_path) - else: - raise RunnerException(f"Result not found {result_path}") - LOGGER.info("Done") - - results[stage.result_type] = dst_path - - def _create_dirs(self) -> None: - """ - Create directories used to store artifacts and final results - - Returns: - None - """ - LOGGER.info(f"{Fore.GREEN}================ Creating Artifacts Directories Started ================{Fore.RESET}") - - if self._executor_workspace.is_dir(): - LOGGER.info(f"Removing previous executor workspace: {self._executor_workspace}") - shutil.rmtree(self._executor_workspace) - - for directory in [ - self._libraries_dir, - self._shared_dir, - self._scripts_dir, - self._triton_models_repository_dir, - ]: - directory.mkdir(parents=True, exist_ok=True) - LOGGER.info(f"Directory {directory.name} created.") - LOGGER.info( - f"{Fore.GREEN}================ Creating Artifacts Directories Finished ================{Fore.RESET}" - ) - - def _clean_experiment_artifacts(self, idx: int, total: int) -> None: - """ - Clean artifacts stored between experiments - - Returns: - None - """ - LOGGER.info( - f"{Fore.GREEN}[Experiment: {idx}/{total}] ================ Cleanup Experiment Data Started ================{Fore.RESET}" - ) - for directory in [ - self._shared_dir, - self._scripts_dir, - self._triton_models_repository_dir, - ]: - clean_directory(directory) - LOGGER.info(f"Location {directory} cleaned.") - LOGGER.info( - f"{Fore.GREEN}[Experiment: {idx}/{total}] ================ Cleanup Experiment Data Finished ================{Fore.RESET}" - ) - - def _create_experiment_results_dir(self, task: Task, experiment: Experiment): - """ - Create result directory for experiment - - Returns: - - """ - experiment_dir = self._workspace / task.results_dir / experiment.results_dir - experiment_dir.mkdir(parents=True, exist_ok=True) - - def _prepare_triton_custom_operations(self, task: Task) -> None: - """ - Prepare Triton Server custom operations library - - Returns: - None - """ - if task.triton_custom_operations: - target_library_path = Triton.custom_library_path_local(self._libraries_dir) - target_library_path_dir = target_library_path.parent - target_library_path_dir.mkdir(parents=True, exist_ok=True) - shutil.copy(task.triton_custom_operations, target_library_path) - - def _run_stage(self, stage: Stage) -> bool: - """ - Run single stage commands - - Args: - stage: Stage object with defined commands - - Returns: - True on success, False otherwise - """ - try: - command = self._exporter.export(stage=stage) - exec_command(command) - except RunnerException: - return False - - return True diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/experiment.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/experiment.py deleted file mode 100644 index 7418d59fd..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/experiment.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import dataclasses -import pathlib -from datetime import datetime -from typing import Any, Dict, Optional - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .core import DataObject - - -class ExperimentStatus(object): - """ - Experiment status flags object - """ - - SUCCEED = "Succeed" - FAILED = "Failed" - - -class StageStatus: - """ - Stages status flags object - """ - - SUCCEED = "Succeed" - FAILED = "Failed" - - -class Stage(DataObject): - """ - Stage data object - """ - - name: str - status: str - started_at: Optional[int] - ended_at: Optional[int] - result_path: Optional[str] - result_type: Optional[str] - - def __init__( - self, - name: str, - result_path: Optional[str], - result_type: Optional[str], - status: str = StageStatus.FAILED, - started_at: Optional[int] = None, - ended_at: Optional[int] = None, - ): - """ - - Args: - name: name of stage - result_path: path where results file is stored - result_type: type of results - status: success/fail status - started_at: time when stage has started - ended_at: time when stage has ended - """ - self.name = name - self.status = status - self.started_at = started_at - self.ended_at = ended_at - - self.result_path = result_path - self.result_type = result_type - - def start(self) -> None: - """ - Update stage execution info at start - - Returns: - None - """ - self.started_at = int(datetime.utcnow().timestamp()) - - def end(self) -> None: - """ - Update stage execution info at end - - Returns: - None - """ - self.status = StageStatus.SUCCEED - self.ended_at = int(datetime.utcnow().timestamp()) - - -class Experiment(DataObject): - """ - Experiment data object - """ - - experiment_id: int - parameters: Dict - stages: Dict[str, Stage] - results: Dict[str, str] - status: str - started_at: Optional[int] - ended_at: Optional[int] - - def __init__( - self, - experiment_id: int, - parameters: Dict, - stages: Dict[str, Stage], - results: Dict[str, str], - started_at: Optional[int] = None, - ended_at: Optional[int] = None, - status: str = ExperimentStatus.FAILED, - ): - """ - Args: - experiment_id: experiment identifier - parameters: dictionary with experiment configuration - stages: dictionary with stages run in experiment - results: mapping between results types and location where are stored - started_at: time when experiment has started - ended_at: time when experiment has ended - status: experiment success/fail information - """ - self.experiment_id = experiment_id - self.started_at = started_at - self.ended_at = ended_at - self.parameters = parameters - self.stages = stages - self.status = status - - self.results = results - self.results_dir = f"experiment_{experiment_id}" - - def start(self) -> None: - """ - Update experiment execution info at start - - Returns: - None - """ - self.started_at = int(datetime.utcnow().timestamp()) - - def end(self) -> None: - """ - Update experiment execution info at end - - Returns: - None - """ - self.status = ExperimentStatus.SUCCEED - self.ended_at = int(datetime.utcnow().timestamp()) - - -@dataclasses.dataclass -class Status: - state: ExperimentStatus - message: str - - -@dataclasses.dataclass -class ExperimentResult: - """ - Experiment result object - """ - - status: Status - experiment: Experiment - results: Dict[str, pathlib.Path] - payload: Dict[str, Any] = dataclasses.field(default_factory=dict) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/exporter.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/exporter.py deleted file mode 100644 index 5f3a236ad..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/exporter.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -import pathlib - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .core import Command -from .exceptions import RunnerException -from .stages import Stage - - -class CommandsExporter: - """ - Command exported to BASH scripts - """ - - def __init__(self, scripts_dir: pathlib.Path): - """ - - Args: - scripts_dir: Paths where scripts should be stored - """ - self._scripts_dir = scripts_dir - - def export(self, stage: Stage) -> Command: - """ - Export stage commands to script and return new command to execute - - Args: - stage: Stage object with commands - - Returns: - Command object with script execution command - """ - filename = self._get_filename(stage.label) - file_path = self._scripts_dir / filename - with open(file_path, "w+") as stagefile: - stagefile.write("set -x\n") - stagefile.write("set -e\n") - stagefile.write("export PYTHONUNBUFFERED=1\n") - stagefile.write("export PYTHONPATH=`pwd`\n") - for command in stage.commands: - stagefile.write(str(command)) - - result = os.system(f'ex +"set syn=sh" +"norm gg=G" -cwq {file_path}') - if result != 0: - raise RunnerException(f"Failed running {filename} script formatting. Exit code {result}") - - command = Command(f"bash -xe {file_path.as_posix()}") - return command - - def _get_filename(self, label: str): - """ - Generate filename for script based on label - - Args: - label: String with stage label - - Returns: - String with script filename - """ - filename = label.replace(" ", "_").lower() - filename = f"{filename}.sh" - - return filename diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/finalizer.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/finalizer.py deleted file mode 100644 index 6a4eaaeac..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/finalizer.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import abc -import pathlib -import shutil -from typing import Dict, List - -import yaml - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .experiment import ExperimentResult -from .logger import LOGGER -from .stages import ResultsType -from .summary import load_results, save_summary -from .task import Task - - -class Finalizer(abc.ABC): - @abc.abstractmethod - def exec(self, workspace: pathlib.Path, task: Task, results: List[ExperimentResult]): - pass - - -class ExperimentFinalizer(Finalizer): - """ - Public runner finalizer object. - """ - - def exec(self, workspace: pathlib.Path, task: Task, results: List[ExperimentResult]): - results_path = workspace / task.results_dir - - self._generate_summary(results_path, results) - self._finalize_task(results_path, task) - - def _finalize_task(self, results_path: pathlib.Path, task: Task) -> None: - """ - Finalize task information - - Args: - task: Task object - - Returns: - None - """ - task.end() - - file_path = results_path / task.filename - - LOGGER.debug(f"Saving task details to file {file_path}") - task.to_file(file_path) - LOGGER.debug("Done") - - LOGGER.info(f"Task details and results stored in {results_path}") - - def _generate_summary(self, results_path: pathlib.Path, experiment_results: List[ExperimentResult]): - """ - Generate summary for results collected in all experiments - - Args: - results_path: Path where results should be stored - experiment_results: Results collected from experiments - - Returns: - - """ - performance_offline_results = list() - performance_online_results = list() - results_mapping = { - ResultsType.TRITON_PERFORMANCE_OFFLINE: performance_offline_results, - ResultsType.TRITON_PERFORMANCE_ONLINE: performance_online_results, - } - - self._collect_summary_results(experiment_results, results_mapping) - self._prepare_final_results(results_path, results_mapping) - - def _collect_summary_results(self, experiment_results: List[ExperimentResult], results_mapping: Dict): - for experiment_result in experiment_results: - experiment = experiment_result.experiment - for result_type, result_path in experiment_result.results.items(): - - if not result_path.is_file() and not result_path.is_dir(): - raise FileNotFoundError(f"Expected file {result_path} not found") - - LOGGER.debug(f"Found {result_type} in {result_path} file.") - - if result_type not in results_mapping: - LOGGER.debug(f"Results {result_type} for {experiment.experiment_id} are ignored in final summary.") - return - - LOGGER.debug(f"Collecting {result_type} results from {result_path} for summary") - result = load_results( - results_path=result_path, - parameters=experiment.parameters, - result_type=result_type, - ) - - results_mapping[result_type].extend(result) - LOGGER.debug(f"Done.") - - def _prepare_final_results(self, results_path: pathlib.Path, results_mapping: Dict) -> None: - """ - Prepare summary files for offline and online performance - - Args: - results_path: Path where results should be stored - results_mapping: Mapping with results type and collected results for given stage - - Returns: - None - """ - for results_type, results in results_mapping.items(): - save_summary( - result_type=results_type, - results=results, - summary_dir=results_path, - ) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/logger.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/logger.py deleted file mode 100644 index ffd67b99a..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/logger.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import logging -import pathlib - -import coloredlogs - - -class Logger(logging.Logger): - def __init__(self, name, level=logging.NOTSET): - super().__init__(name, level=level) - self._file_path = None - - def initialize(self, file_path: pathlib.Path): - self._file_path = file_path - - def write(self, log: str): - if not self._file_path: - return - - with open(self._file_path, "+a") as file: - file.write(log) - - -LOGGER = Logger("runner") - -log_format = "%(asctime)s %(levelname)s %(name)s %(message)s" -logging.basicConfig(format=log_format) -coloredlogs.install( - level=logging.INFO, - fmt=log_format, - logger=LOGGER, - field_styles={ - "asctime": {"color": "green"}, - "hostname": {"color": "magenta"}, - "levelname": {"bold": True, "color": "blue"}, - "name": {"color": "blue"}, - "programname": {"color": "cyan"}, - "username": {"color": "yellow"}, - }, - reconfigure=True, -) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/container.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/container.py deleted file mode 100644 index ae6639c4e..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/container.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import abc -from typing import Any - - -class Container(abc.ABC): - def __init__(self, name: str): - self.name = name - self._container = None - - @abc.abstractmethod - def start(self): - """ - Start container - """ - pass - - @abc.abstractmethod - def stop(self): - """ - Stop container - """ - - @abc.abstractmethod - def run(self, command: str) -> Any: - """ - Run command inside container - Args: - command: command to execute - - Returns: - Any - """ - pass diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/container.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/container.py deleted file mode 100644 index beccb8edd..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/container.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import abc -import pathlib - -import docker -from docker.models.containers import ExecResult - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from ..container import Container - - -class DockerContainer(Container): - def __init__(self, name: str): - super().__init__(name) - self._container = None - self._docker_client = docker.from_env() - self._docker_api_client = docker.APIClient() - - @abc.abstractmethod - def start(self): - """ - Start container - """ - pass - - @abc.abstractmethod - def stop(self): - """ - Stop container - """ - - @abc.abstractmethod - def run(self, command: str) -> ExecResult: - """ - Run command inside container - Args: - command: command to execute - - Returns: - ExecResult - """ - pass diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/containers/triton_server_container.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/containers/triton_server_container.py deleted file mode 100644 index 0f26fa72b..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/containers/triton_server_container.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import json -import pathlib -from threading import Thread -from typing import Dict, Generator, Union - -from docker.models.containers import ExecResult -from docker.types import DeviceRequest, Ulimit - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from ....logger import LOGGER -from ...exceptions import ContainerNotStarted -from ..container import DockerContainer - - -class TritonServerContainer(DockerContainer): - def __init__( - self, - name: str, - command: str, - image: str, - volumes: Dict, - devices: Union[list, int], - environment: Dict, - log_file: Union[pathlib.Path, str], - network: str = "host", - shm_size: str = "1G", - ): - """ - Initialize Triton Server Container - Args: - name: Container name - command: Triton Server command to exec on container start - image: Docker Image - volumes: Volumes to mount inside container - devices: Devices which has to be visible in container - environment: Environment variables - log_file: Path where logs should be saved - network: Network mode - shm_size: Shared memory size - """ - super().__init__(name) - self._image = image - self._command = command - self._volumes = volumes - self._devices = devices - self._environment = environment - self._network = network - self._shm_size = shm_size - self._triton_exec = None - self._logging_thread = None - self._log_file_path = pathlib.Path(log_file) - - def start(self) -> None: - """ - Start Triton Server Container - """ - devices = [ - DeviceRequest(capabilities=[["gpu"]], device_ids=self._devices), - ] - - LOGGER.info(f"Triton environment: {json.dumps(self._environment, indent=4)}") - - LOGGER.info(f"Starting Triton container {self.name}.") - self._container = self._docker_client.containers.run( - image=self._image, - name=self.name, - device_requests=devices, - detach=True, - tty=True, - shm_size=self._shm_size, - ulimits=[ - Ulimit(name="memlock", soft=-1, hard=-1), - Ulimit(name="stack", soft=67108864, hard=67108864), - ], - volumes=self._volumes, - environment=self._environment, - network_mode=self._network, - auto_remove=True, - ipc_mode="host", - ) - LOGGER.info(f"Triton command:") - LOGGER.info(f" {self._command}") - LOGGER.info(f"Starting Triton Server {self.name}.") - self._triton_exec = self._docker_api_client.exec_create( - container=self._container.id, - cmd=self._command, - ) - stream_generator = self._docker_api_client.exec_start(exec_id=self._triton_exec["Id"], stream=True) - - self._logging_thread = Thread(target=TritonServerContainer._logging, args=(self, stream_generator), daemon=True) - self._logging_thread.start() - - def stop(self) -> None: - """ - Stop Triton Server Container and save logs to file - """ - if self._container is not None: - triton_result = self._docker_api_client.exec_inspect(self._triton_exec["Id"]) - if triton_result.get("ExitCode") not in (0, None): - LOGGER.info( - f"Triton Inference Server instance {self.name} failed. Exit code: {triton_result.get('ExitCode')}" - ) - - LOGGER.info(f"Stopping triton server {self.name}.") - self._container.stop() - - self._container = None - self._docker_client.close() - self._docker_api_client.close() - - def run(self, command: str) -> ExecResult: - """ - Run command in container - Args: - command: Command to execute - - Returns: - ExecResult - """ - if not self._container: - raise ContainerNotStarted("Triton Server Container is not running. Use .start() first.") - - return self._container.exec_run(command) - - def _logging(self, generator: Generator) -> None: - """Triton logging thread for Triton Inference Server - - Args: - generator (string generator): Triton log stream. - """ - with open(self._log_file_path, mode="w") as file: - try: - while True: - log = next(generator) - txt = log.decode("utf-8") - file.write(txt) - except StopIteration: - LOGGER.info(f"Saving Triton Inference Server {self.name} logs in {self._log_file_path}.") diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/maintainer.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/maintainer.py deleted file mode 100644 index fa62a7006..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/docker/maintainer.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import pathlib -from typing import Any, Dict, List, Optional, Union - -import docker - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from ...logger import LOGGER -from ..maintainer import Maintainer -from .container import DockerContainer -from .containers import TritonServerContainer - - -class DockerMaintainer(Maintainer): - def triton_container( - self, command: str, image: str, devices: List, volumes: Dict, environment: Dict, log_file: Union[pathlib.Path, str] - ) -> DockerContainer: - """ - Return triton container - - Args: - command: Triton Server command that has to be executed - image: Container image - devices: List of device ids which has to be available in container - volumes: Volumes mapping - environment: Environment variables set in container - log_file: File path where server logs has to be saved - - Returns: - DockerContainer object - """ - return TritonServerContainer( - name="triton-server", - command=command, - image=image, - devices=devices, - volumes=volumes, - environment=environment, - log_file=log_file, - ) - - def build_image( - self, - *, - image_file_path: pathlib.Path, - image_name: str, - workdir_path: Optional[pathlib.Path] = None, - build_args: Optional[Dict[str, Any]] = None, - ) -> None: - - workdir_path = workdir_path or image_file_path.parent - build_args = build_args or {} - LOGGER.info(f"Building {image_name} docker image.") - LOGGER.debug(f" Using workdir: {workdir_path}") - LOGGER.debug(f" Dockerfile: {image_file_path}") - LOGGER.debug(f" Build args: {build_args}") - build_logs = list() - try: - docker_client = docker.from_env() - _, build_logs = docker_client.images.build( - path=workdir_path.resolve().as_posix(), - dockerfile=image_file_path.resolve().as_posix(), - tag=image_name, - buildargs=build_args, - network_mode="host", - rm=True, - ) - except docker.errors.BuildError as e: - build_logs = e.build_log - raise e - finally: - for chunk in build_logs: - log = chunk.get("stream") - if log: - LOGGER.debug(log.rstrip()) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/maintainer.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/maintainer.py deleted file mode 100644 index 58ba7a6d5..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/maintainer/maintainer.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import abc -import pathlib -from typing import Any, Dict, List, Optional, Union - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .container import Container - - -class Maintainer(abc.ABC): - @abc.abstractmethod - def triton_container( - self, command: str, image: str, devices: List, volumes: Dict, environment: Dict, log_file: Union[pathlib.Path, str] - ) -> Container: - """ - Return triton container - - Args: - command: Triton Server command that has to be executed - image: Container image - devices: List of device ids which has to be available in container - volumes: Volumes mapping - environment: Environment variables set in container - log_file: File path where server logs has to be saved - - Returns: - Container object - """ - pass - - @abc.abstractmethod - def build_image( - self, - *, - image_file_path: pathlib.Path, - image_name: str, - workdir_path: Optional[pathlib.Path] = None, - build_args: Optional[Dict[str, Any]] = None, - ) -> None: - pass diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/pipeline.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/pipeline.py deleted file mode 100644 index acd21fa7e..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/pipeline.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import pathlib -from typing import Dict, Tuple - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .stages import ( - ConversionStage, - DeployStage, - ExportStage, - ResultsType, - TritonPerformanceOfflineStage, - TritonPerformanceOnlineStage, - TritonPreparePerformanceProfilingDataStage, -) - - -class Pipeline: - """ - Definition of stages that has to be executed before and during experiments - """ - - # Stages to execute as part of single experiment - _experiment_stages = [ - ExportStage.label, - ConversionStage.label, - DeployStage.label, - TritonPreparePerformanceProfilingDataStage.label, - TritonPerformanceOfflineStage.label, - TritonPerformanceOnlineStage.label, - ] - - def __init__(self): - """ - Initialize pipeline - """ - self._stages: Dict = dict() - - def model_export(self, commands: Tuple[str, ...]) -> None: - """ - Model export stage - - Args: - commands: Commands to be executed as part of stage - - Returns: - None - """ - stage = ExportStage(commands=commands) - self._stages[stage.label] = stage - - def model_conversion(self, commands: Tuple[str, ...]) -> None: - """ - Model conversion stage - - Args: - commands: Commands to be executed as part of stage - - Returns: - None - """ - stage = ConversionStage(commands=commands) - self._stages[stage.label] = stage - - def model_deploy(self, commands: Tuple[str, ...]) -> None: - """ - Model deployment stage - - Args: - commands: Commands to be executed as part of stage - - Returns: - None - """ - stage = DeployStage(commands=commands) - self._stages[stage.label] = stage - - def triton_prepare_performance_profiling_data(self, commands: Tuple[str, ...]) -> None: - """ - Model profiling data creation stage - - Args: - commands: Commands to be executed as part of stage - - Returns: - None - """ - stage = TritonPreparePerformanceProfilingDataStage(commands=commands) - self._stages[stage.label] = stage - - def triton_performance_offline_tests(self, commands: Tuple[str, ...], result_path: str) -> None: - """ - Model performance offline test stage - - Args: - commands: Commands to be executed as part of stage - result_path: Path where results file is stored - - Returns: - None - """ - stage = TritonPerformanceOfflineStage( - commands=commands, - result_path=result_path, - result_type=ResultsType.TRITON_PERFORMANCE_OFFLINE, - ) - self._stages[stage.label] = stage - - def triton_performance_online_tests(self, commands: Tuple[str, ...], result_path: str) -> None: - """ - Model performance online test stage - - Args: - commands: Commands to be executed as part of stage - result_path: Path where results file is stored - - Returns: - None - """ - stage = TritonPerformanceOnlineStage( - commands=commands, - result_path=result_path, - result_type=ResultsType.TRITON_PERFORMANCE_ONLINE, - ) - self._stages[stage.label] = stage - - def stages(self): - """ - Generate stages which should be run per experiment - - Returns: - Generator with stages object - """ - for stage_name in self._experiment_stages: - stage = self._stages.get(stage_name) - if not stage: - continue - - yield stage diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/pipeline_impl.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/pipeline_impl.py deleted file mode 100755 index 422bbbd56..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/pipeline_impl.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import pathlib - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .pipeline import Pipeline - -pipeline = Pipeline() -pipeline.model_export( - commands=( - r""" - if [[ "${EXPORT_FORMAT}" == "ts-trace" || "${EXPORT_FORMAT}" == "ts-script" ]]; then - export FORMAT_SUFFIX="pt" - else - export FORMAT_SUFFIX="${EXPORT_FORMAT}" - fi - python3 triton/export_model.py \ - --input-path triton/model.py \ - --input-type pyt \ - --output-path ${SHARED_DIR}/exported_model.${FORMAT_SUFFIX} \ - --output-type ${EXPORT_FORMAT} \ - --ignore-unknown-parameters \ - --onnx-opset 13 \ - \ - --checkpoint ${CHECKPOINT_DIR}/ \ - --precision ${EXPORT_PRECISION} \ - \ - --dataloader triton/dataloader.py \ - --dataset ${DATASETS_DIR}/${DATASET} \ - --batch-size 1 - """, - ) -) -pipeline.model_conversion( - commands=( - r""" - if [[ "${EXPORT_FORMAT}" == "ts-trace" || "${EXPORT_FORMAT}" == "ts-script" ]]; then - export FORMAT_SUFFIX="pt" - else - export FORMAT_SUFFIX="${EXPORT_FORMAT}" - fi - model-navigator convert \ - --model-name ${MODEL_NAME} \ - --model-path ${SHARED_DIR}/exported_model.${FORMAT_SUFFIX} \ - --output-path ${SHARED_DIR}/converted_model \ - --target-formats ${FORMAT} \ - --target-precisions ${PRECISION} \ - --launch-mode local \ - --override-workspace \ - --verbose \ - \ - --onnx-opsets 13 \ - --max-batch-size ${MAX_BATCH_SIZE} \ - --container-version 21.08 \ - --max-workspace-size 10000000000 \ - --atol target__0=100 \ - --rtol target__0=100 - """, - ) -) - -pipeline.model_deploy( - commands=( - r""" - if [[ "${FORMAT}" == "ts-trace" || "${FORMAT}" == "ts-script" ]]; then - export CONFIG_FORMAT="torchscript" - else - export CONFIG_FORMAT="${FORMAT}" - fi - - model-navigator triton-config-model \ - --model-repository ${MODEL_REPOSITORY_PATH} \ - --model-name ${MODEL_NAME} \ - --model-version 1 \ - --model-path ${SHARED_DIR}/converted_model \ - --model-format ${CONFIG_FORMAT} \ - --model-control-mode ${TRITON_LOAD_MODEL_METHOD} \ - --load-model \ - --load-model-timeout-s 100 \ - --verbose \ - \ - --backend-accelerator ${ACCELERATOR} \ - --tensorrt-precision ${PRECISION} \ - --tensorrt-capture-cuda-graph \ - --tensorrt-max-workspace-size 10000000000 \ - --max-batch-size ${MAX_BATCH_SIZE} \ - --batching dynamic \ - --preferred-batch-sizes ${TRITON_PREFERRED_BATCH_SIZES} \ - --max-queue-delay-us ${TRITON_MAX_QUEUE_DELAY} \ - --engine-count-per-device ${DEVICE}=${TRITON_GPU_ENGINE_COUNT} - """, - ) -) -pipeline.triton_prepare_performance_profiling_data( - commands=( - r""" - mkdir -p ${SHARED_DIR}/input_data - """, -r""" - python triton/prepare_input_data.py \ - --input-data-dir ${SHARED_DIR}/input_data/ \ - --dataset ${DATASETS_DIR}/${DATASET} \ - --checkpoint ${CHECKPOINT_DIR}/ \ - """, - ) -) -pipeline.triton_performance_offline_tests( - commands=( - r""" - python triton/run_performance_on_triton.py \ - --model-repository ${MODEL_REPOSITORY_PATH} \ - --model-name ${MODEL_NAME} \ - --input-data ${SHARED_DIR}/input_data/data.json \ - --batch-sizes ${BATCH_SIZE} \ - --number-of-triton-instances ${TRITON_INSTANCES} \ - --batching-mode static \ - --evaluation-mode offline \ - --measurement-request-count ${REQUEST_COUNT} \ - --warmup \ - --performance-tool perf_analyzer \ - --result-path ${SHARED_DIR}/triton_performance_offline.csv - """, - ), - result_path="${SHARED_DIR}/triton_performance_offline.csv", -) -pipeline.triton_performance_online_tests( - commands=( - r""" - python triton/run_performance_on_triton.py \ - --model-repository ${MODEL_REPOSITORY_PATH} \ - --model-name ${MODEL_NAME} \ - --input-data ${SHARED_DIR}/input_data/data.json \ - --batch-sizes ${BATCH_SIZE} \ - --number-of-triton-instances ${TRITON_INSTANCES} \ - --number-of-model-instances ${TRITON_GPU_ENGINE_COUNT} \ - --batching-mode dynamic \ - --evaluation-mode online \ - --measurement-request-count 500 \ - --warmup \ - --performance-tool perf_analyzer \ - --result-path ${SHARED_DIR}/triton_performance_online.csv - """, - ), - result_path="${SHARED_DIR}/triton_performance_online.csv", -) \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/preparer.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/preparer.py deleted file mode 100644 index 8cd7d0fab..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/preparer.py +++ /dev/null @@ -1,286 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import abc -import pathlib -from datetime import datetime -from typing import Dict, List - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .config import Config -from .configuration import Configuration -from .downloader import download -from .experiment import Experiment, Stage -from .logger import LOGGER -from .maintainer import Maintainer -from .pipeline import Pipeline -from .stages import ResultsType, TritonPerformanceOfflineStage, TritonPerformanceOnlineStage -from .task import Checkpoint, Dataset, SystemInfo, Task -from .triton import Triton -from .utils import clean_directory - - -class Preparer(abc.ABC): - """ - Runner preparer object. - """ - - @abc.abstractmethod - def exec( - self, - workspace: pathlib.Path, - config: Config, - pipeline: Pipeline, - maintainer: Maintainer, - triton: Triton, - logs_dir: pathlib.Path, - ): - pass - - -class ExperimentPreparer(Preparer): - """ - Experiment runner preparer object. - """ - - def exec( - self, - workspace: pathlib.Path, - config: Config, - pipeline: Pipeline, - maintainer: Maintainer, - triton: Triton, - logs_dir: pathlib.Path, - ): - LOGGER.info("Preparing Triton container image") - triton_container_image = self._prepare_triton_container_image(config, maintainer, triton) - - LOGGER.info("Initialize task") - task = self._initialize_task( - workspace=workspace, - config=config, - pipeline=pipeline, - triton_container_image=triton_container_image, - logs_dir=logs_dir, - ) - - LOGGER.info("Preparing directories") - self._create_dirs(workspace, task) - - LOGGER.info("Clean previous run artifacts directories") - self._clean_previous_run_artifacts(workspace, task) - - LOGGER.info("Downloading checkpoints") - self._download_checkpoints(task) - - return task - - def _create_dirs(self, workspace: pathlib.Path, task: Task) -> None: - """ - Create directories used to store artifacts and final results - - Returns: - None - """ - for directory in [task.results_dir, task.logs_dir, task.checkpoints_dir]: - directory_path = workspace / directory - directory_path.mkdir(parents=True, exist_ok=True) - LOGGER.info(f"Directory {directory} created.") - - def _clean_previous_run_artifacts(self, workspace: pathlib.Path, task: Task) -> None: - """ - Clean logs from previous run - - Returns: - None - """ - - for directory in [ - task.logs_dir, - task.results_dir, - ]: - directory_path = workspace / directory - clean_directory(directory_path) - LOGGER.info(f"Location {directory} cleaned.") - - def _prepare_triton_container_image(self, config: Config, maintainer: Maintainer, triton: Triton) -> str: - """ - Prepare Triton Container Image based on provided configuration - - Returns: - Name of container image to use in process - """ - if not config.triton_dockerfile: - image_name = triton.container_image(config.container_version) - LOGGER.info(f"Using official Triton container image: {image_name}.") - return image_name - - if config.triton_container_image: - LOGGER.info(f"Using provided Triton Container Image: {config.triton_container_image}") - return config.triton_container_image - - normalized_model_name = config.model_name.lower().replace("_", "-") - image_name = f"tritonserver-{normalized_model_name}:latest" - LOGGER.info(f"Building Triton Container Image: {image_name}") - - maintainer.build_image( - image_name=image_name, - image_file_path=pathlib.Path(config.triton_dockerfile), - build_args={"FROM_IMAGE": triton.container_image(container_version=config.container_version)}, - ) - return image_name - - def _download_checkpoints(self, task: Task) -> None: - """ - Download checkpoints - """ - for variant, checkpoint in task.checkpoints.items(): - checkpoint_url = checkpoint.url - download_path = checkpoint.path - - if download_path.is_dir(): - LOGGER.info(f"Checkpoint {download_path.name} already downloaded.") - continue - - if not checkpoint_url: - LOGGER.warning( - f"Checkpoint {variant} url is not provided." - "\nIf you want to use that checkpoint please train the model locally" - f"\nand copy to {download_path} directory" - ) - continue - - download(checkpoint_url, download_path) - - def _initialize_task( - self, - workspace: pathlib.Path, - config: Config, - pipeline: Pipeline, - triton_container_image: str, - logs_dir: pathlib.Path, - ) -> Task: - """ - Initialize task object - - Args: - workspace: Path to workspace where artifacts are stored - config: Config object - pipeline: Pipeline object - triton_container_image: Triton Inference Server container image used for tests - - Returns: - Task object - """ - datasets = {} - for dataset in config.datasets: - datasets[dataset.name] = Dataset(name=dataset.name) - - checkpoints = {} - for checkpoint in config.checkpoints: - download_path = workspace / Task.checkpoints_dir / checkpoint.name - checkpoints[checkpoint.name] = Checkpoint(name=checkpoint.name, url=checkpoint.url, path=download_path) - - results_types = self._task_results_types(pipeline=pipeline) - - stages = dict() - for stage in pipeline.stages(): - stages[stage.label] = {"result_path": stage.result_path, "result_type": stage.result_type} - - experiments = list() - for idx, configuration in enumerate(config.configurations, start=1): - experiment = self._prepare_experiment( - idx=idx, - configuration=configuration, - results_types=results_types, - stages=stages, - ) - experiments.append(experiment) - - system_info = SystemInfo.from_host() - - task = Task( - model_name=config.model_name, - framework=config.framework, - checkpoints=checkpoints, - datasets=datasets, - datasets_dir=config.datasets_dir, - experiments=experiments, - container_version=config.container_version, - system_info=system_info, - triton_container_image=triton_container_image, - triton_custom_operations=config.triton_custom_operations, - triton_load_model_method=config.triton_load_model_method, - started_at=int(datetime.utcnow().timestamp()), - logs_dir=logs_dir, - ) - return task - - def _task_results_types(self, pipeline: Pipeline) -> List[str]: - """ - Types of results generated as part of task - - Returns: - List of result types - """ - results = list() - for stage in pipeline.stages(): - if TritonPerformanceOfflineStage.label == stage.label: - results.append(ResultsType.TRITON_PERFORMANCE_OFFLINE) - continue - - if TritonPerformanceOnlineStage.label == stage.label: - results.append(ResultsType.TRITON_PERFORMANCE_ONLINE) - continue - - return results - - def _prepare_experiment( - self, - idx: int, - configuration: Configuration, - results_types: List[str], - stages: Dict, - ) -> Experiment: - """ - Prepare experiments data - - Args: - idx: Experiment index - configuration: Configuration object - results_types: Results types stored in experiment - stages: Stages executed as part of experiment - - Returns: - Experiment object - """ - parameters = {key.lower(): value for key, value in configuration.parameters.items()} - results_mapped = dict() - for result_type in results_types: - results_mapped[result_type] = result_type - - stages_mapped = dict() - for name, stage_data in stages.items(): - stages_mapped[name] = Stage(name=name, **stage_data) - - experiment = Experiment( - experiment_id=idx, - parameters=parameters, - stages=stages_mapped, - results=results_mapped, - ) - - return experiment diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/requirements.txt b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/requirements.txt deleted file mode 100644 index 51d04c1c8..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/requirements.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -tqdm>=4.44.1 -docker==5.0.0 -colorama==0.4.4 -pytz==2021.1 -coloredlogs==15.0.1 -py-cpuinfo==8.0.0 -psutil==5.8.0 -retrying>=1.3.3 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/runner.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/runner.py deleted file mode 100644 index f938ef482..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/runner.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import logging -import pathlib -import signal -import sys -from typing import List, Type - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .config import Config -from .exceptions import RunnerException -from .executor import Executor -from .finalizer import Finalizer -from .logger import LOGGER, log_format -from .maintainer import Maintainer -from .pipeline import Pipeline -from .preparer import Preparer -from .triton import Triton - - -class Runner: - """ - Runner class. Main entrypoint to performing task and experiments - """ - - WORKSPACE = pathlib.Path.cwd() - EXECUTOR_WORKSPACE = WORKSPACE / "runner_workspace" - - def __init__( - self, - pipeline: Pipeline, - config: Config, - executor_cls: Type[Executor], - maintainer_cls: Type[Maintainer], - preparer_cls: Type[Preparer], - finalizer_cls: Type[Finalizer], - devices: List[str] = None, - log_level: int = logging.INFO, - ): - self._pipeline = pipeline - self._config = config - - self._pipeline = pipeline - self._config = config - self._preparer = preparer_cls() - self._finalizer = finalizer_cls() - self._devices = devices or ["0"] - self._log_level = log_level - self._logs_dir = self.EXECUTOR_WORKSPACE / "logs" - self._log_file_path = self._logs_dir / "runner.log" - - self._maintainer = maintainer_cls() - - self._executor = executor_cls( - workspace=self.EXECUTOR_WORKSPACE, - maintainer=self._maintainer, - pipeline=pipeline, - devices=devices, - ) - - signal.signal(signal.SIGINT, self._catch) - - self._logs_dir.mkdir(parents=True, exist_ok=True) - - def start(self) -> None: - """ - Start runner - - Returns: - None - """ - self._setup_logger() - - task = self._preparer.exec( - workspace=self.EXECUTOR_WORKSPACE, - config=self._config, - pipeline=self._pipeline, - logs_dir=self._logs_dir, - maintainer=self._maintainer, - triton=Triton(), - ) - - results = [] - try: - for result in self._executor.start(task): - results.append(result) - except RunnerException as e: - LOGGER.error(f"Error running task: {str(e)}") - finally: - self._executor.stop() - self._finalizer.exec(workspace=self.EXECUTOR_WORKSPACE, task=task, results=results) - - def _catch(self, signum, frame): - """ - SIGINT catcher. Stops executor on any sigterm. - - Args: - signum: signal id - frame: signal frame - """ - self._executor.stop() - - sys.exit(0) - - def _setup_logger(self) -> None: - """ - Add file handle for logger - - Returns: - None - """ - file = logging.FileHandler(self._log_file_path) - formatter = logging.Formatter(log_format) - file.setFormatter(formatter) - - LOGGER.addHandler(file) - LOGGER.setLevel(level=self._log_level) - LOGGER.initialize(file_path=self._log_file_path) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/runner_proxy.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/runner_proxy.py deleted file mode 100644 index 9054d9221..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/runner_proxy.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import pathlib -from typing import List, Type - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .config import Config -from .executor import Executor -from .finalizer import Finalizer -from .maintainer import Maintainer -from .pipeline import Pipeline -from .preparer import Preparer -from .runner import Runner - - -class RunnerProxy: - """ - Runner proxy to configure original runner - """ - - maintainer_cls: Type[Maintainer] = None - executor_cls: Type[Executor] = None - preparer_cls: Type[Preparer] = None - finalizer_cls: Type[Finalizer] = None - - def __init__(self, config: Config, pipeline: Pipeline, devices: List[str]): - """ - RunnerProxy constructor - - Args: - config: Config object - pipeline: Pipeline to evaluate - devices: List of devices to use for tests - """ - self._runner = Runner( - config=config, - pipeline=pipeline, - devices=devices, - maintainer_cls=self.maintainer_cls, - executor_cls=self.executor_cls, - preparer_cls=self.preparer_cls, - finalizer_cls=self.finalizer_cls, - ) - - def start(self) -> None: - """ - Runner interface - """ - self._runner.start() diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/stages.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/stages.py deleted file mode 100644 index 397069ea6..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/stages.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pathlib -from typing import List, Optional, Tuple, Union - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .core import Command - - -class ResultsType: - """ - Results types generated by runner - """ - - TRITON_PERFORMANCE_OFFLINE = "triton_performance_offline" - TRITON_PERFORMANCE_ONLINE = "triton_performance_online" - - -class Stage: - """ - Stage definition - """ - - label: str - commands: List[Command] - result_path: Optional[str] - result_type: Optional[str] - - def __init__( - self, - commands: Union[Tuple[str, ...], List[str]], - result_path: Optional[str] = None, - result_type: Optional[str] = None, - ): - """ - - Args: - commands: List or Tuple of commands provided as raw string - result_path: Path to results file generated by stage - result_type: Type of results generated by stage - """ - if type(commands) not in [tuple, list]: - raise ValueError("""Incorrect type of commands list. Please, provide list of commands as tuple.""") - - self.commands = list(map(lambda command: Command(data=command), commands)) - self.result_path = result_path - self.result_type = result_type - - -class ExportStage(Stage): - label = "Export Model" - - -class ConversionStage(Stage): - label = "Convert Model" - - -class DeployStage(Stage): - label = "Deploy Model" - - -class CorrectnessStage(Stage): - label = "Model Correctness Tests" - - -class TritonPreparePerformanceProfilingDataStage(Stage): - label = "Prepare Triton Profiling Data" - - -class TritonPerformanceOfflineStage(Stage): - label = "Triton Performance Offline Tests" - - -class TritonPerformanceOnlineStage(Stage): - label = "Triton Performance Online Tests" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-A30.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-A30.sh deleted file mode 100755 index 9ec64eec5..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-A30.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#!/bin/bash -# Install Docker -. /etc/os-release && \ -curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \ -echo "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/docker.list && \ -curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey| apt-key add - && \ -curl -s -L https://nvidia.github.io/nvidia-docker/$ID$VERSION_ID/nvidia-docker.list > /etc/apt/sources.list.d/nvidia-docker.list && \ -apt-get update && \ -apt-get install -y docker-ce docker-ce-cli containerd.io nvidia-docker2 - -# Install packages -pip install -r triton/runner/requirements.txt - -# Evaluate Runner -python3 -m "triton.runner.__main__" \ - --config-path "triton/runner/config_NVIDIA-A30.yaml" \ - --device 0 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-DGX-1-(1x-V100-32GB).sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-DGX-1-(1x-V100-32GB).sh deleted file mode 100755 index 5621412f3..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-DGX-1-(1x-V100-32GB).sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#!/bin/bash -# Install Docker -. /etc/os-release && \ -curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \ -echo "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/docker.list && \ -curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey| apt-key add - && \ -curl -s -L https://nvidia.github.io/nvidia-docker/$ID$VERSION_ID/nvidia-docker.list > /etc/apt/sources.list.d/nvidia-docker.list && \ -apt-get update && \ -apt-get install -y docker-ce docker-ce-cli containerd.io nvidia-docker2 - -# Install packages -pip install -r triton/runner/requirements.txt - -# Evaluate Runner -python3 -m "triton.runner.__main__" \ - --config-path "triton/runner/config_NVIDIA-DGX-1-(1x-V100-32GB).yaml" \ - --device 0 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-DGX-A100-(1x-A100-80GB).sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-DGX-A100-(1x-A100-80GB).sh deleted file mode 100755 index a03f3cb45..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-DGX-A100-(1x-A100-80GB).sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#!/bin/bash -# Install Docker -. /etc/os-release && \ -curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \ -echo "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/docker.list && \ -curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey| apt-key add - && \ -curl -s -L https://nvidia.github.io/nvidia-docker/$ID$VERSION_ID/nvidia-docker.list > /etc/apt/sources.list.d/nvidia-docker.list && \ -apt-get update && \ -apt-get install -y docker-ce docker-ce-cli containerd.io nvidia-docker2 - -# Install packages -pip install -r triton/runner/requirements.txt - -# Evaluate Runner -python3 -m "triton.runner.__main__" \ - --config-path "triton/runner/config_NVIDIA-DGX-A100-(1x-A100-80GB).yaml" \ - --device 0 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-T4.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-T4.sh deleted file mode 100755 index 974082563..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/start_NVIDIA-T4.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#!/bin/bash -# Install Docker -. /etc/os-release && \ -curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \ -echo "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/docker.list && \ -curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey| apt-key add - && \ -curl -s -L https://nvidia.github.io/nvidia-docker/$ID$VERSION_ID/nvidia-docker.list > /etc/apt/sources.list.d/nvidia-docker.list && \ -apt-get update && \ -apt-get install -y docker-ce docker-ce-cli containerd.io nvidia-docker2 - -# Install packages -pip install -r triton/runner/requirements.txt - -# Evaluate Runner -python3 -m "triton.runner.__main__" \ - --config-path "triton/runner/config_NVIDIA-T4.yaml" \ - --device 0 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/summary.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/summary.py deleted file mode 100644 index 391c06ad6..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/summary.py +++ /dev/null @@ -1,187 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import csv -import json -import pathlib -from typing import Dict, List, Union - -# method from PEP-366 to support relative import in executed modules -import yaml - -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from ..deployment_toolkit.report import save_results, sort_results -from .logger import LOGGER - - -def save_summary(result_type: str, results: List, summary_dir: pathlib.Path) -> None: - """ - Create file with summary for results of given type - Args: - result_type: Type of results to dump - results: Results data - summary_dir: Path where results should be stored - - Returns: - None - """ - if len(results) == 0: - LOGGER.warning(f"No {result_type} results found.") - return - - results = sort_results(results=results) - - kind_file = summary_dir / f"{result_type}_summary.csv" - save_results(filename=kind_file.as_posix(), data=results, formatted=True) - LOGGER.info(f"Summary for {result_type} stored in {kind_file}") - - -def load_results(*, results_path: Union[pathlib.Path, str], result_type: str, parameters: Dict) -> List: - """ - Update results - Args: - results_path: Path to file or directory from which data should be read - result_type: type of results - parameters: Parameters used in experiment which generated results - - - Returns: - List of result rows - """ - LOGGER.debug(f"Loading {result_type} from {results_path} for summary") - results_path = pathlib.Path(results_path) - - if results_path.is_file(): - files = [results_path] - elif results_path.is_dir(): - files = list(results_path.iterdir()) - else: - LOGGER.debug(f"Unable to load file: {results_path}. Generating empty rows.") - data = [{}] - return data - - if any([file.name.endswith(".ckpt") for file in files]): - model_analyzer_metrics = results_path / "metrics-model-inference.csv" - files = [model_analyzer_metrics] - else: - files = [file for file in files if file.name.endswith(".csv")] - - results = list() - parameters_cpy = {key: value for key, value in parameters.items() if key != "batch"} - for file in files: - if file.suffix == ".csv": - data = _generate_data_from_csv(file=file) - elif file.suffix == ".json": - data = _generate_data_from_json(file=file) - elif file.suffix == ".yaml": - data = _generate_data_from_yaml(file=file) - else: - raise ValueError(f"Unsupported file extension: {file.suffix}") - - for item in data: - result = {**parameters_cpy, **item} - results.append(result) - - LOGGER.debug(f"Loading done. Collected {len(results)} results.") - return results - - -def _normalize_key(*, key: str) -> str: - """ - Normalize key - - Args: - key: Key to normalize - - Returns: - Normalized string - """ - key = "_".join(key.split(sep=" ")) - key = key.lower() - return key - - -def _normalize_keys(*, data: Dict) -> Dict: - """ - Normalize keys in dictionary - - Args: - data: Dictionary to normalize - - Returns: - Normalized dictionary - """ - keys = {_normalize_key(key=key): value for key, value in data.items()} - return keys - - -def _generate_data_from_csv(*, file: Union[pathlib.Path, str]) -> List[Dict]: - """ - Generate result rows from CSV file - Args: - file: CSV file path - - Returns: - List of rows - """ - LOGGER.debug(f"Reading data from {file}") - filtered_rows: List[Dict] = [] - with open(file, "r") as csvfile: - reader = csv.DictReader(csvfile) - for r in reader: - r = _normalize_keys(data=r) - filtered_row = {k: v for k, v in r.items()} - filtered_rows.append(filtered_row) - - LOGGER.debug("done") - - return filtered_rows - - -def _generate_data_from_json(file: pathlib.Path) -> List[Dict]: - LOGGER.info(f"Reading data from {file}") - filtered_rows: List[Dict] = list() - with open(file, "r") as json_file: - file_data = json.load(json_file) - if not isinstance(file_data, list): - file_data = [file_data] - - for r in file_data: - r = _normalize_keys(data=r) - filtered_row = {k: v for k, v in r.items()} - filtered_rows.append(filtered_row) - - LOGGER.info("done") - - return filtered_rows - - -def _generate_data_from_yaml(file: pathlib.Path) -> List[Dict]: - LOGGER.info(f"Reading data from {file}") - filtered_rows: List[Dict] = list() - with open(file, "r") as yaml_file: - file_data = yaml.safe_load(yaml_file) - if not isinstance(file_data, list): - file_data = [file_data] - - for r in file_data: - r = _normalize_keys(data=r) - filtered_row = {k: v for k, v in r.items()} - filtered_rows.append(filtered_row) - - LOGGER.info("done") - - return filtered_rows diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/task.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/task.py deleted file mode 100644 index b9ea264b9..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/task.py +++ /dev/null @@ -1,356 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pathlib -import platform -import subprocess -from datetime import datetime -from typing import Dict, List, Optional, Union - -import cpuinfo -import psutil -import yaml - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .core import CustomDumper, DataObject -from .experiment import Experiment -from .triton import Triton - - -class GPU(DataObject): - """ - GPU information data object - """ - - name: str - driver_version: str - cuda_version: str - memory: str - tdp: str - - def __init__(self, name: str, driver_version: str, cuda_version: str, memory: str, tdp: str): - """ - Args: - name: name of GPU - driver_version: version of driver - cuda_version: version of CUDA - memory: size of memory available on GPU [MB] - tdp: Max TDP of GPU unit - """ - self.name = name - self.driver_version = driver_version - self.cuda_version = cuda_version - self.memory = memory - self.tdp = tdp - - @staticmethod - def from_dict(data: Dict): - """ - Create GPU object from dictionary - - Args: - data: dictionary with GPU data - - Returns: - GPU object - """ - return GPU( - name=data["name"], - driver_version=data["driver_version"], - cuda_version=data["cuda_version"], - memory=data["memory"], - tdp=data["tdp"], - ) - - @staticmethod - def from_host(): - """ - Create GPU object from host data - - Returns: - GPU object - """ - data = subprocess.check_output( - ["nvidia-smi", "--query-gpu=name,driver_version,memory.total,power.max_limit", "--format=csv"] - ).decode() - - lines = data.split(sep="\n") - device_details = lines[1].split(",") - name = device_details[0].strip() - driver_version = device_details[1].strip() - memory = device_details[2].strip() - tdp = device_details[3].strip() - cuda_version = None - - data = subprocess.check_output(["nvidia-smi", "--query"]).decode() - lines = data.split(sep="\n") - for line in lines: - if line.startswith("CUDA Version"): - cuda_version = line.split(":")[1].strip() - break - - return GPU( - name=name, - driver_version=driver_version, - cuda_version=cuda_version, - memory=memory, - tdp=tdp, - ) - - -class CPU(DataObject): - """ - CPU details - """ - - name: str - physical_cores: int - logical_cores: int - min_frequency: float - max_frequency: float - - def __init__(self, name: str, physical_cores: int, logical_cores: int, min_frequency: float, max_frequency: float): - """ - Args: - name: name of CPU unit - physical_cores: number of physical cores available on CPU - logical_cores: number of logical cores available on CPU - min_frequency: minimal clock frequency - max_frequency: maximal clock frequency - """ - self.name = name - self.physical_cores = physical_cores - self.logical_cores = logical_cores - self.min_frequency = min_frequency - self.max_frequency = max_frequency - - @staticmethod - def from_host(): - """ - Create CPU object from host data - - Returns: - CPU object - """ - return CPU( - name=cpuinfo.get_cpu_info()["brand_raw"], - physical_cores=psutil.cpu_count(logical=False), - logical_cores=psutil.cpu_count(logical=True), - min_frequency=psutil.cpu_freq().min, - max_frequency=psutil.cpu_freq().max, - ) - - -class Memory(DataObject): - """ - Memory data object - """ - - size: float - - def __init__(self, size: float): - """ - Args: - size: RAM memory size in MB - """ - self.size = size - - @staticmethod - def from_host(): - """ - Create Memory object from host data - - Returns: - Memory object - """ - svm = psutil.virtual_memory() - return Memory(size=svm.total) - - -class SystemInfo(DataObject): - """ - System Information data object - """ - - system: str - cpu: CPU - memory: Memory - gpu: GPU - - def __init__(self, system: str, cpu: CPU, memory: Memory, gpu: GPU): - """ - Args: - system: name of operating system - cpu: CPU info - memory: Memory info - gpu: GPU info - """ - self.system = system - self.cpu = cpu - self.memory = memory - self.gpu = gpu - - @staticmethod - def from_host(): - """ - Create SystemInfo object from host data - - Returns: - SystemInfo object - """ - system = platform.platform() - gpu = GPU.from_host() - memory = Memory.from_host() - cpu = CPU.from_host() - - return SystemInfo(system=system, cpu=cpu, gpu=gpu, memory=memory) - - -class Checkpoint(DataObject): - """ - Checkpoint data object - """ - - def __init__(self, name: str, url: str, path: Union[str, pathlib.Path]): - """ - Args: - name: Name of checkpoint - path: Location of checkpoint on local hardware - """ - self.name = name - self.url = url - self.path = pathlib.Path(path) - - -class Dataset(DataObject): - """ - Dataset data object - """ - - def __init__(self, name: str): - """ - Args: - name: Name of dataset - """ - self.name = name - - -class Task(DataObject): - """ - Task data object to store build information - """ - - model_name: str - framework: str - started_at: int - ended_at: Optional[int] - container_version: str - checkpoints: Dict[str, Checkpoint] - datasets: Dict[str, Dataset] - datasets_dir: Optional[Union[str, pathlib.Path]] - experiments: List[Experiment] - system_info: SystemInfo - triton_container_image: Optional[str] - triton_custom_operations: Optional[str] - - filename: str = "task.yaml" - results_dir: str = "results" - checkpoints_dir: str = "checkpoints" - - def __init__( - self, - model_name: str, - framework: str, - container_version: str, - checkpoints: Dict, - datasets: Dict, - experiments: List, - system_info: SystemInfo, - started_at: int, - logs_dir: pathlib.Path = pathlib.Path("/var/logs"), - datasets_dir: Optional[Union[str, pathlib.Path]] = None, - ended_at: Optional[int] = None, - triton_container_image: Optional[str] = None, - triton_custom_operations: Optional[str] = None, - triton_load_model_method: str = Triton.LOAD_MODE.EXPLICIT, - ): - """ - - Args: - model_name: Name of model - framework: Model framework - container_version: Container version used in task - checkpoints: List of checkpoints - datasets: List of datasets - datasets_dir: Directory where datasests are stored - experiments: List of experiments run as part of task - system_info: information about node on which experiment was executed - started_at: Time when task has started - ended_at: Time when task has ended - triton_container_image: Custom Triton Container Image used for task - triton_custom_operations: Custom operations library path - triton_load_model_method: Method how models are loaded on Triton - """ - self.started_at = started_at - self.ended_at = ended_at - - self.model_name = model_name - self.framework = framework - self.container_version = container_version - self.checkpoints = checkpoints - self.datasets = datasets - self.datasets_dir = pathlib.Path(datasets_dir) - self.experiments = experiments - self.system_info = system_info - - self.triton_container_image = triton_container_image - self.triton_custom_operations = triton_custom_operations - self.triton_load_model_method = triton_load_model_method - - self.logs_dir = logs_dir - - def start(self) -> None: - """ - Update stage execution info at start - - Returns: - None - """ - self.started_at = int(datetime.utcnow().timestamp()) - - def end(self) -> None: - """ - Update stage execution info at end - - Returns: - None - """ - self.ended_at = int(datetime.utcnow().timestamp()) - - def to_file(self, file_path: Union[pathlib.Path, str]): - """ - Store task data to YAML file - - Args: - file_path: path to file where task data has to be saved - - Returns: - None - """ - task_data = self.to_dict() - with open(file_path, "w") as f: - yaml.dump(task_data, f, Dumper=CustomDumper, width=240, sort_keys=False) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/triton.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/triton.py deleted file mode 100644 index cd8a4dda1..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/triton.py +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import pathlib - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .core import Framework, Paths - - -class Triton: - """ - Triton Inference Server helper class - """ - - image = "nvcr.io/nvidia/tritonserver" - tag = "py3" - - class LOAD_MODE: - """ - Loading mode available in Triton - """ - - POLL = "poll" - EXPLICIT = "explicit" - - @staticmethod - def container_image(container_version: str): - """ - Container image based on version - - Args: - container_version: Version of container to be used - - Returns: - Image name with tag - """ - return f"{Triton.image}:{container_version}-{Triton.tag}" - - @staticmethod - def command( - framework: str, - repository_path: str, - strict_mode: bool = False, - poll_model: bool = False, - metrics: bool = False, - verbose: bool = False, - ): - """ - Command to run Triton Inference Server inside container - Args: - framework: Framework used for model - repository_path: Path to model repository - strict_mode: Flag to use strict model config - poll_model: Poll model - metrics: Enable GPU metrics (disable for MIG) - verbose: Use verbose mode logging - - Returns: - - """ - triton_command = f"tritonserver --model-store={repository_path}" - if poll_model: - triton_command += " --model-control-mode=poll --repository-poll-secs 5" - else: - triton_command += " --model-control-mode=explicit" - - if not strict_mode: - triton_command += " --strict-model-config=false" - - if not metrics: - triton_command += " --allow-metrics=false --allow-gpu-metrics=false" - - if verbose: - triton_command += " --log-verbose 1" - - if framework in (Framework.TensorFlow1, Framework.TensorFlow2): - version = 1 if framework == Framework.TensorFlow1 else 2 - triton_command += f" --backend-config=tensorflow,version={version}" - - return triton_command - - @staticmethod - def library_path(framework: str): - """ - Obtain custom library path for framework - - Args: - framework: Framework used for model - - Returns: - Path to additional libraries needed by framework - """ - paths = { - Framework.PyTorch.name: "/opt/tritonserver/backends/pytorch", - Framework.TensorFlow1.name: "/opt/tritonserver/backends/tensorflow1", - Framework.TensorFlow2.name: "/opt/tritonserver/backends/tensorflow2", - } - - return paths[framework] - - @staticmethod - def custom_library_path_remote() -> str: - """ - Path to custom library mounted in Triton container - - Returns: - Path to shared library with custom operations - """ - return f"{Paths.LIBRARIES_PATH}/libcustomops.so" - - @staticmethod - def custom_library_path_local(libs_dir: pathlib.Path) -> pathlib.Path: - """ - Path to custom library in local path - - Args: - libs_dir: path to libraries directory - - Returns: - Path to shared library with custom operations - """ - return libs_dir / "libcustomops.so" diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/utils.py deleted file mode 100644 index 316981be7..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/runner/utils.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -import pathlib -import shutil -import subprocess -from enum import Enum -from typing import Any, List, Optional - -# method from PEP-366 to support relative import in executed modules -if __name__ == "__main__" and __package__ is None: - __package__ = pathlib.Path(__file__).parent.name - -from .core import Command -from .exceptions import RunnerException -from .logger import LOGGER - - -def format_env_key(s: str): - """ - Format environmental variable key - - Args: - s: String to format - - Returns: - Upper cased string - """ - return s.upper() - - -def format_env_value(value: Any) -> str: - """ - Format environment variable value - - Args: - value: value to be formatted - - Returns: - Formatted value as a string - """ - value = value if not isinstance(value, Enum) else value.value - value = value if type(value) not in [list, tuple] else ",".join(map(str, value)) - value = str(value) - return value - - -def get_result_path(result_path: str) -> str: - """ - Map result path when different variants passed ex. with env variable in path - - Args: - result_path: Path to result file - - Returns: - str - """ - for env_var, val in os.environ.items(): - result_path = result_path.replace(f"${{{env_var}}}", val) - - if result_path.startswith("/"): - return result_path - - if result_path.startswith("./"): - result_path = result_path[2:] - - return result_path - - -def clean_directory(directory: pathlib.Path) -> None: - """ - Remove all files and directories from directory - - Args: - directory: Path to directory which should be cleaned - - Returns: - None - """ - LOGGER.debug(f"Cleaning {directory.as_posix()}") - if not directory.is_dir(): - LOGGER.warning(f"{directory.name} is not a directory.") - return - - for item in os.listdir(directory): - item_path = directory / item - if item_path.is_dir(): - LOGGER.debug(f"Remove dir {item_path.as_posix()}") - shutil.rmtree(item_path.as_posix()) - elif item_path.is_file(): - LOGGER.debug(f"Remove file: {item_path.as_posix()}") - item_path.unlink() - else: - LOGGER.warning(f"Cannot remove item {item_path.name}. Not a file or directory.") - - -def exec_command(command: Command) -> None: - """ - Execute command - - Args: - command: Command to run - """ - try: - process = subprocess.Popen( - [str(command)], - shell=True, - start_new_session=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - encoding="utf-8", - ) - while True: - output = process.stdout.readline() - if output == "" and process.poll() is not None: - break - - if output: - print(output.rstrip()) - LOGGER.write(output) - - result = process.poll() - if result != 0: - raise RunnerException(f"Command {command} failed with exit status: {result}") - - except subprocess.CalledProcessError as e: - raise RunnerException(f"Running command {e.cmd} failed with exit status {e.returncode} : {e.output}") diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/interactive.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/interactive.sh deleted file mode 100644 index c8350818b..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/interactive.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -DATASET_PATH=${1:-"/data/"} -NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES:=0} - -docker run -it --rm \ - --runtime=nvidia \ - -e NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES} \ - --net=host \ - --shm-size=1g \ - --ulimit memlock=-1 \ - --ulimit stack=67108864 \ - --ipc=host \ - -e WORKDIR="$(pwd)" \ - -e PYTHONPATH="$(pwd)" \ - -v ${DATASET_PATH}/processed/:"$(pwd)"/datasets/ \ - -v "$(pwd)":"$(pwd)" \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -w "$(pwd)" \ - tft:latest bash diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/triton_inference_server.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/triton_inference_server.sh deleted file mode 100644 index bf8b2c124..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/docker/triton_inference_server.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Install Docker -. /etc/os-release && \ -curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \ -echo "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" > /etc/apt/sources.list.d/docker.list && \ -curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey| apt-key add - && \ -curl -s -L https://nvidia.github.io/nvidia-docker/$ID$VERSION_ID/nvidia-docker.list > /etc/apt/sources.list.d/nvidia-docker.list && \ -apt-get update && \ -apt-get install -y docker-ce docker-ce-cli containerd.io nvidia-docker2 -WORKDIR="${WORKDIR:=$(pwd)}" -export DATASETS_DIR=${WORKDIR}/datasets -export WORKSPACE_DIR=${WORKDIR}/runner_workspace -export CHECKPOINTS_DIR=${WORKSPACE_DIR}/checkpoints -export MODEL_REPOSITORY_PATH=${WORKSPACE_DIR}/model_store -export SHARED_DIR=${WORKSPACE_DIR}/shared_dir -NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES:=all} - -docker run --rm -d \ - -p 8000:8000 \ - -p 8001:8001 \ - -p 8002:8002 \ - --runtime=nvidia \ - -e NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES} \ - -e ORT_TENSORRT_FP16_ENABLE=1 \ - -v ${MODEL_REPOSITORY_PATH}:${MODEL_REPOSITORY_PATH} \ - --shm-size=1g \ - --ulimit memlock=-1 \ - --ulimit stack=67108864 \ - --ipc=host \ - nvcr.io/nvidia/tritonserver:21.12-py3 tritonserver \ - --model-store=${MODEL_REPOSITORY_PATH} \ - --strict-model-config=false \ - --exit-on-error=true \ - --model-control-mode=explicit \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/setup_environment.sh b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/setup_environment.sh deleted file mode 100644 index ea4987f96..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/triton/scripts/setup_environment.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -WORKDIR="${WORKDIR:=$(pwd)}" -export DATASETS_DIR=${WORKDIR}/datasets -export WORKSPACE_DIR=${WORKDIR}/runner_workspace -export CHECKPOINTS_DIR=${WORKSPACE_DIR}/checkpoints -export MODEL_REPOSITORY_PATH=${WORKSPACE_DIR}/model_store -export SHARED_DIR=${WORKSPACE_DIR}/shared_dir - -echo "Preparing directories" -mkdir -p ${WORKSPACE_DIR} -mkdir -p ${DATASETS_DIR} -mkdir -p ${CHECKPOINTS_DIR} -mkdir -p ${MODEL_REPOSITORY_PATH} -mkdir -p ${SHARED_DIR} - -echo "Setting up environment" -export MODEL_NAME=TFT -export ENSEMBLE_MODEL_NAME= -export TRITON_LOAD_MODEL_METHOD=explicit -export TRITON_INSTANCES=1 \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/utils.py deleted file mode 100644 index bf88be40c..000000000 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tft_pyt/utils.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import time - -class PerformanceMeter(): - def __init__(self): - self.reset() - - def reset(self): - self.avg = 0 - self.count = 0 - self.total_time = 0 - self.last_update_time = time.time() - self.intervals = [] - - def update(self, n, exclude_from_total=False): - delta = time.time() - self.last_update_time - self.intervals.append(delta) - if not exclude_from_total: - self.total_time += delta - self.count += n - self.avg = self.count / self.total_time - self.last_update_time = time.time() - - return n/delta - - def reset_current_lap(self): - self.last_update_time = time.time() - - def p(self, i): - assert i <= 100 - idx = int(len(self.intervals) * i / 100) - return sorted(self.intervals)[idx] - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/trivial_model.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/trivial_model.py index 66fc72b40..902473dab 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/trivial_model.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/trivial_model.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 import torch import torch.nn as nn @@ -37,11 +37,9 @@ def predict(self, batch): prev_predictions = targets.roll(1, 1) return prev_predictions[:, -self.predict_steps :, :] - # TODO: reenable usage of such functions def test_with_last(self, batch): bs = max([tensor.shape[0] if tensor is not None else 0 for tensor in batch.values()]) values = ( - # TODO: this will become disfuntional after removing "targer_masked" from dataset. Seed comment in data_utils.py batch["target_masked"] .clone()[:, -1, :] .reshape((bs, 1, self.output_dim)) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tspp_xgboost.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tspp_xgboost.py index 02b3d47e6..65f4885ea 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tspp_xgboost.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/models/tspp_xgboost.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -23,12 +23,15 @@ import dask_cudf from distributed_utils import create_client +#Deal with the pateince and log_interval. Also objective, cluster class TSPPXGBoost(): def __init__(self, config): self.config = config self.models = [] def fit(self, train, label, valid, valid_label, **kwargs): + train = train.drop(['_id_', '_timestamp_'], axis=1, errors='ignore') + valid = valid.drop(['_id_', '_timestamp_'], axis=1, errors='ignore') X = xgb.DeviceQuantileDMatrix(cudf.from_pandas(train), label=cudf.from_pandas(label)) V = xgb.DMatrix(cudf.from_pandas(valid), label=cudf.from_pandas(valid_label)) model = xgb.train(params=self.config, @@ -41,6 +44,7 @@ def fit(self, train, label, valid, valid_label, **kwargs): self.models.append(model) def predict(self, test, i): + test = test.drop(['_id_', '_timestamp_'], axis=1, errors='ignore') model = self.models[i] X = xgb.DMatrix(cudf.from_pandas(test)) return model.predict(X) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/requirements.txt b/Tools/PyTorch/TimeSeriesPredictionPlatform/requirements.txt index b0421f199..cc6a537d7 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/requirements.txt +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/requirements.txt @@ -1,25 +1,20 @@ -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - +# SPDX-License-Identifier: Apache-2.0 pmdarima==1.8.0 +matplotlib==3.3.2 wget==3.2 hydra-core==1.1.1 pyunpack==0.2.2 +py7zr==0.15.0 +patool==1.12 tensorboard optuna optuna-dashboard -hydra-optuna-sweeper==1.1.2 -hydra-joblib-launcher==1.1.5 -pandas==1.1.4 -dgl-cu111 +mlflow==1.23.1 +pandas==1.4.3 +tables +einops==0.4.0 +opt-einsum==3.3.0 +pykeops==1.5 +gdown==4.7.1 +xgboost==1.7.3 +wandb diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/checkpoint_utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/checkpoint_utils.py index d082858f8..d725f47f9 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/checkpoint_utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/checkpoint_utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,9 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +import sys import os import json import shutil +import atexit import dllogger import torch @@ -23,8 +25,6 @@ from hydra.utils import get_original_cwd from omegaconf import OmegaConf -from loggers.log_helper import restart_logger - def save_checkpoint(trainer, filename="checkpoint.zip", checkpoint_dir="."): if trainer.ema: @@ -38,9 +38,13 @@ def save_checkpoint(trainer, filename="checkpoint.zip", checkpoint_dir="."): "global_step": trainer.global_step, "model_state_dict": module_to_save.state_dict(), "optimizer_state_dict": trainer.optimizer.state_dict(), + "scheduler_state_dict": trainer.scheduler.state_dict() if trainer.scheduler is not None else None } checkpoint_path = os.path.join(checkpoint_dir, filename) - trainer.logger.log(step='event', data={"String": f"Saving checkpoint to {filename}"}, verbosity=dllogger.Verbosity.DEFAULT) + trainer.logger.log(step='event', + data={"String": f"Saving checkpoint to {filename}"}, + verbosity=dllogger.Verbosity.DEFAULT + ) torch.save(state, checkpoint_path) @@ -54,6 +58,8 @@ def maybe_restore_checkpoint(trainer, checkpoint_path): checkpoint = torch.load(checkpoint_path, map_location=trainer.device) trainer.model.load_state_dict(checkpoint["model_state_dict"]) trainer.optimizer.load_state_dict(checkpoint["optimizer_state_dict"]) + if checkpoint["scheduler_state_dict"]: + trainer.scheduler.load_state_dict(checkpoint["scheduler_state_dict"]) trainer.global_step = checkpoint["global_step"] trainer.epoch = checkpoint["epoch"] @@ -92,6 +98,7 @@ def detect_duplicated_run(): rel = os.path.relpath(os.getcwd(), get_original_cwd()) rel = next(x for x in rel.split(os.path.sep)) result_dir = os.path.join(get_original_cwd(), rel) + print(f'Looking for a training to resume in {result_dir}', file=sys.stderr) duplicated = [] for p, s, f in os.walk(result_dir): @@ -101,7 +108,7 @@ def detect_duplicated_run(): duplicated.append(p) # Don't take into account runs that ended before any checkpoint had been saved # or current run (at this point hydra's config has already been saved) - duplicated = [p for p in duplicated if os.path.exists(os.path.join(p,'last_checkpoint.zip'))] + duplicated = [p for p in duplicated if os.path.exists(os.path.join(p, 'last_checkpoint.zip'))] return duplicated @@ -123,17 +130,30 @@ def maybe_continue_run(trainer): if not duplicates: return - logfile_name = trainer.config.get('logfile_name', 'log.json') - unfinished_run_path = get_most_advanced_run(duplicates, logfile_name) - checkpoint_path = os.path.join(unfinished_run_path, 'last_checkpoint.zip') - best_checkpoint_path = os.path.join(unfinished_run_path, 'best_checkpoint.zip') - maybe_restore_checkpoint(trainer, checkpoint_path) - log_lines = trim_json_log(os.path.join(unfinished_run_path, logfile_name)) - - # Reinitialize the logger. This will cause it to append to the copied log file. - with open(logfile_name, 'w') as f: - f.writelines(log_lines) - trainer.logger = restart_logger(trainer.config, trainer.logger) + # Restart only JSON backend, because the rest either produce only output on stdout or are 3rd party that are hard to configure + if json_backend := next((x for x in trainer.logger.backends if isinstance(x, dllogger.JSONStreamBackend)), None): + logfile_name = json_backend._filename + unfinished_run_path = get_most_advanced_run(duplicates, logfile_name) + checkpoint_path = os.path.join(unfinished_run_path, 'last_checkpoint.zip') + best_checkpoint_path = os.path.join(unfinished_run_path, 'best_checkpoint.zip') + maybe_restore_checkpoint(trainer, checkpoint_path) + log_lines = trim_json_log(os.path.join(unfinished_run_path, logfile_name)) + with open(logfile_name, 'w') as f: + f.writelines(log_lines) + + # Reinitialize the backend + json_backend.file.close() + # In the regular (not resumed) case, the backend is created before a logger, which means, that its atexit handler is called after + # logger's atexit call. Creating new backend we place its atexit call after the logger's one which means that it would be executed earlier. + # This in turn closes the file. Then logger's call is executed trying to flush into the closed file and in result raising the exception. + # We have no direct control over the order of atexit callback list, so we remove both calls and place them back in the correct order. + atexit.unregister(trainer.logger.flush) + atexit.unregister(json_backend.file.close) + new_backend = dllogger.JSONStreamBackend(verbosity=json_backend._verbosity, filename=json_backend._filename, append=True) + atexit.register(trainer.logger.flush) + trainer.logger.backends[trainer.logger.backends.index(json_backend)] = new_backend + del json_backend + trainer.logger.log( step='event', data={"String": f"Resuming run: {unfinished_run_path}"}, diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/ema.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/ema.py index 9fb23a3e0..00ad431b0 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/ema.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/ema.py @@ -1,4 +1,4 @@ -# Copyright 2021-2022 NVIDIA Corporation +# Copyright 2021-2024 NVIDIA Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/trainer.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/trainer.py index 1aaec08a4..d64daf555 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/trainer.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/trainer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,16 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import importlib import os +import time from abc import ABC -import dgl import dllogger -import hydra import numpy as np import torch import torch.nn as nn -import importlib +import hydra try: from apex import amp except ImportError: @@ -31,12 +31,11 @@ from torch.utils.data import DataLoader, DistributedSampler from callbacks.ctl_callbacks import CTLCallbackContainer -from data.datasets import TSBaseDataset, get_collate_fn -from distributed_utils import reduce_tensor, get_mp_context -from loggers.log_helper import setup_logger -from training.ema import ModelEmaV2 from criterion import TSPP_criterion_wrapper +from data.datasets import TSBaseDataset, get_collate_fn +from distributed_utils import get_mp_context, reduce_tensor from training.checkpoint_utils import maybe_continue_run +from training.ema import ModelEmaV2 from training.utils import to_device @@ -54,7 +53,9 @@ def __init__( optimizer, criterion, callbacks, + logger, config, + scheduler=None, ): self.config = config self._stop_training = False @@ -77,16 +78,22 @@ def __init__( self.encoder_length = config.encoder_length if self.world_size > 1: - # XXX: is the seed argument here needed for reproducibility? - # It should be set in launch_training.py with other seeds self.train_sampler = DistributedSampler( train_dataset, self.world_size, seed=config.get("seed", 1), drop_last=True ) self.valid_sampler = DistributedSampler( valid_dataset, self.world_size, seed=config.get("seed", 1), drop_last=False ) - self.logger = setup_logger(self.config) + self.logger = logger self.optimizer = optimizer + + if scheduler is not None: + scheduler._target_ = scheduler.target + del scheduler.target + self.scheduler = hydra.utils.instantiate(scheduler, optimizer=optimizer) + else: + self.scheduler = None + self.amp_enabled = self.config.get("amp", False) if not importlib.util.find_spec("apex"): self.amp_enabled = False @@ -97,17 +104,7 @@ def __init__( if not self.config.get('force_rerun'): maybe_continue_run(self) - if config.get("ema", False): - self.ema = ModelEmaV2(model, decay=self.config.get('ema_decay', 0.999), device=self.device) - else: - self.ema = None - if self.amp_enabled: - self.model, self.optimizer = amp.initialize(self.model, self.optimizer, opt_level="O2", loss_scale="dynamic") - if self.world_size > 1: - self.model = DDP(self.model, device_ids=[self.local_rank], output_device=self.local_rank, find_unused_parameters=True) - - mp_context = get_mp_context() - + mp_context = get_mp_context() if self.config.num_workers else None self.train_dataloader = DataLoader( train_dataset, batch_size=self.config.batch_size, @@ -128,13 +125,22 @@ def __init__( multiprocessing_context=mp_context ) - # TODO: make it reccursively instantiated - if self.config.get("scheduler", None): - self.config.scheduler._target_ = self.config.scheduler.target - del self.config.scheduler.target - self.scheduler = hydra.utils.instantiate(self.config.scheduler, optimizer) + # Before calling copy on model parameters we want to be sure that they are defined. Regards lazy modules + dummy_batch, dummy_labels, dummy_weights = next(iter(self.train_dataloader)) + dummy_batch, _, _ = self.prep_data(dummy_batch, dummy_labels, dummy_weights) + self.model(dummy_batch) + + if config.get("ema", False): + self.ema = ModelEmaV2(model, decay=self.config.get('ema_decay', 0.999), device=self.device) else: - self.scheduler = None + self.ema = None + if self.amp_enabled: + self.model, self.optimizer = amp.initialize(self.model, self.optimizer, opt_level="O2", loss_scale="dynamic") + if self.world_size > 1: + self.model = DDP(self.model, + device_ids=[self.local_rank], + output_device=self.local_rank, + find_unused_parameters=True) cl_start_horizon = config.get("cl_start_horizon") cl_update = config.get("cl_update") @@ -173,8 +179,8 @@ def validate(self): running_losses = running_losses.unsqueeze(0) running_losses = [loss.item() for loss in running_losses] data = {"val_loss": sum(running_losses)} - for i, elem in enumerate(running_losses): - data["val_loss_component_" + str(i)] = elem + #for i, elem in enumerate(running_losses): + # data["val_loss_component_" + str(i)] = elem self.logger.log(step=self.global_step, data=data, verbosity=dllogger.Verbosity.VERBOSE) self.model.train() @@ -215,8 +221,6 @@ def train(self): losses = [losses] losses = [loss.item() for loss in losses] data = {"loss": loss.item()} - for k, v in enumerate(losses): - data["loss_component_" + str(k)] = v self.logger.log(step=self.global_step, data=data, verbosity=dllogger.Verbosity.VERBOSE) @@ -226,9 +230,13 @@ def train(self): self.global_step += 1 if self.scheduler: self.scheduler.step() + self.logger.log(step=self.global_step, + data={f'lr_{i}': x for i, x in enumerate(self.scheduler.get_last_lr())}, + verbosity=dllogger.Verbosity.VERBOSE + ) self.callbacks.on_valid_begin(self.epoch) validation_loss = self.validate() - if validation_loss != validation_loss: #NaN check + if validation_loss != validation_loss: # NaN check self._stop_training = True data = {"val_loss": validation_loss} self.callbacks.on_valid_end(self.epoch, logs=data) @@ -246,44 +254,91 @@ def train(self): self.callbacks.on_train_end(logs=self.metrics) +def _get_continious_bound_iterator(): + _get_continious_bound_iterator.i = 0 + def inner(dataset, id): + while _get_continious_bound_iterator.i < len(dataset) and dataset[_get_continious_bound_iterator.i]['id'] == id: + yield dataset[_get_continious_bound_iterator.i] + _get_continious_bound_iterator.i += 1 + return inner + + class StatTrainer(Trainer): + '''This trainer fits statistical models with a single time serie at a time. + If `input_length` is specified in dataset, model will training only on last `input_lengs` observations, + otherwise whole series will be used. + ''' def __init__(self, config, model, train_dataset, - valid_dataset + valid_dataset, + logger, + evaluator, ): self.config = config self.train_dataset = train_dataset + self.valid_dataset = valid_dataset self.global_step = 0 self.epoch = 0 self.model = model - self.logger = setup_logger(self.config) + self.logger = logger + self.evaluator = evaluator + self.log_interval = self.config.get('log_interval', 25) def train(self): - for train_batch in self.train_dataset: - self.model.fit(train_batch["endog"], train_batch["exog"]) - + bound_iterator = _get_continious_bound_iterator() + + total_steps = len(self.train_dataset) + prev_timestemp = time.time() + time_running_avarage = 0 + predictions_dict = {} + for step_id, train_example in enumerate(self.train_dataset): + self.model.fit(train_example) + next_timestemp = time.time() + + if time_running_avarage == 0: + time_running_avarage = (next_timestemp - prev_timestemp) + else: + time_running_avarage = time_running_avarage * 0.9 + (next_timestemp - prev_timestemp) * 0.1 + prev_timestemp = next_timestemp + if (step_id + 1) % self.log_interval == 0: + self.logger.log(step=step_id, data={'steps:': f'{step_id+1} / {total_steps}', 's/iter': time_running_avarage}, verbosity=dllogger.Verbosity.DEFAULT) + self.logger.flush() + + evaluation_timer = time.time() + preds = self.evaluator.predict(self.model, dataloader=bound_iterator(self.valid_dataset, train_example['id'])) + if predictions_dict: + for k in predictions_dict: + predictions_dict[k] = np.concatenate((predictions_dict[k], preds[k])) + else: + predictions_dict = preds + + if (step_id + 1) % self.log_interval == 0: + self.logger.log(step=step_id, data={'log': f'Evaluation finished in {time.time() - evaluation_timer}s'}, verbosity=dllogger.Verbosity.DEFAULT) + self.logger.flush() self.model.save() + return predictions_dict def validate(self): raise RuntimeError("Validation is not supported for StatTrainer") class XGBTrainer(Trainer): - def __init__(self, config, callbacks, model, train_dataset, valid_dataset): + def __init__(self, config, callbacks, model, train_dataset, valid_dataset, logger): ''' - The idea behind this trainer is that we are given data at a time step t and want to create models to predict the value of a target - from t+1 to t+n. At time step t we have access to every feature including the target, and if we are trying to predict at time step - t+i, we have access to the known and static values from there, using the function target_shift. To aid in prediction and - give the model access to the history, lag and moving features can be specified in the configs. - Lag features can either be specifed by a min value and max value or a list of values. If a min and max - value are specified then the range(min, max+1) is used as the list. Moving average (or rolling features) are specified - by a window size. These values are added with the feat_adder function. A new model is trained for every step we want - to predict. The trainer is not recursive so each model is independent and does not rely on the previous trained models. + The idea behind this trainer is that we are given data at a time step t and want to create models to predict + the value of a target from t+1 to t+n. At time step t we have access to every feature including the target, + and if we are trying to predict at time step t+i, we have access to the known and static values from there, + using the function target_shift. To aid in prediction and give the model access to the history, lag and moving + features can be specified in the configs. Lag features can either be specifed by a min value and max value + or a list of values. If a min and max value are specified then the range(min, max+1) is used as the list. + Moving average (or rolling features) are specified by a window size. These values are added with the feat_adder function. + A new model is trained for every step we want to predict. The trainer is not recursive so each model is + independent and does not rely on the previous trained models. ''' self.config = config - self.logger = setup_logger(config) + self.logger = logger self.train_dataset = train_dataset self.valid_dataset = valid_dataset self.patience = callbacks.early_stopping.patience @@ -296,4 +351,3 @@ def train(self): patience=self.patience, log_interval=self.log_interval) self.model.save(os.getcwd()) - diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/utils.py index 9bac22c9c..fb4c6c5f1 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/training/utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/training/utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# SPDX-License-Identifier: Apache-2.0 import dgl import torch import numpy as np @@ -29,7 +30,7 @@ def to_device(batch, device=None): if isinstance(batch, torch.Tensor): return batch.to(device=device) if isinstance(batch, dict): - return {k: t.to(device=device) if t.numel() else None for k, t in batch.items()} + return {k: t.to(device=device) if t is not None and t.numel() else None for k, t in batch.items()} if isinstance(batch, dgl.DGLGraph): return batch.to(device=device) elif batch is None: @@ -47,7 +48,10 @@ def set_seed(seed): def get_optimization_objectives(config, metrics): - objectives = tuple(v if v == v else float('inf') for k,v in metrics.items() if k in config.get('optuna_objectives', [])) + objectives = tuple(v if v == v and v < 2.0**15 else 2.0**15 + for k, v in metrics.items() + if k in config.get('optuna_objectives', []) + ) if len(objectives) == 1: return objectives[0] elif not objectives: diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/calculate_metrics.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/calculate_metrics.py index 873563c69..fddb19ec1 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/calculate_metrics.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/calculate_metrics.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/check_accuracy.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/check_accuracy.py index a935ca39c..811d1dc66 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/check_accuracy.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/check_accuracy.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/dataloader.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/dataloader.py index 65821b659..e428b351d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/dataloader.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/dataloader.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/__init__.py index a528aa86d..8ad3be9f6 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/__init__.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/args.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/args.py index 187e31c69..f6876b80f 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/args.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/args.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/__init__.py index e69de29bb..8ad3be9f6 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/__init__.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. \ No newline at end of file diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/onnx.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/onnx.py index 9108f34d1..2b93b9f06 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/onnx.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/onnx.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/pyt.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/pyt.py index 2d3e3a67c..983e3443d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/pyt.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/pyt.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -161,6 +161,8 @@ def load(self, model_path: Union[str, Path], **kwargs) -> Model: def _trace(self, model: Model, dataloader_fn) -> Model: device = get_model_device(model.handle) dummy_input = get_sample_input(dataloader_fn(), device) + # Run dummy forward to initialize lazy modules + model.handle(*dummy_input) traced_model = torch.jit.trace_module(model.handle, {"forward": dummy_input}) return Model(traced_model, precision=model.precision, inputs=model.inputs, outputs=model.outputs) diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/utils.py index 72d4f7d0f..686f37a8f 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/bermuda/utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/core.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/core.py index 0109bd921..c65617fce 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/core.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/core.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/dump.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/dump.py index f714c5515..9090f1f92 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/dump.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/dump.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/extensions.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/extensions.py index ff45fbde0..c328b64f1 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/extensions.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/extensions.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/__init__.py index 1c9a31379..4d3bf2cf6 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/__init__.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/exceptions.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/exceptions.py index 52c852b31..8947a98e3 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/exceptions.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/exceptions.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/model_analyzer_config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/model_analyzer_config.py index fed6b32a1..21dbb9656 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/model_analyzer_config.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/model_analyzer/model_analyzer_config.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/__init__.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/__init__.py index c96f9a06c..e1dfc06ed 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/__init__.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_analyzer.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_analyzer.py index 9b3f253bd..193619be4 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_analyzer.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_analyzer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_config.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_config.py index 5506d0ccd..39d363a58 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_config.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/perf_analyzer/perf_config.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/report.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/report.py index 53cc8016e..0e53e437a 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/report.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/report.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/utils.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/utils.py index 2fcb27ddf..c1a1a6f36 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/utils.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/warmup.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/warmup.py index 5e2a55b10..27ff34eb0 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/warmup.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/deployment_toolkit/warmup.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/export_model.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/export_model.py index 12aeaf96c..175da1ab6 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/export_model.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/export_model.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/metrics.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/metrics.py index 10a95a580..f2a931402 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/metrics.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/metrics.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -25,10 +25,6 @@ def update_argparser(parser): parser.add_argument("--model-dir", type=str, help="Path to the model directory you would like to use (likely in outputs)", required=True) - - - - class MetricsCalculator(BaseMetricsCalculator): def __init__(self, model_dir): with open(os.path.join(model_dir, ".hydra/config_merged.yaml"), "rb") as f: @@ -60,11 +56,8 @@ def update( x, y_real, ): - #can probably just pass all of this to the evaluator main class self.targets.append(y_real['target__0'][:,:,0][:,:,np.newaxis]) self.ids.append(ids) self.weights.append(x["weight__9"]) preds = y_pred["target__0"] self.predictions.append(preds) - - # return self.metrics diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/model.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/model.py index bf6c5ac47..b42ef28dc 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/model.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/model.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/requirements.txt b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/requirements.txt index 670189097..d7a2cd4dd 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/requirements.txt +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/requirements.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,4 +21,3 @@ pycuda>=2019.1.2 PyYAML>=5.2 tabulate>=0.8.7 tqdm>=4.44.1 -polygraphy==0.36.2 diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_fw.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_fw.py index 9d35268bd..ad33b1fc9 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_fw.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_fw.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_triton.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_triton.py index bb6d2a114..869774499 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_triton.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_inference_on_triton.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_performance_on_triton.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_performance_on_triton.py index cdaff5ee4..9c9526331 100755 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_performance_on_triton.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/run_performance_on_triton.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/xgboost_triton.py b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/xgboost_triton.py index 72f9b24e2..d68e2379d 100644 --- a/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/xgboost_triton.py +++ b/Tools/PyTorch/TimeSeriesPredictionPlatform/triton/xgboost_triton.py @@ -7,7 +7,7 @@ import xgboost as xgb import hydra import subprocess -from loggers.log_helper import setup_logger + def generate_config( model_name, *, @@ -62,7 +62,6 @@ def generate_config( def format_checkpoint(ckpt, total_features, max_batch_size): main_output_path = ckpt - #TODO hardcoded the num features #make deployment checkpoint_path = os.path.join(main_output_path, 'checkpoints') #make navigator_workspace diff --git a/hubconf.py b/hubconf.py index af430e207..923bff539 100644 --- a/hubconf.py +++ b/hubconf.py @@ -24,3 +24,11 @@ from PyTorch.SpeechSynthesis.Tacotron2.tacotron2 import nvidia_tts_utils from PyTorch.SpeechSynthesis.Tacotron2.waveglow import nvidia_waveglow sys.path.append(os.path.join(sys.path[0], 'PyTorch/SpeechSynthesis/Tacotron2')) + +from PyTorch.SpeechSynthesis.HiFiGAN.fastpitch import nvidia_fastpitch +from PyTorch.SpeechSynthesis.HiFiGAN.fastpitch import nvidia_textprocessing_utils +from PyTorch.SpeechSynthesis.HiFiGAN.hifigan import nvidia_hifigan +sys.path.append(os.path.join(sys.path[0], 'PyTorch/SpeechSynthesis/HiFiGAN')) + +from PyTorch.Forecasting.TFT.tft_torchhub import nvidia_tft, nvidia_tft_data_utils +sys.path.append(os.path.join(sys.path[0], 'PyTorch/Forecasting/TFT'))